Multiple aggregates should react to an applied event

Hi everyone,

since we are currently struggling with it and i prolly havent found the correct keywords for my search yet… :wink:

I am wondering what would be the correct way of having multiple aggregates react to an event that gets applied by another aggregate (and handled in the aggregates EventSourcingHandler), where the IDs of the potentially interessted aggregates are unknown.

Wether or not the handling of the event in the other aggregates doesnt matter.

Is it possible to broadcast commands on the commandbus? (likely not, since we need a target identifier, right?)
Would one just broadcast/publish the exact same event on a (Simple)EventBus using a Saga and implement @EventHandler methods on the aggregates which in turn could apply the events to the aggregates?

Or are there better ways? :slight_smile:

Thanks in advance!

Hi 68616e6e61 (in absence of a name),

As you’re new, this might be expected, but there are a couple of misconception I catch from your request.
This is only fair, so let me try to clarify some of the topics at hand.

…the correct way of having multiple aggregates react to an event that gets applied by another aggregate
Aggregates cannot handle events from other Aggregates. Aggregates are you command model and thus react to commands. The events an Aggregate handles, are the events it needs to source itself from the event store.

That’s why an Aggregate should use the @EventSourcingHandler annotation instead of the @EventHandler annotation. If you want an interplay between several Aggregates, either a regular event handling component could suffice, or if there is a notion of time in the problem you try to resolve, a Saga might be the solution.

Is it possible to broadcast commands on the commandbus

No it is not, as a Command is intended to be handled by a single point. There is (should be at least) an authoritative unit which can handle the command and make the decision whether it was okay to execute that command.

Hope this sheds some light on the issues you’re experiencing.

Cheers,
Steven

Hi Steven,

thanks for clarifying things.

Actually, the way you describe the event handling of aggregates, etc. was the way we understood it until today, when we found some JavaDoc that got us confused, because it made it look like events would be published to “other handlers” after they were processed by the aggregate. Maybe i just simply misread it. I ll search for it and create an issue if it was not me misreading it, so it can be worded more unambiguous. :slight_smile:

There is (should be at least) an authoritative unit

Currently it looks as follows:

  • I have multiple Aggregates that can reference each other by their uuids.
  • For each Aggregate type there is a Library that knows all Identifiers (and some other info)
  • If Aggregate A gets deactivated, the identifier of Aggregate A should be removed from all other Aggregates

Intuitively i would say it would be correct so send a Command to each relevant aggregate since its more like a “request” or “order” (Hello Mr. Aggregate, check if you know this aggregate and if you do, remove it).
But i cant think of a way to do this without either querying the read side (in the saga or the event handling component) or applying events in the Library Aggregate only to trigger the Saga without actually changing any state of the LibraryItself.
That would look like:

  • AggregateDeactivationRequested (knows the aggregateId and all relevant Libraries)

  • Saga gets Started and sends DeactivateAggregateCommand to the target aggregate

  • TargetAggregate applies AggregateDeactivatedEvent

  • Saga reacts to the DeactivatedEvent by sending a “RequestRelationRemovalCommand” to the Library

  • Library then applies a “RelationRemovalRequestedEvent” for each Aggregate it knows (the apply doesnt actaully change any of its state)

  • Saga reacts to the RelationRemovalRequestedEvent by sending a Command to the Aggregate that should remove the relation
    The alternative would look something like:

  • AggregateDeactivatedEvent starts a Saga

  • Saga queries read side for every aggregateId that contains the identifier of the deactivated aggregate

  • Saga send RemoveRelationCommand to each of the found aggregates

Its tempting to use the second approach … well because its simple. But then again i am really not sure about querying the read side from within the Saga. On the other hand the applying of events that do not change the aggregates state seems to be wrong to. :wink:

Cheers
68616e6e61 :wink: