将bean路由模板参数传递到Camel中的bean端点

gpnt7bae  于 9个月前  发布在  Apache
关注(0)|答案(1)|浏览(73)

我使用的是Camel 4.0.0-RC 2,并遵循将bean绑定到RouteTemplate的文档。我有一个简单的路由模板,可以从可配置的fromEndpointUri中使用,并将可配置的foo传递给我的fooConsumer

routeTemplate("myTemplate")
  // Define the parameters for the route template.
  .templateParameter ("fromEndpointUri")
  .templateBean      ("foo", Foo.class)

  // Define the route.
  .from ("{{fromEndpointUri}}")
  .bean (fooConsumer, "processFoo(${body}, #{{foo}})");

我使用该模板创建的路由简单如下:

templatedRoute("myTemplate")
  .routeId   ("myTemplateRoute")
  .parameter ("fromEndpointUri", "direct:test")
  .bean      ("foo", Foo.class, ignored -> new Foo());

当通过此路由发送消息时,会抛出No type converter available to convert from type: java.lang.String to the required type: com.example.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]
    ...

如何将路由的Foo示例传递给FooConsumer?我尝试过的一些变化是:
| 变化|误差|
| --|--|
| .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}}语法将myClient bean传递到aws2-s3端点。

r6l8ljro

r6l8ljro1#

我发现了一种使用这些路线模板的方法,就像我在这里尝试的那样,但感觉不是很干净。也许我是想用一种他们不想用的方式来使用它们。无论如何,为了让它工作,我在定义路由模板的类中创建了一个内部ServiceActivator类:

private class ServiceActivator {
  private final Foo foo;

  public ServiceActivator(final RouteTemplateContext routeTemplateContext) {
    this.foo = (
      routeTemplateContext
        .getLocalBeanRepository ()
        .lookupByNameAndType    ("foo", Foo.class)
      );
  }

  @Handler
  public void processFoo(@Body final String body) {
    // do something 
  }
}

然后,我将路由模板更新为:
1.删除foo的声明,因为拥有该定义会使Camel尝试为其创建默认值。
1.在创建路由时创建此ServiceActivator
1.在路由的bean定义中引用ServiceActivator

routeTemplate("myTemplate")
  // Define the parameters for the route template
  .templateParameter ("fromEndpointUri")
  .templateBean      ("serviceActivator, ServiceActivator.class, ServiceActivator::new)

  // Define the route.
  .from("{{fromEndpointUri}}")
  .bean("{{serviceActivator}}")

并将我的模板化路由设置为:

templatedRoute("myTemplate")
  .routeId   ("myTemplateRoute")
  .parameter ("fromEndpointUri", "direct:test")
  .bean      ("foo", Foo.class, ignored -> new Foo());

再次,它似乎几乎像一个黑客,而不是使用这个功能的 Camel 的方式,它是打算使用。从我对代码的逐步了解中可以看出,路由模板参数和bean仅在路由创建时可用,因此这是一种在路由创建期间捕获所有信息的方法,以便在以后执行路由时使用。

相关问题