Proposed async @CommandHandler exception handling

Hi all,

On the topic of set validation & business validations/exceptions thrown in @CommandHandler methods.
What are your proposed solutions for handling these exceptions? It would be great to use Spring AOP to “catch” these exceptions but AggregateRoots are not Spring managed. What are the alternatives? I am aware of pre-validation etc.

Cheers!

Hi Roscoe,

In general, the exception you raise should be handled by the component that sent the event. Using the CommandGateway mechanism, you can simply have these exceptions thrown in the thread that dispatched the command (causing that thread to wait for the command to finish). Alternatively, both when using CommandGateway or CommandBus directly, you can supply a callback and hadnle the exception in the onFailure() method.

If you have very generic actions to take, you can (since Axon 2.3) configure a CommandCallback on the GatewayProxyFactory directly. That callback is then invoked for all commands, regardless of their type.

Hope this helps.
Cheers,

Allard

Thanks Allard,

Downloading Axon 2.3 dependencies as we speak. Some great new features it seems, thank you.
My aggregate root constructor is as follows, I want to throw validation exceptions to ensure business invariants within the aggregate.
I believe Axon 2.3 GatewayProxyFactory’s CommandCallBack might be what I am looking for? My aim is to pipe these validation messages to a message queue/websocket.

Alternatively I thought of maybe throwing a validation event but this seems to leak the ensuring of business invariants into event handlers(I’d like to keep them within Aggregate Roots).

Your thoughts are greatly appreciated!

@CommandHandler
public UserAggregateRoot(RegisterUserCommand registerUserCommand, UserRepository userRepository) {

User userWithEmail = userRepository.userWithEmailAddress(new EmailAddress(registerUserCommand.getEmailAddress()));

if (userWithEmail != null) {
//apply(new UserEmailUnavailableEvent(userId.id()));
// throw new ValidationNotificationException(new ValidationException(“email”, “Email is unavailable”));
}

apply(new UserRegisteredEvent(new UserId(userRepository.newUserId().id(), registerUserCommand.getUsername(), registerUserCommand.getEmailAddress(),registerUserCommand.getPassword(), registerUserCommand.getFirstname(), registerUserCommand.getSurname()));

}

Sounds like the best solution for your case would be to throw an exception from the aggregate. In the end, you’re refusing to process the command. That will invoke the callbacks, allowing you to forward the exception to the client.
If sending it back to the client is generic, you can use the registerCommandCallback on the GatewayProxyFactory. Otherwise, you can simply use the standard DefaultCommandGateway.send(Object, CommandCallback); method.

Cheers,

Allard

Thanks a lot Allard. Just implemented Axon 2.3 and the CommandCallBack is is working as expected. YAY!