我是新来的Apache骆驼和我有理解如何实现一个简单的集成任务的问题:
- REST服务通过Apache的骆驼航线调用一个Spring bean
- 春豆返回类的集合(ArrayList的)
我需要遍历集合中的每个项目,将其转换为另一种类型的通过自定义转换器。
看来,我应该使用拆分和聚合,但我怎么约束聚合消耗从原来的列表,而不是更多,也不少的所有项目。 此外,我怎么能一个项目转换到另一个? 我应该使用类型转换?
有人可以给我提供一个简单的例子吗?
更新1
对不起,我不得不撤消接受所提供的例子,因为它实际上并没有回答我的问题。 下面是用例的资格:我需要拆分和变换方法的返回值to("bean:someBean")
调用,而不是分裂和一些终端转换的输入值。
所以使用情况
- 调用一些端点; 例如,在休息的服务,在我的情况GET请求:
from("endpoint")
- 调用一个bean,并得到它的返回值; 像
List
, to("bean:someBean")
- 变换返回值到另一个
List
- 返回转换
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} -> []]"}}
这里是一个分裂的聚集和转换列表消息一个完整的例子。
- 骆驼分路器提供了一个内置的聚合,其聚合在原有交换所有拆分的消息。 因此,分离器仅聚集每个列表(交换)的消息中发送“直接:启动”。 你必须提供自定义的聚合策略,因为默认的一个将使用原始的交流,在我的例子中序。 聚集策略是分割定义的第二个参数。
该类型的转换器让我们在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; } } }
对于未来的参考,你可以遍历一个列表另一种方法是使用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
,“拆分总请求/应答样本”从你是对的带分流和聚合http://camel.apache.org/splitter.html显示你所需要的。
你分离器后需要对象的“转换”名单? 如果是的话,点从“使用中AggregationStrategy列表” http://camel.apache.org/aggregator2.html寻找适合您的需求。
亲切的问候,soilworker