Conditional upcasting


I’m wondering about the ways to conditionally upcast an event into different events.

For example, transform:

  1. `
    ServiceRequestedEvent {
    type = [HAPPY, SAD, ANGRY]


conditionally into

  1. HappyServiceRequestedEvent

  2. SadServiceRequestedEvent

  3. AngryServiceRequestedEvent

Using SimpleUpcasterChain, it seems possible, though my solution violates the contract.

class MyUpcaster implements Upcaster { // upcast(SerializedType) returns list of ALL THREE POSSIBLE RETURN TYPES // upcast(...) returns list of ONLY ONE EVENT after deserializing and logic }

Using LazyUpcasterChain, the contract violation breaks things. I thought of making upcast(…) return a List of 3 elements, with the unused 2 elements being null…but it seems scary that @EventHandlers would have to handle null events? (Or would they?)

Can anybody recommend the way to do this?

I was surprised to discover this was not possible cleanly, since it seemed like a natural extension of the example of splitting an event shown in the documentation to want to split conditionally.

Best regards,

Peter Davis

P.S. congrats on the 2.1 release!

Hi Peter,

it seems that using the SimpleUpcasterChain is the only way around this, for now. It’s clear that the API on the upcasters doesn’t allow for this flexibility. I’ll see if the is something I can do in a backwards compatible way to improve on this in future versions.

The basic api change would be simple. Passing the serialized object in the upcast-serializedType part of the process would probably give you enough information to do the conditional upcasting. It will then still be lazily upcast in most cases. Only when an upcast is conditional, you will always have to invoke some upcasters to get the required information.

Would you create an issue for this? I’ll schedule it for 2.2. In the meantime, the SimpleUpcasterChain will work around the problem.




I have a problem testing a saga.
The problem arises when I modify the eventHandler of the saga adding as second argument DomainEventMessage.
The test case fails with a very strange error, but it seems that the fixture cannot match the generated command anymore.

Code below:

    @SagaEventHandler(associationProperty = "id") public void handle(EventoLavagnaCreata event, DomainEventMessage domainEventMessage) {
        commandGateway.sendAndWait(newComandoCreaMessaggioVersoCliens(event.getData(), UUID.randomUUID().toString(), event, domainEventMessage.getSequenceNumber()));


ComandoCreaMessaggioVersoCliensMatcher(new ComandoCreaMessaggioVersoCliens(DATA_EVENTO, ID_AGGREGATO, EVENTO_LAVAGNA_CREATA, VERSIONE_0))))

Note that if I remove the parameter DomainEventMessage the test passes wothout problem.
Can this be a bug of the testing suite? Otherwise what should i do to fix this problem?

Thanks for any help you can provide.

Hi again,

going deeper into the problem and reading the documentation showed us that
The SagaEventhandler annotation does not support passing the DomainEventMessage parameter while
the normal EventHandler supports it.
Is possible to add this feature also on the SagaEventHandler?


Hi Andrea,

the mechanism used to process @SagaEventHandler methods is exactly the same as the one for @EventHandler or @EventSourcingHandler methods. Adding a DomainEventMessage works fine.

The probem seems to be in the SagaTestFixture. It doesn’t create a DomainEventMessage, but a “regular” EventMessage. So by adding a second parameter of type DomainEventMessage, that handler method isn’t suitable anymore.
I have created issue AXON-217 to track this.

Just a side note: if you’re just interested in the sequence number, you can also use “@SequenceNumber long seqNo” as parameter.



Hi Allard,

Yes we need exactly the sequence number.

Just a side note: if you're just interested in the sequence number, you can
also use "@SequenceNumber long seqNo" as parameter.

Is this annotation avaliable only in axon 2.1?
Thanks for your precious help.


The annotation was added in 2.1, indeed.