How to handle exceptions and translate them to HTTP status codes?

Hey everyone,

I am working on a small event-sourced proof-of-concept using Spring Boot and Axon Framework to compare it to a more traditional way of working with Spring Boot.

A request comes in via a Spring Boot controller, which then sends a command or query over Axon’s command gateway or query gateway. These both work with CompletableFuture. How do I handle errors and convert them to the appropriate HTTP status code?

I am used to converting custom core exceptions (i.e. ActionNotAllowed or ResourceNotFound) to their respective HTTP status code by catching it and throwing a ResponseStatusException. I haven’t used CompletableFuture before in this context. What would be a good way to go about this and still keep my application’s core presentation-agnostic?

Thanks!

Hi Alex,

instead of using try-catch, which is an imperative programming style, you can use the completableFuture.exceptionally() or completableFuture.exceptionallyCompose() methods to translate exceptions from a CompletableFuture to another type of response.

Note that the first allows you to map an exception to a “regular” response, which would be useful if you use Spring’s ResponseEntity. If you wish to map an exceptionally completed CompletableFuture to one that is exceptionally completed with a different exception, the second one is more flexible as you can return any new CompletableFuture you wish.

StackOverflow also suggests an approach to map one exception to another one: java - Map exception in completable future to a different exception type? - Stack Overflow

Hope this answers your question.

1 Like

Hi @arothuis,

Added to what @allardbz suggested above, this code-sample might give you some ideas on how to do it!

KR,

1 Like

I’ll check out these options, thanks a lot!

Hi Alex,

we have a quite similar setup and what we usually do in the REST controller is using the org.axonframework.commandhandling.gateway.CommandGateway#sendAndWait() variant of the command gateway to send a command and synchronousy wait for the command to complete or throw an exception. We have a central class containing spring web exception handlers for all known exceptions to expect (see Web on Servlet Stack) that transforms an exception into a ResponseEntity with the appropriate status code. Since we’re using Axon Server to distribute command handling we implemented a MessageHandlerInterceptor that allows forwarding exception details from remote command handler to the controller (also see this thread: Get the entire stack trace fpr remote command handlers)

If you would use the org.axonframework.commandhandling.gateway.CommandGateway#send() variant of the command gateway to send the commands in your controller, you would need to block until the completeable future completes to get the exceptional result as described by @allardbz or e.g. return a HTTP 202 accepted response status code to indicate only that the command is submitted (allowing the outcome to be queried with a separate request on the query side).

1 Like

Hi Jakob,

Thanks for the tips!

Using your @allardbz and @lfgcampos’ suggestions, I am now working on wrapping my custom exceptions in exceptions that AxonIQ understands. This is where a MessageInterceptor will come in handy.

If you would use the org.axonframework.commandhandling.gateway.CommandGateway#send() variant of the command gateway to send the commands in your controller, you would need to block until the completeable future completes

Actually, Spring supports CompletableFuture as a return type for controller methods, and will switch to Async mode to return the response to the client. No need for any blocking

2 Likes

I typically would just use the sendAndWait method as has been said already in the thread because it lets you write synchronous and (arguably) more readable code.

Just to add - with Project Loom around the corner the performance of sendAndWait will not neccesarily be worse than the asynchronous alternative and so the potential performance impact of a synchronous approach may be gone in a future Java + Spring + Axon version.

1 Like

I’ll look into sendAndWait! Is something like this also available for the QueryGateway?

You can see the available methods on the query gateway on the published javadoc here: QueryGateway (Axon Framework 4.5.8 API)

It seems like there is no queryAndWait equivalent.

But you could always just call get() on the CompletableFuture<R> which is returned. It is annoying you might have to deal with a checked exception, but it is still totally workable.