MultiEventUpcasting

Hello, I read an article about event upcasting, I have a question about MultiEventUpcasting
Is there any examples ?

I found just one example here

But that seems not to be working. How to create Stream of IntermediateEventRepresentation ?

@Component
public class ItemMenuCreatedEventNullTo1_0MultiUpcaster extends EventMultiUpcaster {
    private static final Logger log = LoggerFactory.getLogger(ItemMenuCreatedEventNullTo1_0MultiUpcaster.class);

    private final SimpleSerializedType sourceTypeMenuCreatedEvent = new SimpleSerializedType(MenuCreatedEvent.class.getTypeName(), null);
    private final SimpleSerializedType targetTypeMenuCreatedEvent = new SimpleSerializedType(MenuCreatedEvent.class.getTypeName(), "1.0");
    private final SimpleSerializedType sourceTypeMenuUpdatedEvent = new SimpleSerializedType(MenuUpdatedEvent.class.getTypeName(), null);
    private final SimpleSerializedType targetTypeMenuUpdatedEvent = new SimpleSerializedType(MenuUpdatedEvent.class.getTypeName(), "1.0");

    @Override
    protected boolean canUpcast(IntermediateEventRepresentation intermediateRepresentation) {
        return intermediateRepresentation.getType().equals(sourceTypeMenuCreatedEvent);
    }

    @Override
    protected Stream<IntermediateEventRepresentation> doUpcast(IntermediateEventRepresentation ir) {
        return Stream.of(
                ir.upcastPayload(new SimpleSerializedType(MenuCreatedEvent.class.getName(), "1.0"),
                        IntermediateEventRepresentation.class,
                        intermediateEventRepresentation -> sortToPosition(ir, targetTypeMenuCreatedEvent)),
                ir.upcastPayload(new SimpleSerializedType(MenuUpdatedEvent.class.getName(), "1.0"),
                        IntermediateEventRepresentation.class,
                        intermediateEventRepresentation -> sortToPosition(ir, targetTypeMenuUpdatedEvent))
        );
    }
    
    private IntermediateEventRepresentation sortToPosition(IntermediateEventRepresentation intermediateRepresentation, SimpleSerializedType targetType) {
        log.info("Upcasting event {} to {}", intermediateRepresentation.getAggregateType(), targetType);

        return intermediateRepresentation.upcastPayload(
                targetType,
                org.dom4j.Document.class,
                document -> {
                    String currentSortValue = document.getRootElement().element("position").getStringValue();

                    document.getRootElement()
                            .addElement("position2")
                            .setText(currentSortValue);

                    document.getRootElement()
                            .element("position")
                            .detach();

                    return document;
                }
        );
    }
}

Hi @VladimirTitov4, how are you doing?

Let me try to help you… first thing, looking at your code and comparing to the link you provided, the error is on the ‘type’ you are sending to the upcastPayload method.
In your example, you are sending the IntermediateEventRepresentation.class while it should be org.dom4j.Document.class (since you are working with XML, JsonNode.class if you were working with Json).
By fixing that, creating your Stream of IntermediateEventRepresentation should work.

Nonetheless, I created an issue on our code-sample to expand what we already have there to add another examples and samples.

Here, I would like to point a couple of small notes, if you allow me:

  1. Looking at your events being called Create* and Update*, seems like you are following a CRUD approach. This is not something we commonly see when working with DDD as your events should have some meaning.
  2. As already stated before, you are using XML but I would recommend you to have a look at using Json (and Jackson) for storing your events. It’s more ‘human readable’ and the size of the event is a lot smaller.
  3. On your example, you are trying to upcast 2 times (you call upcastPayload two times). The second time is almost correct, where you are using the correct type there but the first one not. You should revisit that piece of code.

Hope that helps you enough!
If not, let us know.

KR,

@Component
public class ItemMenuCreatedEventNullTo1_0MultiUpcaster extends EventMultiUpcaster {
    private static final Logger log = LoggerFactory.getLogger(ItemMenuCreatedEventNullTo1_0MultiUpcaster.class);

    private final SimpleSerializedType targetTypeOne = new SimpleSerializedType(MenuCreatedEvent.class.getTypeName(), null);
    private final SimpleSerializedType targetTypeTwo = new SimpleSerializedType(MenuUpdatedEvent.class.getTypeName(), null);

    @Override
    protected boolean canUpcast(IntermediateEventRepresentation intermediateRepresentation) {
        return intermediateRepresentation.getType().equals(targetTypeOne);
    }

    @Override
    protected Stream<IntermediateEventRepresentation> doUpcast(IntermediateEventRepresentation ir) {
        return Stream.of(
                ir.upcastPayload(new SimpleSerializedType(targetTypeOne.getName(), "1.0"),
                        org.dom4j.Document.class,
                        this::doUpcastOne),
                ir.upcastPayload(new SimpleSerializedType(MenuUpdatedEvent.class.getName(), null),
                        org.dom4j.Document.class,
                        this::doUpcastTwo)
        );
    }

    protected org.dom4j.Document doUpcastOne(org.dom4j.Document document) {
        String currentSortValue = document.getRootElement().element("sort").getStringValue();
        document.getRootElement()
                .addElement("position")
                .setText(currentSortValue);

        document.getRootElement()
                .element("sort")
                .detach();

        return document;
    }

    protected org.dom4j.Document doUpcastTwo(org.dom4j.Document document) {
        String currentSortValue = document.getRootElement().element("sort").getStringValue();
        document.getRootElement()
                .addElement("position")
                .setText(currentSortValue);

        document.getRootElement()
                .element("sort")
                .detach();

        return document;
    }
}

Hello @lfgcampos sorry for long response

Actually I refactored my code as it could be seen above.
Now the problem is when I enter getUpcastTwo method I have document passed as MenuCreatedEvent, but it should be MenuUpdatedEvent. So I’m getting java.lang.IllegalArgumentException: argument type mismatch Error.

So could you please take a look again at my piece of code and point me on a mistake.
Because in my project is getting more and more EventUpcasting and I want to use EventMultiUpcaster instead of SingleEventUpcaster

P.S.
Do I have to check canUpcast method for all the events? or just for the first event ?

Waiting for the answer :pray:

Still waiting, please give some examples, or help me with my example
Thank you in advance!

:upside_down_face: