Hello,
we are using axon in production and we have a potential regression concerning upcasting when upgrading to Axon 3.1.1.
With Axon 3.1 we have an upcaster spring bean that upcasts from one event to three events and it works perfectly :
@Component
public class MyUpcaster extends EventMultiUpcaster {
private static SimpleSerializedType targetType = new SimpleSerializedType("my.events.Event", "1");
@Override
protected boolean canUpcast(final IntermediateEventRepresentation ir) {
return ir.getType().equals(targetType);
}
@Override
protected Stream<IntermediateEventRepresentation> doUpcast(final IntermediateEventRepresentation ir) {
return Stream.of(
ir.upcastPayload(
new SimpleSerializedType("my.events.Event", "2"), JsonNode.class, jsonNode -> jsonNode),
ir.upcastPayload(
new SimpleSerializedType("my.events.OtherEvent1", "1"), JsonNode.class, jsonNode -> jsonNode),
ir.upcastPayload(
new SimpleSerializedType("my.events.OtherEvent2", "1"), JsonNode.class, jsonNode -> jsonNode)
);
}
}
The following handlers are called
@Aggregate(type = "myAggregate")
public class MyAggregate {
...
@EventSourcingHandler
public void on(final my.events.Event event){
OK PASS INTO HANDLER
}
@EventSourcingHandler
public void on(final my.events.OtherEvent1 event){
OK PASS INTO HANDLER
}
@EventSourcingHandler
public void on(final my.events.OtherEvent2 event){
OK PASS INTO HANDLER
}
}
When upgrading from axon 3.1 to 3.1.1, only the first handler is called
@Aggregate(type = "myAggregate")
public class MyAggregate {
...
@EventSourcingHandler
public void on(final my.events.Event event){
OK PASS INTO HANDLER
}
@EventSourcingHandler
public void on(final my.events.OtherEvent1 event){
KO DO NOT PASS INTO HANDLER
}
@EventSourcingHandler
public void on(final my.events.OtherEvent2 event){
KO DO NOT PASS INTO HANDLER
}
}
Thanks to unit tests and ConcatenatingDomainEventStream.java javadoc we have found a workaround.
We have to set an incremented sequence number in each IntermediateEventRepresentation
@Component
public class MyUpcaster extends EventMultiUpcaster {
private static SimpleSerializedType targetType = new SimpleSerializedType("my.events.Event", "1");
@Override
protected boolean canUpcast(final IntermediateEventRepresentation ir) {
return ir.getType().equals(targetType);
}
@Override
protected Stream<IntermediateEventRepresentation> doUpcast(final IntermediateEventRepresentation firstRepresentation) {
//first representation sequence number is equal to zero (in our case)
GenericDomainEventMessage<my.events.OtherEvent1> secondEventMessage = new GenericDomainEventMessage<>(
firstRepresentation.getAggregateType().get(), firstRepresentation.getAggregateIdentifier().get(), firstRepresentation.getSequenceNumber().get()+1L, new my.events.OtherEvent1());
EventData<?> secondEventData = new DomainEventEntry(secondEventMessage, serializer);
InitialEventRepresentation secondRepresentation =
new InitialEventRepresentation(secondEventData, serializer);
GenericDomainEventMessage<my.events.OtherEvent2> thirdEventMessage = new GenericDomainEventMessage<>(
firstRepresentation.getAggregateType().get(), firstRepresentation.getAggregateIdentifier().get(), firstRepresentation.getSequenceNumber().get()+2L, new my.events.OtherEvent2());
EventData<?> thirdEventData = new DomainEventEntry(thirdEventMessage, serializer);
InitialEventRepresentation thirdRepresentation =
new InitialEventRepresentation(thirdEventData, serializer);
return Stream.of(
firstRepresentation.upcastPayload(
new SimpleSerializedType("my.events.Event", "2"), JsonNode.class, jsonNode -> jsonNode),
secondRepresentation.upcastPayload(
new SimpleSerializedType("my.events.OtherEvent1", "1"), JsonNode.class, jsonNode -> jsonNode),
thirdRepresentation.upcastPayload(
new SimpleSerializedType("my.events.OtherEvent2", "1"), JsonNode.class, jsonNode -> jsonNode)
);
}
And Now all handlers are called again
@Aggregate(type = "myAggregate")
public class MyAggregate {
...
@EventSourcingHandler
public void on(final my.events.Event event) {
OK PASS INTO HANDLER
}
@EventSourcingHandler
public void on(final my.events.OtherEvent1 event) {
OK PASS INTO HANDLER
}
@EventSourcingHandler
public void on(final my.events.OtherEvent2 event) {
OK PASS INTO HANDLER
}
Questions :
Is it a side effect since 3.1.1 ? or the new behaviour ?
Are we doing something wrong ?
Many thanks.
Nicolas