Camel中如何将路由模板的Bean参数传递给Bean端点
Camel 4.0.0-RC2路由模板Bean参数传递失败解决方案
使用Camel 4.0.0-RC2,按照路由模板绑定Bean的规范创建路由模板,试图将可配置的foo Bean传递给fooConsumer的processFoo方法,但触发类型转换异常。
问题场景与代码
路由模板定义
routeTemplate("myTemplate") // 定义路由模板的参数 .templateParameter ("fromEndpointUri") .templateBean ("foo", Foo.class) // 定义路由 .from ("{{fromEndpointUri}}") .bean (fooConsumer, "processFoo(${body}, #{{foo}})");
路由实例化代码
templatedRoute("myTemplate") .routeId ("myTemplateRoute") .parameter ("fromEndpointUri", "direct:test") .bean ("foo", Foo.class, ignored -> new Foo());
异常信息
发送消息时抛出以下异常:
org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: java.lang.String to the required type: com.example.Foo at org.apache.camel.impl.converter.CoreTypeConverterRegistry.mandatoryConvertTo(CoreTypeConverterRegistry.java:279) ~[camel-base-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluateParameterValue(MethodInfo.java:717) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] ... 94 more Wrapped by: org.apache.camel.component.bean.ParameterBindingException: Error during parameter binding on method: public java.util.List com.example.FooConsumer.processFoo(java.lang.String,com.example.Foo) at parameter #1 with type: class com.example.Foo with value type: class java.lang.String and value: #foo-1 at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluateParameterValue(MethodInfo.java:728) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluateParameterExpressions(MethodInfo.java:618) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.MethodInfo$ParameterExpression.evaluate(MethodInfo.java:591) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.MethodInfo.initializeArguments(MethodInfo.java:262) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.MethodInfo.createMethodInvocation(MethodInfo.java:270) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.BeanInfo.createInvocation(BeanInfo.java:266) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.AbstractBeanProcessor.process(AbstractBeanProcessor.java:128) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:81) ~[camel-bean-4.0.0-RC2.jar:4.0.0-RC2] ...
已尝试的写法及对应错误
| 写法 | 错误信息 |
|---|---|
.bean(fooConsumer, "processFoo(${body}, {{foo}})") | No type converter available to convert from type: java.lang.String to the required type: com.example.Foo |
.to("bean:fooConsumer?method=processFoo(${body},#{{foo}})") | No type converter available to convert from type: java.lang.String to the required type: com.example.Foo |
.to("bean:fooConsumer?method=processFoo(${body},{{foo}})") | No type converter available to convert from type: java.lang.String to the required type: com.example.Foo |
.bean(fooConsumer, "processFoo(${body}, ${bean:#{{foo}}})") | No bean could be found in the registry for: #foo-1 |
.bean(fooConsumer, "processFoo(${body}, ${bean:{{foo}}})") | No bean could be found in the registry for: foo-1 |
官方示例中存在#{{myClient}}语法传递Bean给aws2-s3端点的案例,说明该场景是可行的。
解决方案
方案1:正确使用Bean表达式引用模板参数
问题根源在于#{{foo}}会被解析为字符串标识(如#foo-1)而非Bean实例。需要结合Camel的bean:表达式与模板参数,正确获取Bean实例:
修正后的路由模板:
routeTemplate("myTemplate") .templateParameter ("fromEndpointUri") .templateBean ("foo", Foo.class) .from ("{{fromEndpointUri}}") // 使用${bean:{{foo}}}引用模板定义的Bean参数 .bean (fooConsumer, "processFoo(${body}, ${bean:{{foo}}})");
方案2:通过依赖注入自动绑定Bean
调整FooConsumer的实现,通过注入方式获取Foo实例,避免显式传递参数:
- 修改
FooConsumer类,添加注入逻辑:
public class FooConsumer { private Foo foo; // 提供setter方法用于注入 public void setFoo(Foo foo) { this.foo = foo; } public List<?> processFoo(String body) { // 使用注入的foo实例处理业务 // ... } }
- 调整路由模板,配置Bean注入:
routeTemplate("myTemplate") .templateParameter ("fromEndpointUri") .templateBean ("foo", Foo.class) // 将模板中的foo Bean注入到fooConsumer .bean("fooConsumer", b -> b.beanProperty("foo", "{{foo}}")) .from ("{{fromEndpointUri}}") .bean(fooConsumer, "processFoo(${body})");
注意事项
确保实例化路由时,foo Bean已正确注册到Camel的注册表中:
- 若使用Spring/Spring Boot环境,需保证
Foo实例被Spring容器管理; - 纯Java环境下,通过
bean()方法注册的Bean需能被Camel识别。
内容的提问来源于stack exchange,提问作者sawprogramming
相关产品推荐
相关产品推荐

