Loose coupling with events?

Hi all,

I’ve played around with the" Bootiful CQRS with Axon" webinar (very interesting BTW), and I’ve a question related to the level of coupling we really get by using business events exchanged on a queing system such as RabbitMQ.

Normally, in a microservices architecture, we must strive “Strong consistency and loose coupling”.

In this example, a ComplaintFiledEvent is consummed by an external statistic service.To make XStream (the defaullt serializer mechanism) work properly on the consummer side, I’ve been obliged to copy the ComplaintFiledEvent.java file with the same package from the publisher. Otherwize XStream is unable to deserialize the message.

It means that the publisher and the subscriber must share the very same class. This is not exactly what I call “loose coupling”? Is there a way to configure XStream (or another supported serializer mechanism such as Jackson) to enable at least different packages on both sides? Ideally, the consummer side should be able to use a simplified representation of the event with just the attributes it needs …

Do I miss ST?

Thank you for your help.

Hello Jean-Francois,

you are absolutely right on the coupling part. In the Spring Boot webinar, we had to take a number of shortcuts, otherwise it didn’t fit in the time we were given (or wanted to take).
In a production system, you will definitely not want to serialize your published events using XStream. The reason XStream is default is because it will always work. It can serialize just about everything and deserialize it back into the original state. But the serialized form is quite implementation-specific.

Still, there is a way to use XStream and be more flexible. Using aliases for classes or packages is one, and you can also configure XStream to ignore unknown properties. In that case, a recipient can create its own event classes for only the events that it really cares about.

In general, I would recommend using the JacksonSerializer for the Events. Since Axon 3.1, you can configure a separate serializer for Events and the rest. “The rest” being Saga state, snapshots, tracking tokens and other things that are generally only read by the instance that also stored it.

Essentially, the way serialization works in Axon, is that it takes any Object and writes it as a combination of information: type (which default to the fully qualified class name, but you can alias), revision (basically a version indication) and then the actual serialized information, generally represented as a byte array. When receiving information, the type and revision are used to deduct a class name. The bytes are then deserialized into an instance of that class.

Hope this helps.
Cheers,

Allard

Thank you very much Allard for the clarifiaction. I will try to investigate JacksonSerializer to achieve loose coupling. Otherwize, the Webinar was very interesting!