Jobrunr: How to add custom filters for job? - kotlin

I am trying to integrate jobrunr 5.1.6 to my micronaut application. I am unable to get the filter implementing ApplyStateFilter triggered when the job is processed. Please see below:
class JobCompletionFilter : ApplyStateFilter {
override fun onStateApplied(job: Job?, oldState: JobState?, newState: JobState?) {
if (newState != null) {
if (isFailed(newState) && maxAmountOfRetriesReached(job)) {
// Failed after retry. Add logs and handle strategy logic
} else if (newState is SucceededState) {
// Job succeeded. Add job completion logic
}
}
}
How do I inject this filter for all of my jobs? Below is how I am enqueueing the jobs
#Inject
lateinit var jobScheduler: JobScheduler
jobScheduler.enqueue {jobProcessor.execute(job)}

In the free version, you will have to manually configure JobRunr via the Fluent Java API instead of using the Spring integration. There, you have the possibility to pass the filter. An example:
JobRunr
.configure()
.withJobFilter(...) // pass your job filters here
For more info, see the fluent API.
In the Pro version, any Job Filter which is a Spring Bean (e.g. an #Component or #Service) will automatically be executed without any additional configuration. For more info, see the docs.

Related

How to list configured routes in Ktor

I am setting up a project with multiple modules that contain different versions of api.
To verify correct route configuration I would like to print configured routes to application log like it is done in spring framework.
Is it possible and what should I use for that?
You can do it by recursively traversing routes starting from the root all the way down the tree and filtering in only ones with the HTTP method selector. This solution is described here.
fun Application.module() {
// routing configuration goes here
val root = feature(Routing)
val allRoutes = allRoutes(root)
val allRoutesWithMethod = allRoutes.filter { it.selector is HttpMethodRouteSelector }
allRoutesWithMethod.forEach {
println("route: $it")
}
}
fun allRoutes(root: Route): List<Route> {
return listOf(root) + root.children.flatMap { allRoutes(it) }
}
Please note that the code above must be placed after the routing configuration.

Hangfire.Console logging not displayed in Dashboard

I've been using Hangfire for ages, but only recently discovered you can use Hangfire.Console to output logging, which can be seen in the Hangfire Dashboard.
I've seen it work on someone else's project, but when adding logging to my own project, I cannot make it work.
This is the gist of the task.
I checked with Debugger that all lines are executed and the job does finish successfully.
public async Task MethodName(PerformContext context)
{
var result = await apiClient.MethodName();
if (result != null)
{
context.SetTextColor(ConsoleTextColor.Green);
context.WriteLine($"Checked: {result.Checked}");
context.WriteLine($"Cleared: {result.Cleared}");
}
else
{
context.SetTextColor(ConsoleTextColor.Red);
context.WriteLine($"No result ...");
}
}
I expected to find the output in my Hangfire dashboard, but it shows no logging whatsoever. Is there a crucial step I am missing?
Using Hangfire 1.7.18 and Hangfire.Console 1.4.2

Quarkus Vert.x Example

I want to test Quarkus and the native image for Docker with an existing project written in Kotlin and using Vert.x verticles.
Can you point me to an example on how to deploy verticles using Quarkus?
My dependencies are vertx-sockjs-service-proxy and vertx-lang-kotlin.
I found some examples in the Vert.x extension tests but I cannot find how to deploy my verticles at server startup.
#Inject
EventBus eventBus;
#Route(path = "/hello-event-bus", methods = GET)
void helloEventBus (RoutingExchange exchange){
eventBus.send("hello", exchange.getParam("name").orElse("missing"), ar -> {
if (ar.succeeded()) {
exchange.ok(ar.result().body().toString());
} else {
exchange.serverError().end(ar.cause().getMessage());
}
});
}
You can use verticle as follows:
#Inject Vertx vertx;
void onStart(#Observes StartupEvent ev) {
vertx.deploy(new MyVerticleA());
vertx.deploy(new MyVerticleB());
}

how can webflux handle global error, like 404 page not found

i use #restcontrolleradvice and #ExceptionHandler , but i can handle controller exception. server error like 404, 500 can't handle.
#RestControllerAdvice
public class HttpExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(HttpExceptionHandler.class);
#ExceptionHandler(value = Exception.class)
public String exceptions(Exception e) {
String code = Global.ERR_UNKNOWN;
if (e instanceof MethodNotAllowedException) {
code = Global.ERR_HTTP_METHOD;
}
return code;
}
}
If you're using Spring Boot, this is already done for you and you can customize this support as well quite easily (see Spring Boot reference docs).
If you're using plain Spring Framework, then you need to register a custom WebExceptionHandler bean to handle that (see Spring Framework reference docs). Because those errors can happen at any point during request handling (i.e. not only during the controller handling phase, but also during response encoding, within a WebFilter...), the API there is quite low level and you need to deal with raw DataBuffer instances. If you're looking for inspiration on how to achieve higher level error handling support, you can also take a look at what's done in Spring Boot.

Swagger for Kotlin

Has anyone used a swagger tool with Kotlin?
In our organization, we have create most of our REST services using Java and SpringMVC (#RestController classes). We have used springfox to generate the Swagger API documentation. The swagger JSON representation is also used to automatically feed a searchable service catalog, so the swagger format for service metadata is important to us.
Some dev teams are now beginning to use Kotlin. We're looking for recommendations or comments related to using springfox or other swagger lib with Kotlin.
Here is sample spring boot app with swagger:
#RestController
class MyController {
#ApiOperation(value = "doc header...", notes = "detailed doc...")
#RequestMapping(value = "/double", method = arrayOf(RequestMethod.GET))
fun doubleValue(number: Int) = 2 * number
}
#Configuration
#EnableSwagger2
class SwaggerConfig {
#Bean
fun api(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
}
}
dependencies are
compile("io.springfox:springfox-swagger2:2.7.0")
compile("io.springfox:springfox-swagger-ui:2.7.0")
If you browse http://localhost:8080/swagger-ui.html it is all there...
I recently had a similar requirement. As a result I created a template project that integrates Kotlin, Webflux, and Swagger. It provides interactive API doc and automatic request validation.
See here -> https://github.com/cdimascio/kotlin-swagger-spring-functional-template
Validation is functional. It's used as such:
validate.request(req) {
// Do stuff e.g. return a list of names
ok().body(Mono.just(listOf("carmine", "alex", "eliana")))
}
with body
validate.request(req).withBody(User::class.java) { body ->
// Note that body is deserialized as User!
// Now you can do stuff.
// For example, lets echo the request as the response
ok().body(Mono.just(body))
}
It utilizes openapi 2 and 3 validation provided by atlassian.