I am building a monolith project using Axon framework.
I have a method here that dispatches an event
@CommandHandler
public void createRoom(CreateRoomCommand createRoomCommand){
log.info("Receiving create room command: {}",createRoomCommand);
ChatRoom chatRoom = new ChatRoom(
createRoomCommand.getRoomId(),
createRoomCommand.getName()
);
chatRoom.create();
List<DomainEvent> domainEvents = chatRoom.getDomainEvents();
domainEvents.forEach(domainEvent -> eventBus.publish(GenericEventMessage.asEventMessage(domainEvent)));
chatRoomRepository.save(chatRoom);
}
And this is my event handler that might throw an exception
@EventHandler
public void on(RoomCreatedEvent event){
//throw exception here
}
My question is, how should I handle the exception?
I thought of two things:
Should I dispatch an event from the event handler to reverse the transaction?
How do I make eventBus.publish synchronous so that they can fail as one transaction?
CodePudding user response:
When moving to an Event-Driven Architecture, what's important to note is that an Event Handling failure should never mean Event Publishing should fail too.
The benefit of this style of programming is the decoupling of these components. If you prefer the Event Handling task to roll back the Event Publishing task, you're not really benefitting from this separation.
I try to see events as follows. An event describes "something relevant that has happened." This makes it past-tense, differently put a fact, and thus history. You cannot revert history, as it's something from the past.
Hence as soon as an event is present, it is the handler's concern to deal with faulty scenarios. Who knows, maybe your handler deals with events from 10 years ago. You couldn't have such a handler tell the publisher (from 10 years ago!) that you're not happy with that event.
In more technical terms, the event consumer should deal with faulty scenarios. If you're curious how Axon Framework supports this, you can have a look at the Event Processor page. More specifically the Error Handling section.
To not just link documentation, you have two layers of error handling.
The first is called the ListenerInvocationErrorHandler
, which is invoked if your @EventHandler
annotated method throws an exception.
The second is called the ErrorHandler
, which is invoked for exceptions that move outside of a single event handler's scope.
I hope this clarifies things for you, @firepunch! Feel free to add comments underneath if I need to explain more.