and then access the Aggregate using a Repository?
For example:
@Component
public class BankAccountHandler {
private Repository<BankAccount> repository;
@Autowired
public BankAccountHandler (Repository<BankAccount> repository) {
this.repository = repository;
}
@CommandHandler
public void handle(AddMoneyCommand command) {
Aggregate<BankAccount> bankAccountAggregate = repository.load(command.getBankAccountId());
bankAccountAggregate.execute(bankAccount -> {apply(new MoneyDepositedEvent(command.getBankAccountId(), command.getAmountOfMoney());});
}
@EventSourcingHandler
public void on((MoneyAddedEvent event) {
Aggregate<BankAccount> bankAccountAggregate = repository.load(command.getBankAccountId());
bankAccountAggregate.execute(bankAccount -> {
bankAccount.addAmount(event.getAmount());
});
}
Hi Constantino,
unless I am missing something from your code, I would expect it to work if you would just replace @EventSourcingHandler
with a regular @EventHandler
(and most probably change the event class also - see MoneyDepositedEvent
vs MoneyAddedEvent
). Maybe AxonIQ guys/gals can give us more insights on using event sourcing handler outside of an aggregate as I only assume it is designed for aggregates only.
However what puzzles me is the idea behind your code. Why would you implement a handler outside of an aggregate (actually two handlers - for a command and an event) when you have all of the aggregate’s power (it already knows how to add amount of money) if you keep the handlers inside the aggregate. The code above is IMHO violating encapsulation
Are you trying to extend the aggregate’s behaviour using an external class because you can’t modify its class?
1 Like
Hi Constantino,
Yes, you can as David mentioned, but they would work as @EventHandler
s instead of @EventSourcingHandler
s. However, in regards to state changes and transactions it would be best to use @EventSourcingHandler
inside of an aggregate.
If you chose not to use @EventSourcingHandler
when you get a new command you will always get an empty command & empty event, because your aggregate can not be rehydrated.
If you move your @EventSourcingHandler
s outside of your aggregates they would act as an @EventHandler
, which means they will be handling transactions as 2 separate ones. If you use the @EventHandler
it will automatically use its own event processor, which is the TrackingEventProcessor
with its own threads. This event processor is separate from the one used for your CommandHandler
which again means that your transactions will happen in two different threads. Your validation (state changes and event publication) then do not happen in the same transaction.
@David, in regards to your question, the reason why one would want to go this direction, could be that in the pure DDD mindset, the framework annotations are not used in the domain classes.
Thank you both for your questions. Let me know if there is anything else we can help you with.
Best,
Sara
2 Likes
Hi @Sara_Torrey , Hi @BribedSeeker904 ,
I wanted to thank you for your replies!
I’m now convinced, the it’s better to have the @EventSourcingHandler
direct into the Aggregate.
Initially the reason the put them outside was to have them togheter with the CommandHandlers, that are external in our project but now I understand it was a wrong design decision.
1 Like
It’s my pleasure. I’m glad I could be of help.