Apache Camel遍历列表 [英] Apache Camel iterate over List

查看:83
本文介绍了Apache Camel遍历列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to Apache Camel and I am having problems understanding how to implement a simple integration task:

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

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

I need to iterate over each item in the collection and convert it to another type through the custom converter.

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

It seems that I should use Split and an Aggregator, but how do I constraint Aggregator to consume all items from the original list, not more, nor less. Also, how can I convert one item to another? Should I use a Type Converter?

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

Can someone provide me a simple example?

更新1

对不起,我不得不撤消对所提供示例的接受,因为它实际上并未回答我的问题.这是用例资格: 我需要从to("bean:someBean")调用中拆分和转换方法返回值,而不是从某个端点拆分和转换输入值.

Sorry, I had to undo acceptance of the provided example since it is not actually answering to my question. Here is the use case qualification: I need to split and transform a method return value from to("bean:someBean") invocation rather than split and transform input values from some endpoint.

所以用例是

  1. 呼叫某个端点;例如,对休息服务的GET请求,在我的情况下:from("endpoint")
  2. 调用一个bean并获取它的返回值;像Listto("bean:someBean"))
  3. 将返回值转换为另一个List
  4. 将转换后的List返回给消费者
  1. Call some endpoint; e.g a GET request on rest service, in my case: from("endpoint")
  2. Call a bean and get it's return value; like List, to("bean:someBean"))
  3. Transform returned value to another List
  4. Return transformed List to consumer

更新2

因此,我可以确定比使用end()方法不能解决我的问题.

So, I can confirm than using end() method does not solve my problem.

这是代码:

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();

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

Using this kind of route I get the following exception on the application server:

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} -> []]"}}

推荐答案

下面是一个完整的示例,该示例拆分聚合并转换列表消息.

Here is a complete example that splits aggregates and converts a list message.

  1. 骆驼分割器提供了一个内置的聚合器,用于聚合 原始交换中的所有拆分邮件.所以分离器只是 汇总每个列表(交换)的消息,以"direct:start"形式发送.您必须提供一个自定义 聚合策略,因为默认策略将使用原始策略 在我的示例InOrder中进行交换.聚合策略是 分割定义的第二个参数.
  2. 类型转换器使我们有机会在 DSL.您还可以使用bean,处理器来实现这一目标,或者在自定义聚合策略中进行所有转换.

  1. The camel splitter provides a built-in aggregator which aggregates all split messages in the original exchange. So the splitter is only aggregating the messages of each list(exchange) send in "direct:start". You have to provide a custom aggregation strategy because the default one will use the original exchanges, in my example InOrder. The aggregation strategy is the second argument of the split definition.
  2. The type converter gives us the opportunity to use convertBodyTo in DSL. You cound also achieve that with a bean,processor or do all the transformations in the custom aggregation strategy.

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;
        }
    }
}

这篇关于Apache Camel遍历列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆