Identifier Mapping
When loading Aggregates or Sagas we need to know what Identifier should be used for that. This depending on the business feature we work may require different approaches. In this section we will dive into different solutions which we can use.
Auto-Mapping from the Command/Event
Ecotone resolves the mapping automatically, when Identifier in the Aggregate/Saga is named the same as the property in the Command/Event.
then, if Message has productId, it will be used for Mapping:
You may use multiple aggregate identifiers or identifier as objects (e.g. Uuid) as long as they provide __toString
method
Expose Identifier using Method
We may also expose identifier over public method by annotating it with attribute IdentifierMethod("productId").
Targeting Identifier from Event/Command
If the property name is different than Identifier in the Aggregate/Saga, we need to give Ecotone
a hint, how to correlate identifiers.
We can do that using TargetIdentifier attribute, which states to which Identifier given property references too:
Targeting Identifier from Metadata
When there is no property to correlate inside Command or Event, we can use Identifier from Metadata.
When we've the identifier inside Metadata
then we can use identifierMetadataMapping.
Suppose the orderId identifier is available in metadata under key orderNumber, then we can then use this mapping:
We can make use of Before
or Presend
Interceptors to enrich event's metadata with required identifiers.
Dynamic Identifier
We may provide Identifier dynamically using Command Bus. This way we can state explicitly what Aggregate/Saga instance we do refer too. Thanks to we don't need to define Identifier inside the Command and we can skip any kind of mapping.
In some scenario we won't be in deal to create an Command class at all. For example we may provide block user action, which changes the status:
Event so we are using "aggregate.id" in the metadata, this will work exactly the same for Sagas. Therefore if we want to trigger Message Handler on the Saga, we can use "aggregate.id" too.
Advanced Identifier Mapping
There may be cases where more advanced mapping may be needed. In those cases we can use identifier mapping based on Expression Language.
When using identifierMapping configuration, we get access to the Message fully and to Dependency Container. To access specific part we will be using:
payload -> Represents our Event/Command class
headers -> Represents our Message's metadata
reference('name') -> Allow to access given service from our Dependency Container
Suppose the
orderId
identifier is available in metadata under keyorderNumber
, then we can tell Message Handler to use this mapping:
Suppose our Identifier is an Email object within Command class and we would like to normalize before it's used for fetching the Aggregate/Saga:
Suppose we receive external order id, however we do have in database our internal order id that should be used as Identifier. We could then have a Service registered in DI under "orderIdExchange":
Then we can make use of it in our identifier Mapping
Last updated