Axon 3.3.1 - Spring Boot - Kotlin: Events can not be converted when switching to JocksonSerializer

I set up a simple bank application (Account/Deposit/Withdraw) with Spring boot 2.0.3, kotlin 1.2.51 and axon 3.3.1, you can find it here: https://github.com/holisticon/holi-bank

Everything works fine, love the new QuerySubscription feature in combination with webflux!

But:

when I change the serializer to Jackson (uncomment bean in HoliBankApplication#70, The application fails with:

Command ‘de.holisticon.bank.domain.Deposit’ resulted in org.axonframework.messaging.annotation.MessageHandlerInvocationException(Error handling event of type [class de.holisticon.bank.domain.AccountCreated] in aggregate)

I assume that because parsing the json event confused AccountCreated and BalancedChanged …

Did you see this problem somewhere else?

Hi,
you need the jackson-module-kotlin (https://github.com/FasterXML/jackson-module-kotlin) instead of the default Jackson one.

Hope this helps,

Richard

That did not solve it … thanks, though

Hi Jan,

I think Richard is on the right track but some things are still missing.

The lines you have are

@Bean
fun eventSerializer() = JacksonSerializer()

This constructor of JacksonSerializer will create a new ObjectMapper which doesn’t have the Jackson Kotlin module registered. There are a few ways to fix that. One of them is to take advantage of the fact that Spring Boot will set up an ObjectMapper and will register any Module type beans with it. So we can make a bean out of the KotlinModule, and create the JacksonSerializer bean with an injected ObjectMapper bean:

@Bean
fun kotlinModule() = KotlinModule()

@Bean
fun eventSerializer(objectMapper: ObjectMapper) = JacksonSerializer(objectMapper)

Hope this helps.

Regards,

Thanks, that was the missing piece … problem solved.

Is my axon backend now “json-only” or do I have to do the same for tokens and other serializations?

Since I read in some docs/comments that most people will probably switch from XStream to jackson … how aout making this default or at least switchable via properties?

Hi Jan,

You only set the event serializer in your code, which means that some other stuff would still be using XStream - so it’s not json-only yet.

In an Axon Spring Boot application, there are three different Serializer beans:

  • eventSerializer -> used for events, defaults to the messageSerializer if defined, otherswise defaults to the general serializer
  • messageSerializer -> used for messages, defaults to the general serializer
  • general serializer -> used for everything else, defaults to XStream

This can in fact be configured using properties (like axon.serializer.general=jackson), see http://www.axonframework.org/apidocs/3.2/org/axonframework/boot/SerializerProperties.html, but looking at how the mechanism works I don’t think this would allow you to plug in the Jackson Kotlin module. I’ll discuss internally with the team to see if we can fix that. For now I think you would have to do it programmatically.

The reason for defaulting to XStream is that it will serialize/deserialize anything without placing restrictions on the classes. That’s very useful as a starting point.

Kind regards,

Hi Jan,

Jackson serializer will be used for events only in this case. We are still missing the reference guide update on serializers topic, but you can watch for this issue: https://github.com/AxonFramework/ReferenceGuide/issues/45.

Regarding serializer properties, you can use these:

axon.serializer.general=...
axon.serializer.messages=...
axon.serializer.events=...

Cheers,
Milan.

Hi,

We face the same error and doing some test i have fix with this code in my @Configuration class

`

@Autowired
fun kotlinSerializer(@Qualifier(“eventSerializer”) eventSerializer: Serializer) {
System.out.println("Serializer with kotlin ")
val serializer : JacksonSerializer = eventSerializer as JacksonSerializer
serializer.objectMapper.registerKotlinModule()
}

`

PS: i’m new to kotlin so my code probabily is not the best one…

Best regards.