quarkus: Setup reactive and blocking and non-blocking routes the same way
I a using Quarkus and reading about it, and to my understanding, it seems to favor non-blocking code over blocking code. In light of that, it seems weird that creating a blocking http endpoint is much simpler than a reactive route.
This is an example: https://github.com/oscarfh/code-with-quarkus-reactive-routes This project has a simple edpoint that, given a string passed as query parameter, you get a “user” object with the string as its name. If you send the name “fail”, you will get a 400 back.
To create the blocking endpoint, all I have to do for blocking code is:
@GET
@Produces(MediaType.APPLICATION_JSON)
public User hello(@QueryParam("name") String name) {
return service.createUser(name);
}
And to map my exception to an HTTP response:
@Provider
public class MyExceptionHandler implements ExceptionMapper<MyCustomException>
{
@Override
public Response toResponse(MyCustomException exception)
{
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
I got it covered in 2 “real” lines of code (the rest is boilerplate), and it took me something like 10 minutes.
This is the code for a similar non-blocking behavior:
@Route(path = "/reactive-hello", methods = HttpMethod.GET)
void greetings(RoutingExchange ex) {
String name = ex.getParam("name").get();
ObjectMapper objectMapper = new ObjectMapper();
service.rxCreateUser(name)
.onItem().apply(user -> {
try {
return objectMapper.writeValueAsString(user);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
})
.onItem().invoke(userAsString -> {
ex.response().putHeader("Content-type", MediaType.APPLICATION_JSON);
ex.ok(userAsString);
})
.subscribe().with(s -> ex.response().close(),
throwable -> {
if (throwable instanceof MyCustomException) {
ex.response().setStatusCode(400).setStatusMessage("BAD REQUEST").end();
} else {
ex.response().setStatusCode(500).setStatusMessage("INTERNAL SERVER ERROR").end();
}
});
}
(I have inlined everything, so it is easier to see the difference. The format is the standard format in my Intellij - for some reason it is called “Quarkus IDE”) One extra point is that in the blocking variant, all exceptions will map to a 404, while this is not provided in the non-blocking version.
It would be great if both variants were virtually identical when setting things up and offered the same type of resources (exception mapping, for instance).
This seems to be possible: there is another framework that will decide based on the return type whether the code is blocking or not and act accordingly. Would that be possible in Quarkus?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 3
- Comments: 20 (11 by maintainers)
@mkouba I have changed the application to use reactive routes only, now the failure route is being detected, but now when i return any response entity I get a bunch of attributes that I dont need: and the response code in swagger is always 200, even if the “status” attribute in the response body is otherwise
However what i want to receive is something like this, which is what i normally receive without reactive routes:
Yes, it would be a nice addition.
Note that… this part is generated in bytecode. So be warned, it can be a spicy experience: https://github.com/quarkusio/quarkus/blob/master/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java#L716-L723
Exception handling (whether your Uni produced a failure or if the method throws an exception) would produce a 500 response (using the routing context
failmethod).If you register a route of type
FAILUREthen you can handle the failure and produce the response you want.We have improved the reactive routes UX recently. If your
servicereturns a Mutiny type, you should be able to do somethign like (in the master branch):I’m not sure about the exception handling though… Maybe @cescoffier has some idea?