I recently started trying the JGroupsConnector to spread my application across multiple hosts. It mostly works out of the box which is great, but I did run into one problem that others might also run into and I figure I should describe how I fixed it. This is on Axon 2, but I suspect the same situation could happen on Axon 3 with subscribing event processors. (Maybe not with tracking processors, though.)
The problem manifests itself when you have saga code like
private void startSomeWork(CreateMyAggregateCommand command) {
associateWith("aggregateId", command.getAggregateId());
commandGateway.dispatch(command);
}
@SagaEventHandler(associationProperty="aggregateId")
public void on(MyAggregateCreatedEvent event) {
// do the next thing in the saga's workflow
}
This works fine most of the time, but occasionally, when the timing is just right, the following happens:
1. Saga on host A dispatches the creation command
2. Creation command gets routed to host B
3. Aggregate on host B publishes the MyAggregateCreatedEvent
4. Saga is written to database on host A
The problem is that at the time the event is published on host B, the fact that the saga is associated with the aggregate ID hasn't hit the database yet. So the event bus on host B thinks nothing is interested in the event, and the saga event handler is never invoked.
Right now I'm fixing it like this:
private void startSomeWork(CreateMyAggregateCommand command) {
associateWith("aggregateId", command.getAggregateId());
CurrentUnitOfWork.get().registerListener(new UnitOfWorkListenerAdapter() {
@Override
public void afterCommit(UnitOfWork unitOfWork) {
commandGateway.dispatch(command);
}
});
}
By deferring command dispatch until after the saga (with its associations) has been committed to the database, host B always sees the association and invokes the saga event handler without issues.
It's not necessary to wrap *all* commands like this, of course, just ones that occur in a unit of work where a saga's associations change in a way that affects its ability to receive whatever events result from the command.
Is this a sane approach, or is it a sign I'm doing something wrong?
-Steve