Apache的骆驼遍历目录(Apache Camel iterate over List)

2019-10-21 07:41发布

我是新来的Apache骆驼和我有理解如何实现一个简单的集成任务的问题:

  1. REST服务通过Apache的骆驼航线调用一个Spring bean
  2. 春豆返回类的集合(ArrayList的)

我需要遍历集合中的每个项目,将其转换为另一种类型的通过自定义转换器。

看来,我应该使用拆分和聚合,但我怎么约束聚合消耗从原来的列表,而不是更多,也不少的所有项目。 此外,我怎么能一个项目转换到另一个? 我应该使用类型转换?

有人可以给我提供一个简单的例子吗?

更新1

对不起,我不得不撤消接受所提供的例子,因为它实际上并没有回答我的问题。 下面是用例的资格:我需要拆分和变换方法的返回值to("bean:someBean")调用,而不是分裂和一些终端转换的输入值。

所以使用情况

  1. 调用一些端点; 例如,在休息的服务,在我的情况GET请求: from("endpoint")
  2. 调用一个bean,并得到它的返回值; 像Listto("bean:someBean")
  3. 变换返回值到另一个List
  4. 返回转换List消费者

更新2

所以,我可以比使用确认end()方法并没有解决我的问题。

下面是代码:

rest("some/service").get().produces("application/json").to("bean:someBean?method=getListOfObjects").route().split(body(), (oldExchange, newExchange) -> {
                List<ObjectToConvert> oldList = oldExchange.getIn(List.class);
                List<NewObject> convertedList = taskList.stream().map(ObjectToConvert::new).collect(Collectors.toList());
                newExchange.getOut().setBody(convertedList);

                return newExchange;
            }).end();

使用这种路线我得到的应用程序服务器上的以下异常:

19:30:21,126 ERROR [org.jboss.as.controller.management-operation] (XNIO-1 task-5) JBAS014613: Operation ("full-replace-deployment") failed - address: (undefined) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./CamundaLearningCamel" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./CamundaLearningCamel: Failed to start service
    Caused by: java.lang.RuntimeException: org.apache.camel.RuntimeCamelException: org.apache.camel.FailedToCreateRouteException: Failed to create route route2 at: >>> Split[{body} -> []] <<< in route: Route(route2)[[From[rest:get:task/all?produces=application%2... because of Definition has no children on Split[{body} -> []]
    Caused by: org.apache.camel.RuntimeCamelException: org.apache.camel.FailedToCreateRouteException: Failed to create route route2 at: >>> Split[{body} -> []] <<< in route: Route(route2)[[From[rest:get:task/all?produces=application%2... because of Definition has no children on Split[{body} -> []]
    Caused by: org.apache.camel.FailedToCreateRouteException: Failed to create route route2 at: >>> Split[{body} -> []] <<< in route: Route(route2)[[From[rest:get:task/all?produces=application%2... because of Definition has no children on Split[{body} -> []]
    Caused by: java.lang.IllegalArgumentException: Definition has no children on Split[{body} -> []]"}}

Answer 1:

这里是一个分裂的聚集和转换列表消息一个完整的例子。

  1. 骆驼分路器提供了一个内置的聚合,其聚合在原有交换所有拆分的消息。 因此,分离器仅聚集每个列表(交换)的消息中发送“直接:启动”。 你必须提供自定义的聚合策略,因为默认的一个将使用原始的交流,在我的例子中序。 聚集策略是分割定义的第二个参数。
  2. 该类型的转换器让我们在DSL使用convertBodyTo的机会。 您还cound实现这一带豆,处理器或做自定义聚合策略所有的转换。

     package org.mydemocamel.app; import org.apache.camel.*; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.processor.aggregate.AggregationStrategy; import org.apache.camel.processor.aggregate.GroupedExchangeAggregationStrategy; import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy; import org.apache.camel.processor.aggregate.UseOriginalAggregationStrategy; import org.apache.camel.support.TypeConverterSupport; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.camel.util.toolbox.FlexibleAggregationStrategy; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class CamelSplitAggregateConvertTest extends CamelTestSupport { @Produce private ProducerTemplate template; @EndpointInject(uri = "mock:out") private MockEndpoint mock; @Test public void testSplitAggregateConvertOrder(){ InOrder inOrder1 = new InOrder(); inOrder1.setId("1"); InOrder inOrder2 = new InOrder(); inOrder2.setId("2"); List<InOrder> inOrderList = new ArrayList<InOrder>(); inOrderList.add(inOrder1); inOrderList.add(inOrder2); template.sendBody("direct:start", inOrderList); mock.expectedMessageCount(1); Exchange outList = mock.getReceivedExchanges().get(0); List<OutOrder> outOrderList = outList.getIn().getBody(List.class); assertEquals(1, outOrderList.get(0).getId()); assertEquals(2, outOrderList.get(1).getId()); } @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { context.getTypeConverterRegistry().addTypeConverter(OutOrder.class, InOrder.class, new MyOrderTypeConverter()); from("direct:start") .split(body(), new AggregationStrategy() { @Override public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { if (oldExchange == null) { List<OutOrder> orders = new ArrayList<OutOrder>(); OutOrder newOrder = newExchange.getIn().getBody(OutOrder.class); orders.add(newOrder); newExchange.getIn().setBody(orders); return newExchange; } List<OutOrder> orders = oldExchange.getIn().getBody(List.class); OutOrder newOutOrder = newExchange.getIn().getBody(OutOrder.class); orders.add(newOutOrder); oldExchange.getIn().setBody(orders); return oldExchange; } }) .convertBodyTo(OutOrder.class) .end() //splitter ends here and the exchange body is now List<OutOrder> .to("mock:out"); } }; } private static class MyOrderTypeConverter extends TypeConverterSupport { @SuppressWarnings("unchecked") public <T> T convertTo(Class<T> type, Exchange exchange, Object value) { // converter from inorder to outorder bean OutOrder order = new OutOrder(); order.setId(Integer.parseInt(((InOrder) value).getId())); return (T) order; } } private static class OutOrder { private int id; public void setId(int id) { this.id = id; } public int getId() { return id; } } private static class InOrder { private String id; public void setId(String id) { this.id = id; } public String getId() { return id; } } } 


Answer 2:

对于未来的参考,你可以遍历一个列表另一种方法是使用loop在Java DSL的结构。 下面是一个例子:

from("direct:myDirect")
.loop(header("LIST_LENGTH")) // You will set this header in the processor before with the list lenght.
.process(new Processor(){

      @Override
      public void proocess(Exchange arg0){
          MyObj currentElement = (MyObj) arg0.getIn().getBody(List.class).get(LOOP_INDEX);
          // Do your processing here.
      }
})
.end()
.end();

LOOP_INDEX属性将包含当前迭代,从0开始到LIST_LENGHT标头值,所以你可以用它来从列表中选择当前元素。

注意双end()方法调用:一个是用于结束循环,并且另一个是结束路由。

文档: http://camel.apache.org/loop.html



Answer 3:

,“拆分总请求/应答样本”从你是对的带分流和聚合http://camel.apache.org/splitter.html显示你所需要的。

你分离器后需要对象的“转换”名单? 如果是的话,点从“使用中AggregationStrategy列表” http://camel.apache.org/aggregator2.html寻找适合您的需求。

亲切的问候,soilworker



文章来源: Apache Camel iterate over List