Event raised from one AR handled by another AR which has not been created in the repository

Here is a situation

AR raises multiple events in its business method

AR1.dosomething(somedata sData) {
do some logic
apply(new Event1)
do some logic

apply(new Event2)

}

AR1.onEvent1() {
change ARstate
}

Now AR2 needs to handle Event2, but it has not been created via command handler or retrieved from a repository i.e. it does not exist, however…this event2 needs to generate a new AR and handle event2…and it needs to generate event3 which is handled by AR1

AR1.onEvent3() //this was generated by AR2

…don’t think this can be done…this is cross bounded context communication and handling.

Any thoughts?? Is this appropriate for Saga use?? any elaboration of ideas by leveraging above example would be great.

Thanks

Hi,

this exactly what sagas are for: they coordinate activities between aggregates (sometimesmwithin different bounded contexts).
In Axon, you can use the Saga mechanism, but if the process is really simple, and event handler sending out command will suffice.
In your case, you could createman EventHandler that listens to Event2 and Event3. on Event2, send a command to AR3, and similar for on Event3.

If the process is a bit more complex (e.g. you need to be able to trigger compensating actions when things go wrong), it's better to create a real Saga for it.

Hope this helps.

Cheers,

Allard

That makes a lot of sense…I was already down the saga path and was good revalidation…2 areas though where still need clarification are

1)how to get handle to the command bus in AR and commandbus.dispatch() in the AR. Sagas have resource injection to get the handle with transient variable. If this is to be done in AR and not in Saga for simple scenario, Also the commandbus needs to be transient in the AR and autowired by some resource injection, but have not seen that as a widespread practice. Am I on the right track? Any example of how to do that? Maybe as spring bean defining AR having that property? and set by spring? outside Axon?

2)how to initiate saga from commandbus.dispatch in commandHandler to start of a cross AR SAGA process with coordination similar to creation of a new AR from AR repository, but for SagaRepository. Scenario is command from clients send information to craate 2 ARs and fire the appropriate events, however they have to be done in a sequence AR1 first and then after sucessfull AR1 creation and completion of events, AR2 gets initalized and its events fire…coordination of this cross AR process e.g. in the addressbook example if Contact and Address were BC ARs (probably not a good example, but for simplicity), then we want to start a saga to create and establish contact and then go to the Address AR create the Address and then assign the Addressid to the Contact AR for reference and future propogation of context from Contact (something like that, again not good example)

Any thoughts…thanks

Cheers.

Hi,

this is how I see the process:

  1. a command triggers an action in AR1. This generates an event.
  2. An event handler (one outside the aggregate, which is subscribed to the event bus) picks up this event and sends a command to create AR2.
  3. AR2 processes this command and generates another event.
  4. The same listener as step 2. picks up this event and sends another command to AR1.
  5. AR1 processes the command and generates another event, which is probably irrelevant to the saga.

The handlers of steps 2 and 4 are placed inside a separate object, which subscribe to the event bus. It can be a single Spring bean, or a Saga managed by Axon. If you use the Saga mechanism, event1 will trigger a new saga, and probably the event generated in step 5 will end it.

In general, you should never have to wire a command bus in the aggregate. If an event from one aggregate is a command for another aggregate, then a Saga (either complex or just a bean with handlers on it) will do that translation.

So to answer your second question: a Saga is triggered by an event, not by a command.

Cheers,

Allard

Thanks for the clarification…one suttle observation/question/clarification is

a) Why does the AR not react to external events? i.e. why does a command have to call a method on AR from external event handler/saga which generates a so called event which it handles? Seems like from below in Step 4, instead AR1 could handle the event from AR2 directly.

My theory on any answer is that since in cqrs all event handlers on the AR change state on AR and thats all they do, then
1)that event handling done directly in AR may work i.e. no logic in AR event handler only state change directly.
2)However if domain logic has to be applied then a method to apply logic and an event to change state would be needed to assure that no logic gets executed during the replay cycle of events to build the ARs latest state, hence the external event handler/saga needs to leverage a command to load the AR and call a method on it.

Does that make sense, any thoughts…want to clarify.

Cheers…

Hi,

your response is quite correct. There are several reasons why one AR should not process events from another AR.

  • decoupling: you don’t want to tie the logic of one aggregate to that of another. Why should an Order know about the lifecycle of a Product? All an Aggregate should do is maintain, track and validate state transitions.
  • the event handler inside an aggregate is meant for “rebuilding” purposes. These methods don’t do any validation, they just plainly change state. If the aggregate were to listen to another aggregate’s events, there is no way you could validate any state. When this is about to happen, maybe you have overlooked an aggregate boudary. Perhaps both entities need to be part of the same aggregte.
  • explicitness. If one aggregate’s event, is another aggregate’s command, name them as such.
  • timing: the event handler inside an aggregate is invoked immediately as part of the apply method. All other handlers are only invoked after the aggregate is committed.

In the end it’s a sort of “design convention” that I am sure you won’t regret. :wink:

Cheers,

Allard

Good summary…thx

Please see my article about Axon/DDD/EDA: http://pkaczor.blogspot.com/2011/08/axon-framework-ddd-and-eda-meet.html
I applied Axon to standard ORM-based application and got rid of transaction script. I prefer event driven approach.

Hi Pawel,

nice article. I haven’t seen many implementations that use the plain JPA ORM for aggregates on the command side. For some reason, many immediately go for the event sourced approach. (As do I :wink: )

Cheers,

Allard