Best practices in error handling

Hello, all.

I was wondering how you are going about error handling and what some established best-practices are.

The early Axon Versions distinguished between different types of events. Now ists pretty much just one type.

Lets say I have an aggregate A, which handles command C.

Upon receiving the command C detects that the parameters given in C imply that this is an illegal action.

Overall, it would be simple to just apply(new ErrorEvent()). This would make it easy to handle the error in event listeners,
but it would persist the event in the event store.

I am currently torn between the ease of this and the resulting audit possibilities and the potential issues with accumulating
a lot of non-state changing events in the event store potentially costing a lot of storage (may result in a denial of service)
and harm aggregate load times.

Is it possible and meaningful to publish domain events which are not persisted by the aggregate ?

What are your thoughts on this from a “clean design” perspective?

Pragmatically I currently tend to just apply the error events and deal with any issues once this should become a problem in practice (“premature optimization is the root of all evil”, Knuth)

Thank you.

Dominic

Hi,

as always, it all depends…
In this case, how you want to handle the error depends on the value of that error in your domain. An Event is “a notification that something important happened”. That has nothing to do with a state change.
That these events are available to the aggregate when it is recreated should not prevent you from saving it. The aggregate can simply ignore it. In that case, the Serializers and Upcasters won’t be called. So there is a little bit of I/O overhead, but that will be neutralized by any snapshotting mechanism. I wouldn’t worry about it…

Note that it is still possible to store events that won’t be part of an Aggregate’s event stream. Simply inject the Event Bus in your Aggregate (or as a parameter to the Command Handler) and publish events on it. In Axon 3, these Events will respect ordering compared to those published using apply().

Cheers,

Allard

Hello, Allard,

thanks for clarifying. I think I will try out the injection of the event bus. Because this enables me to go for a consisten error handling model. I also have application/domain services which may publish error events. So the behaviour would be consisten with the ones published by the aggregate without persistence.
The alertnative to make it consistent would have been to select the appropriate aggregates and to apply the matching error events created by the domain service to them. That sounded much worse.

Just a side note, I am currently using Axon in teaching at an university in thesis work and work experiences with CS students.

Best regards,
Dominic

Good job teaching modern architectural styles to University Students! I hope one day I meet more people that just see the layered architecture as AN architectural style, instead of THE architectural style…
If you ever need a guest lecturer…

Most of them are just fixated on layered architectures and CRUD, but also in all kinds of research projects (senior) people still think they are doing good software engineering if they to some random n-tier architecture (because they have to do one …). sigh

Side note: Whats the go-to way to inject the EventBus or any other Bean into an Aggregate in 3.0 ? I simply can’t find it. Can my AggregateFactory extend/reuse a matching Sping-aware factory? Currently I extend the constructors and inject manually from my Factory.

If you use Spring and the @Aggregate annotation, your Aggregate basically becomes a Spring managed bean. However, this doesn’t completely work for the creation command, which just invokes a constructor. In that case, you can add your dependencies as a parameter in the constructor. Make sure the actual command is always the first parameter.

Note that this requires the use of @EnableAxon.

Cheers,

Allard

Good. Thank you.