Apache Camel REST与POJO转换报错:无可用类型转换器及疑问
问题
我定义了一个接收DTO的POST类型REST端点,发现只有添加unmarshal/marshal语句才能正常运行,但很多示例里都没用到这些语句。现在有两个疑问:
- 是否必须使用这些marshal/unmarshal语句?
- POJO能否实现JSON与POJO的双向转换?
REST端点:
rest://post:saveIDto?inType=ContainerDefinitionDto.class&outType=ContainerDefinitionDto.class&type=ContainerDefinitionDto.class
路由 - 在direct:processRoute处失败
.from("rest://post:saveIDto?inType=ContainerDefinitionDto.class&outType=ContainerDefinitionDto.class&type=ContainerDefinitionDto.class") // 需要插入以下代码才能正常运行 //.unmarshal(new JacksonDataFormat(ContainerDefinitionDto.class)) .log("${body}") .to("direct:processRoute") // 需要插入以下代码才能正常运行 //.marshal(new JacksonDataFormat(ContainerDefinitionDto.class));");
错误信息:
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[] at org.apache.camel.CamelExecutionException.wrapCamelExecutionException(CamelExecutionException.java:45) at org.apache.camel.support.builder.ExpressionBuilder$35.evaluate(ExpressionBuilder.java:1101) at org.apache.camel.support.ExpressionAdapter.evaluate(ExpressionAdapter.java:45) at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluateParameterBinding(MethodInfo.java:743) at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluateParameterExpressions(MethodInfo.java:623) at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluate(MethodInfo.java:591) at org.apache.camel.component.bean.MethodInfo.initializeArguments(MethodInfo.java:262) at org.apache.camel.component.bean.MethodInfo.createMethodInvocation(MethodInfo.java:270) at org.apache.camel.component.bean.BeanInfo.createInvocation(BeanInfo.java:279) at org.apache.camel.component.bean.AbstractBeanProcessor.useMethodInvocation(AbstractBeanProcessor.java:102) at org.apache.camel.component.bean.AbstractBeanProcessor.process(AbstractBeanProcessor.java:88) at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:81) at org.apache.camel.component.bean.BeanProducer.process(BeanProducer.java:41) at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:172) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.handleFirst(RedeliveryErrorHandler.java:462) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:438) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.doRun(DefaultReactiveExecutor.java:199) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.executeReactiveWork(DefaultReactiveExecutor.java:189) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.tryExecuteReactiveWork(DefaultReactiveExecutor.java:166) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59) at org.apache.camel.processor.Pipeline.process(Pipeline.java:163) at org.apache.camel.impl.engine.CamelInternalProcessor.processNonTransacted(CamelInternalProcessor.java:354) at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:330) at org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:81) at org.apache.camel.support.AsyncProcessorSupport.process(AsyncProcessorSupport.java:32) at org.apache.camel.component.undertow.UndertowConsumer.handleRequest(UndertowConsumer.java:214) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:393) at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:859) at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1512) at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: org.apache.camel.InvalidPayloadException: No body available of type: au.com.cs.inventory.api.dto.ContainerDefinitionDto but has type: byte[] on: Message. Caused by: No type converter available to convert from type: byte[] to the required type: au.com.cs.inventory.api.dto.ContainerDefinitionDto. Exchange[]. Caused by: [org.apache.camel.NoTypeConversionAvailableException - No type converter available to convert from type: byte[] to the required type: au.com.cs.inventory.api.dto.ContainerDefinitionDto] at org.apache.camel.support.MessageSupport.getMandatoryBody(MessageSupport.java:128) at org.apache.camel.support.builder.ExpressionBuilder$35.evaluate(ExpressionBuilder.java:1099) ... 32 more Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: byte[] to the required type: au.com.cs.inventory.api.dto.ContainerDefinitionDto at org.apache.camel.impl.converter.CoreTypeConverterRegistry.mandatoryConvertTo(CoreTypeConverterRegistry.java:199) at org.apache.camel.support.MessageSupport.getMandatoryBody(MessageSupport.java:126) ... 33 more
解答
1. 是否必须使用marshal/unmarshal语句?
不是必须的,这取决于你的Camel配置和所用组件的状态。
从错误栈能看出,核心问题是Camel没法自动把byte[]类型的请求体转成你的ContainerDefinitionDto对象——说明Camel的自动类型转换机制没起作用。
你用的rest://组件底层是Undertow,正常情况下,如果项目里依赖了Jackson相关的Camel组件(比如camel-jackson或camel-jackson-dataformat),并且inType参数配置正确,组件应该自动完成反序列化(unmarshal)。现在没生效,大概率是这几个原因:
- 缺少Jackson相关依赖,导致Camel没有对应的类型转换器
inType参数写错了,应该填全限定类名(比如au.com.cs.inventory.api.dto.ContainerDefinitionDto),不用加.class后缀- 没开启Camel的自动类型转换支持,或者自定义的转换规则覆盖了默认行为
把这些问题解决后,就不需要手动加unmarshal语句。但如果有特殊场景(比如自定义JSON序列化规则、兼容多种数据格式),手动加unmarshal/marshal能更精准控制转换逻辑。
2. POJO能否实现JSON与POJO的双向转换?
当然可以,只要你的POJO满足以下基本要求:
- 有无参构造函数(Jackson默认要求这个)
- 字段有对应的getter/setter方法(或者用
@JsonProperty注解指定序列化/反序列化的字段) - 项目里依赖了Jackson核心库(比如
jackson-databind),同时Camel引入了camel-jackson或camel-jackson-dataformat组件
只要ContainerDefinitionDto符合这些条件,不管是手动用JacksonDataFormat做序列化/反序列化,还是依赖Camel的自动转换,都能实现JSON和POJO的双向转换。
内容的提问来源于stack exchange,提问作者Coffee Bean
相关产品推荐
相关产品推荐

