Is it possible to have @EventSourcingHandler annotated methods in an external class (different from Aggregate)?

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 :slight_smile:

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 @EventHandlers instead of @EventSourcingHandlers. 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 @EventSourcingHandlers 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. :slight_smile:

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. :slight_smile: