camel自定义编组,标题中包含dataFormat名称

时间:2016-09-13 08:47:30

标签: apache header apache-camel marshalling dataformat

我在两个独立的项目中有两条路线:

  1. 第一个路由是将数据格式bean名称设置为常量:
  2. setHeader("dataFormatBeanName", constant("myFirstList"))

    第一条路线:

    public class MyTest {
        @Configuration
        public static class MyTestConfig extends CamelConfiguration {
    
            @Bean(name = "myFirstList")
            public DataFormat getMyFirstListDataFormat() {
                return new MyFirstListDataFormat();
            }
    
            @Bean(name = "mySecondList")
            public DataFormat getMySecondListDataFormat() {
                return new MySecondListDataFormat();
            }
    
            @Bean
            public RouteBuilder route() {
                return new RouteBuilder() {
    
                    @Override
                    public void configure() throws Exception {
                        from("direct:testFirstDataFormat").setHeader("dataFormatBeanName", constant("myFirstList")).to("direct:myRoute");
                        from("direct:testSecondDataFormat").setHeader("dataFormatBeanName", constant("mySecondList")).to("direct:myRoute");
                    }
                };
            }
        }
    }
    
    1. 第二个路由应该从头部检索bean名称并将其用作自定义编组器。类似的东西:
    2. custom(header("dataFormatBeanName"))

      (不编译)

      任何人都知道我应该从标题中获取我的bean名称以在自定义方法中使用它吗?

      @Component
      public class MyRouteBuilder extends RouteBuilder {
          @Override
          public void configure() throws Exception {
              final RouteDefinition routedefinition = this.from("direct:myRoute");
              routedefinition.marshal().custom(??????????).to("netty4:tcp://{{route.address}}:{{port}}?textline=true&sync=true");
          }
      

4 个答案:

答案 0 :(得分:0)

经过几个小时的搜索,这里找到了解决方案:

第一堂课没有变化。

第二个类使用匿名DataFormat,在其中我从头部检索bean名称,并在调用其marshal方法之前从camel上下文获取spring bean。 AbstractXxxDataFormat类属于project2,由Project1 DataFormat继承。

    @Override
    public void configure() throws Exception {
        final RouteDefinition routedefinition = this.from("direct:myRoute");
        routedefinition.marshal(new DataFormat() {
            @Override
            public void marshal(final Exchange exchange, final Object graph, final OutputStream stream) throws Exception {
                AbstractXxxDataFormat myDataFormat = (AbstractGoalDataFormat) getContext().getRegistry().lookupByName(exchange.getIn().getHeader("dataFormatBeanName", String.class));
                myDataFormat.marshal(exchange, graph, stream);
            }

            @Override
            public Object unmarshal(final Exchange exchange, final InputStream stream) throws Exception {
                return null;
            }
        });
        routedefinition.to("netty4:tcp://{{route.address}}:{{port}}?textline=true&sync=true");
    }

如果有更好的解决方案,我会对此感兴趣。

答案 1 :(得分:0)

您是否尝试simple("${header.dataFormatBeanName}")访问标题?

此外,为什么不将每个.marshal()调用分解为两个子路由(一个用于formatBeanA,一个用于formatBeanB),然后调用适当的子路由而不是在头部中首先传递格式bean名称。首先设置标题?我相信这可能是一种更清洁的方法。

答案 2 :(得分:0)

如果你真的需要在路由中将它作为变量(而不是在构建器api中使用的谓词),你可以使用内联处理器来提取它:

public class MyRouteBuilder extends RouteBuilder {
    public void configure() throws Exception {
        from("someEndpoint")
        .process(new Processor() {
        public void process(Exchange exchange) throws Exception {
            String beanName = exchange.getHeader("beanNameHeader");
        }
    });
    }
}

但是,在存储提取的beanName时,请注意范围和并发性。

答案 3 :(得分:0)

我的同事(感谢他)找到了明确的解决方案:

  1. 在交换属性中设置bean名称: exchange.setProperty(“myDataFormat”,“myDataFormatAutowiredBean”);

  2. 使用RecipientList模式和(un)marshal检索dataFormat bean:

  3. routedefinition.recipientList(简单( “DATAFORMAT:$ {property.myDataFormat}:编组”)); routedefinition.recipientList(简单( “DATAFORMAT:$ {property.myDataFormat}:解组”));

    非常简洁,工作得很好。