首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Apache Camel迭代列表

Apache Camel迭代列表
EN

Stack Overflow用户
提问于 2014-11-24 13:03:44
回答 3查看 26.1K关注 0票数 1

我是Apache Camel的新手,我在理解如何实现一个简单的集成任务时遇到了问题:

  1. REST服务正在通过Apache路由调用Spring
  2. Spring返回类集合(ArrayList)

我需要迭代集合中的每一项,并通过自定义转换器将其转换为另一种类型。

我似乎应该使用Split和聚合器,但是如何约束聚合器使用原始列表中的所有项,而不是更多,更少。此外,如何将一个项目转换为另一个项目?我应该使用类型转换器吗?

有人能给我举个简单的例子吗?

更新1

对不起,我不得不撤销对所提供的例子的接受,因为它实际上没有回答我的问题。下面是用例限定:我需要拆分和转换来自to("bean:someBean")调用的方法返回值,而不是从某个端点拆分和转换输入值。

所以用例是

  1. 调用某个端点;例如rest服务上的GET请求,在我的例子中:from("endpoint")
  2. 调用一个bean并获取它的返回值;就像Listto("bean:someBean"))
  3. 将返回值转换为另一个List
  4. 将转换后的List返回给消费者

更新2

所以,我可以肯定比使用end()方法不能解决我的问题。

以下是代码:

代码语言:javascript
复制
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();

使用这种路由,我在应用服务器上得到以下异常:

代码语言:javascript
复制
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} -> []]"}}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-11-24 23:57:36

下面是一个拆分聚合和转换列表消息的完整示例。

  1. camel拆分器提供了一个内置聚合器,用于聚合原始交换中的所有拆分消息。因此,拆分器只是聚合每个列表(Exchange)发送的“直接:开始”中的消息。您必须提供一个自定义聚合策略,因为在我的示例InOrder中,默认策略将使用原始交换。聚合策略是拆分定义的第二个参数。
  2. 类型转换器使我们有机会在DSL中使用convertBodyTo。您还可以使用bean、处理器或执行自定义聚合策略中的所有转换来实现这一点。 包装;进口org.apache.camel.*;进口org.apache.camel.processor.aggregate.GroupedExchangeAggregationStrategy;;进口org.apache.camel.component.mock.MockEndpoint;进口org.apache.camel.processor.aggregate.GroupedExchangeAggregationStrategy;导入org.junit.Test;导入java.util.ArrayList;导入java.util.List;公共类CamelSplitAggregateConvertTest扩展CamelTestSupport {@ ProducerTemplate模板;@EndpointInject(uri =“java.util.List:out”)私有MockEndpoint模拟;@Test (){ InOrder inOrder1 =新InOrder();inOrder1.setId("1");InOrder inOrder2 =新InOrder();inOrder2.setId("2");列表inOrderList =新的ArrayList();inOrderList.add(inOrder1);inOrderList.add(inOrder2);template.sendBody(“直接启动”,inOrderList);mock.expectedMessageCount(1);Exchange = mock.getReceivedExchanges().get(0);List outOrderList = outList.getIn().getBody(List.class);assertEquals(1,outOrderList.get(0).getBody());context.getTypeConverterRegistry().addTypeConverter(OutOrder.class,(2,outOrderList.get(1).getId();}@outOrderList.get受保护的RouteBuilder createRouteBuilder()抛出异常{返回新的RouteBuilder() {@覆盖公共虚配置()抛出异常{outOrderList.get InOrder.class,新MyOrderTypeConverter());从(“直接:开始”) .split(body(),新AggregationStrategy() ){@覆盖公共交换聚合( Exchange oldExchange,Exchange newExchange) { if (oldExchange == null) { List orders =新ArrayList();OutOrder newOrder = newExchange.getIn().getBody(OutOrder.class);orders.add(newOrder);newExchange.getIn().setBody(orders);返回newExchange;} List orders = oldExchange.getIn().getBody(List.class);OutOrder newOutOrder = newExchange.getIn().getBody(OutOrder.class);orders.add(newOutOrder);oldExchange.getIn().setBody(orders);return;}) .convertBodyTo(OutOrder.class) .end() //拆分器在此结束,交换主体现在为List .to(“.end:out”);};}私有静态类MyOrderTypeConverter扩展了TypeConverterSupport { @SuppressWarnings("unchecked")公共T convertTo(类类型、交换、对象值){ //转换器,从convertTo到inorder order =新的OutOrder();order.setId(Integer.parseInt(InOrder)值).getId());返回(T)顺序;}}私有静态类OutOrder {私有int id;公共setId(int id) { this.id = id;}公共int getId() {返回id;}私有静态类InOrder {私有字符串id;公共空setId(字符串id) { this.id = id;}公共字符串getId() {返回id;}
票数 3
EN

Stack Overflow用户

发布于 2016-12-16 09:38:46

对于将来的参考,可以迭代列表的另一种方法是使用Java的loop构造。下面是一个例子:

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2014-11-24 14:48:20

拆分器和聚合器是正确的,来自http://camel.apache.org/splitter.html的“拆分聚合请求/回复示例”显示了您所需要的。

您需要在拆分器之后的“转换”对象列表吗?如果是的话,http://camel.apache.org/aggregator2.html中的“在http://camel.apache.org/aggregator2.html中使用列表”这一点看上去很适合您的需要。

好心的问候,土工

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27105526

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档