I had a similar problem when I first learned about sagas. The confusion seems to be because the docs don’t mention the keyName
and just explain the default behavior.
If you look at the @SagaEventHandler
javadoc, you will notice there is an optional keyName
. So let me explain with an example. Say you have this:
@StartSaga
@SagaEventHandler(associationProperty = "orderId", keyName="orderKey")
public void handleNewOrder(OrderCreatedEvent orderCreatedEvent) {
...
}
When an OrderCreatedEvent
is processed a new saga instance is created (due to @StartSaga
). That instance is associated with a concept that consists of a key and value. The key, in this case, is orderKey
. The value is taken from the orderId
property of the orderCreatedEvent
. For example, if orderCreatedEvent.orderId
is 5
, this sage instance is associated with the orderKey=5
concept.
In the same saga, you may also have
@SagaEventHandler(associationProperty = "orderId", keyName="orderKey")
public void handleShipment(ShippingEvent shippingEvent) {
...
}
The same rule applies here (orderKey = shippingEvent.orderId
). That means that the saga instance will not react to every ShippingEvent
message in the system but only to those matching the associated concept. Following the example above, that is only the events for which shippingEvent.orderId = 5
. In other words, a ShippingEvent
message where the orderId
is not 5
will not make that saga instance execute the handleShipment
method.
When you want the keyName
to use the same name as the property of the event from which it gets the value (which is often the case), you may skip the keyName
. So the following 2 lines are semantically identical
@SagaEventHandler(associationProperty = "orderId", keyName="orderId")
@SagaEventHandler(associationProperty = "orderId")
Please note that setting the association via annotation only works in @StartSaga
methods. In all other handlers, it is used for checking the association (
perhaps we should have distinct annotations). If you want to set more associations or you need to do it at later stage, you should use the API. For example:
SagaLifecycle.associateWith("orderId", shippingEvent.orderId);
I hope this helps understand the concept.