Handling business error w/o relying on exceptions, is it possible (and a good idea)?

Hi all!
I’m new to Axon (and to event sourcing…and to CQRS…at least in practice, even if I’ve known the concept since a long time)…so be patient :sweat_smile:.
I’m trying to understand if it would be possible (and a "good’ idea, I mean…no bad side effects / risks) to deal with business errors without relying on exceptions but with some “functional like” solution like Result/Either (just in case any of you doesn’t know what this is about, basically just return an object encapsulating the error details instead of throwing an exception).
It seem to me that for standard command handlers it’s not a problem, they have a return value.
The main issue I see it the @CommandHandler constructor.
I tried with a @CommandHandler static factory method but I was not able to return the Result (static @CommandHandler methods must declare a return value which is equal to or a subclass of the declaring type).
Any comment/suggestion welcome :slight_smile:

Hi there Luca!

It is definitely possible, If it’s important in your domain to preserve information regarding errors (and perhaps the reject reason) I would personally apply an event stating that the action failed. This can be handled in a projection, or saved for later use.

If that’s not an option, and you want to avoid exceptions, you can return a result from your constructor. Take a look at the @CreationPolicy annotation. You can define a normal @CommandHandler with a policy of @CreationPolicy(AggregateCreationPolicy.ALWAYS), effectively turning into a constructor.
You can find it in the reference guide in this location.

If you want to do this, do know that Axon Framework actually converts exceptions thrown in the aggregate into an exceptional CommandResultMessage. This is something you can handle in the CompletableFuture that is returned by the send method of the CommandGateway. You could also handle the exceptions there, or wrap it in a result using your own CommandGateway implementation

The only major downside I can think of is that you lose the ability for quickly asserting something, like this the following snippet:

Assert.isTrue(roomIsPrepared(), String.format("Room %s is not prepared", roomNumber));

It all comes down to preference! I hope this helped you, let me know if there are more questions.

Mitchell

Thank you Mitchell, you definitely gave me some useful information, I’ll play a bit with it!
I also find very interesting the consideration about preserving information on errors trough events…I’m quite new to real event driven designs so did not think about it.

thank you again!

Hi Luca,

A colleague pointed out that the following example code regarding distributed error handling might also come in handy. So I just wanted to add this to the answer.

It describes how to handle exceptions well in an Event-Sourcing system, especially if it’s distributed over multiple applications (which might have an advanced classpath). It might still be a bit over the top for you now, but might be valuable in the future. Good luck :slight_smile:

Hi Luca,

as Mitchell aready mentioned, from functional view you are free to chose. My personal flavor is to use exceptions to carry business related problems to caller, thus you can separate the actual command results (if any needed) from the infomation whether something in business logic is complaining. Take as an example create or update commands which actually need no returning results. Using exceptions would drop the need of returning any results from these commands which (I feel) keeps the code clean and lean.

I made some experiment but still I am not able to accomplish what I want…but probably for a good reason: w/o exceptions, how can Axon know if the creation of the aggregate was a success (or a failure)?
E.g right now in case of failure creating the aggregate (and me returning an object representing the error instead of the exception), axon complains because I did not set the aggregate identifier. It makes sense I guess…
What do you think?