Search code examples
kotlinjacksonapache-camelquarkusobjectmapper

Camel Quarkus does not seem to be using the Quarkus objectmapper


I have a Camel ReST route that uses Jackson to convert a collection to JSON but it's throwing an error when the object in the collection includes a LocalDate (everything works fine without LocalDates).

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.LocalDate not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"

I have added a class to customise the Quarkus ObjectMapper:


    @Singleton
    class MyObjectMapperCustomizer : ObjectMapperCustomizer {
        override fun customize(objectMapper: ObjectMapper) {
            objectMapper.registerModule(JavaTimeModule())
        }
    }

but it looks like Camel is not using this ObjectMapper and I can see in VisualVM that there are 3 instances of the ObjectMapper class.

The Camel rest endpoint that's throwing the exception is:

     .get().produces(MediaType.APPLICATION_JSON).route()
     .bean(svc.getAllTradeList()).marshal().json(JsonLibrary.Jackson).endRest()

The svc.getAllTradeList just sets the exchange body to a list of Trade objects and the Trade object itself is pretty basic:

    @RegisterForReflection
    data class Trade(
        val id: String,
        val description: String,
        val notional: Double,
        val tradeDate: LocalDate
    )

I can't see an obvious way to make Camel use the Quarkus ObjectMapper that I'm customising or to customise the one that Camel appears to be creating.

Any pointers would be much appreciated.


Solution

  • If there are multiple instances of the object mapper, then camel does not know which one to pick so to use it, you have to explicit configure what camel should use:

    If the object mapper from quarkus is named, you can do something like:

    .marshal()
        .json()
            .libray(JsonLibrary.Jackson)
            .objectMapper("name-of-the-object-mapper") 
    

    if not, you can create an instance of the JacksonDataFormat and configure it:

    JacksonDataFormat df = new JacksonDataFormat();
    df.setObjectMapper(mapper) // use CDI to get a referece
    

    And then use it directly:

    .marshal(mapper)