Search code examples
javajacksonapache-camel

Unit testing with camel causing InvalidDefinitionException Java 8 date/time 'java.time.LocalDate' not supportend


I'm trying to test a camel route that makes use of Marshal EIP with Jackson however when I try to convert a LocalDate I get an InvalidDefinitionException. I already added the module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to my dependencies and registered it without any success. Any suggestion what could be wrong? Also use property camel.dataformat.jackson.auto-discover-object-mapper=true but it doesn't work in tests

Route

@Component
public class MyRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("direct:MyRoute")
            .routeId("MyRoute")
            .marshal()
            .json(JsonLibrary.Jackson)
    }
}

Test

@SpringBootTest()
@CamelSpringBootTest
@EnableRouteCoverage
public class MyRouteTest {
    @Autowired private CamelContext camelContext;

    @Autowired private ProducerTemplate producerTemplate;

    @Test
    public void testMyRoute() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        Exchange ex = new DefaultExchange(camelContext);
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("name", "Rick");
        map.put("birth-date", LocalDate.of(2023, 3, 27));
        exchange.getMessage().setBody(map);
        Exchange result = producerTemplate.send("direct:MyRoute", exchange);
        // Asserts
    }
}

dependencies

configurations {
    testImplementation.extendsFrom compileOnly
}

buildscript {
    ext {
        springBootVersion = '3.0.2'
        camelVersion = '4.0.0-M1'
    }
}

dependencies{
    compileOnly group: 'org.springframework.boot', name: 'spring-boot-dependencies', version: springBootVersion
    compileOnly group: 'org.apache.camel.springboot', name: 'camel-spring-boot-starter', version: camelVersion
    compileOnly group: 'org.apache.camel.springboot', name: 'camel-jackson-starter', version: camelVersion
    compileOnly group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.14.2'
    testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion
    testImplementation group: 'org.apache.camel', name: 'camel-test-spring-junit5', version: camelVersion
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

Solution

  • To solve this I had to create an instance of ObjectMapper and set it to a JacksonDataFormat object that is finally the one used in Marshal EIP

    Route

    @Component
    public class MyRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        JacksonDataFormat dataFormat = new JacksonDataFormat();
        dataFormat.setObjectMapper(objectMapper);
        from("direct:MyRoute")
            .routeId("MyRoute")
            .marshal(dataFormat);
       }
    }
    

    If you know a more elegant way to do it you can suggest it :D