You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试Camel路由时Jackson序列化LocalDate报InvalidDefinitionException问题

搞定Apache Camel Jackson Marshal处理LocalDate时的InvalidDefinitionException

问题根源

  1. 依赖范围错了:你把所有核心依赖都设成compileOnly,这玩意儿只在编译阶段有用,运行时根本不会把这些依赖打包进去,Jackson的JSR310模块自然找不到。
  2. 自定义ObjectMapper没被Camel用上:测试里new的ObjectMapper只是个局部变量,Camel根本不知道它存在,还是在用自己默认的配置。
  3. 配置属性没生效:camel.dataformat.jackson.auto-discover-object-mapper=true得确保Spring容器里有个配置好的ObjectMapper Bean,不然白设。

一步步解决

1. 先把依赖改对

把compileOnly换成implementation,这样运行时才能加载到需要的类:

configurations {
    testImplementation.extendsFrom implementation
}

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

dependencies{
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: springBootVersion
    implementation group: 'org.apache.camel.springboot', name: 'camel-spring-boot-starter', version: camelVersion
    implementation group: 'org.apache.camel.springboot', name: 'camel-jackson-starter', version: camelVersion
    implementation 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'
}

注:Spring Boot 3.x和Jackson 2.14+版本匹配,Camel 4.0-M1也能和Spring Boot 3.0.2兼容,放心用。

2. 注册全局的ObjectMapper

写个配置类,把带JavaTimeModule的ObjectMapper放进Spring容器,让Camel能自动找到:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        // 要是想把LocalDate序列化成"2023-03-27"这种字符串,而不是数组,加下面这行
        // objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return objectMapper;
    }
}

3. 让Camel的配置生效

在application.properties里加一行:

camel.dataformat.jackson.auto-discover-object-mapper=true

这行的作用是让Camel不用自己造ObjectMapper,直接用Spring容器里的那个。

4. 把测试代码里的bug改了

测试里变量名写错了(ex和exchange混着用),而且不用手动new ObjectMapper,直接用容器里的就行:

@SpringBootTest
@CamelSpringBootTest
@EnableRouteCoverage
public class MyRouteTest {
    @Autowired private CamelContext camelContext;
    @Autowired private ProducerTemplate producerTemplate;

    @Test
    public void testMyRoute() throws Exception {
        Exchange exchange = 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);
        
        // 举个断言例子,检查日期是否正确序列化
        String jsonBody = result.getMessage().getBody(String.class);
        assertThat(jsonBody).contains("\"birth-date\":\"2023-03-27\"");
    }
}

5. 备选方案:直接在路由里指定ObjectMapper

要是不想搞全局配置,也可以在路由里直接用自定义的ObjectMapper:

@Component
public class MyRoute extends RouteBuilder {
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void configure() throws Exception {
        JacksonDataFormat jacksonDataFormat = new JacksonDataFormat();
        jacksonDataFormat.setObjectMapper(objectMapper);
        
        from("direct:MyRoute")
            .routeId("MyRoute")
            .marshal(jacksonDataFormat);
    }
}

验证一下

  • 先跑clean build确保依赖都加载对了
  • 检查运行时类路径里有没有jackson-datatype-jsr310-2.14.2.jar
  • 看Camel的日志,有没有用到自定义ObjectMapper的记录

内容的提问来源于stack exchange,提问作者scafrs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:47:12