Search code examples
apache-camelaggregationspring-camel

Apache Camel - split the list, call API and merge the body


I am new to Apache Camel and I would like to ask a few things. Basically, I want to call the API based on the resource ID list I have and combine all the responses from the API into one message. I have already tried AggregationStrategy, but it doesn't seem to be working. The message body always returns the last response from API and it doesn't keep the old list. I would be very grateful if you could give me some examples.

Route

from("file:C:\\Inbound")
//Get resourceID list and split it to call the API
.split(simple("${body}"))
.aggregationStrategy(new ArrayListAggregationStrategy())
.toD("{{api_url}}${body.resourceID}")
.log("After API call ${body}")
.end();

AggregationStrategy

public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {

Object newBody = newExchange.getIn().getBody();

ArrayList<Object> list = null;

if (oldExchange == null) {
    list = new ArrayList<Object>();
    list.add(newBody);
    newExchange.getIn().setBody(list);
    return newExchange;
} else {
    list = oldExchange.getIn().getBody(ArrayList.class);
    list.add(newBody);
    return oldExchange;
}}}

Solution

  • Below you'll find a basic example how to implement .split with AggregationStrategy that returns a Java List. It should be straightforward to apply to your specific scenario.

    Routes.java

    import org.apache.camel.builder.RouteBuilder;
    
    public class Routes {
        public static RouteBuilder routes() {
            return
                new RouteBuilder() {
                    public void configure() {
                        from("timer:mainRouteTrigger?repeatCount=1")
                        .routeId("MainRouteTrigger")
                            .setBody(constant("100\n200\n300"))
                            .to("direct:mainRoute")
                        .end()
                        ;
    
                        from("direct:mainRoute")
                        .routeId("MainRoute")
                            .log("MainRoute BEGINS: BODY: ${body}")
                            .split(body().tokenize("\n"), new Aggregator())
                                .to("direct:singleRoute")
                            .end()
                            .log("MainRoute ENDS: BODY: ${body}")
                        .end()
                        ;
    
                        from("direct:singleRoute")
                        .routeId("SingleRoute")
                            .log("SingleRoute BEGINS: BODY: ${body}")
                            .setBody(simple("this is a response for id ${body}"))
                            .log("SingleRoute ENDS: BODY: ${body}")
                        .end()
                        ;
                    }
                };
        }
    }
    

    Aggregator.java

    import org.apache.camel.AggregationStrategy;
    import org.apache.camel.Exchange;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class Aggregator implements AggregationStrategy {
        @Override
        public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
            // first iteration
            // oldExchange is null
            // body of newExchange is String
            if (oldExchange == null) {
                List<String> newList = buildListFrom(newExchange);
                newExchange.getMessage().setBody(newList, List.class);
                return newExchange;
            }
    
            // second and subsequent iterations
            // body of oldExchange is List<String>
            // body of newExchange is String
            List<String> oldList = oldExchange.getMessage().getBody(List.class);
            List<String> newList = buildListFrom(newExchange);
    
            List<String> combined = Stream.concat(oldList.stream(), newList.stream()).collect(Collectors.toList());
            oldExchange.getMessage().setBody(combined);
    
            return oldExchange;
        }
    
        private List<String> buildListFrom(Exchange exchange) {
            String body = exchange.getMessage().getBody(String.class);
            List<String> list = new ArrayList<String>();
            list.add(body);
            return list;
        }
    }
    

    When executed the following expected outcome is logged:

    AbstractCamelContext  INFO  Routes startup (total:3 started:3)
    AbstractCamelContext  INFO      Started MainRouteTrigger (timer://mainRouteTrigger)
    AbstractCamelContext  INFO      Started MainRoute (direct://mainRoute)
    AbstractCamelContext  INFO      Started SingleRoute (direct://singleRoute)
    AbstractCamelContext  INFO  Apache Camel 3.14.2 (camel-1) started in 133ms (build:14ms init:105ms start:14ms)
    MainSupport           INFO  Waiting until complete: Duration max 5 seconds
    MainRoute             INFO  MainRoute BEGINS: BODY: 100
    200
    300
    SingleRoute           INFO  SingleRoute BEGINS: BODY: 100
    SingleRoute           INFO  SingleRoute ENDS: BODY: this is a response for id 100
    SingleRoute           INFO  SingleRoute BEGINS: BODY: 200
    SingleRoute           INFO  SingleRoute ENDS: BODY: this is a response for id 200
    SingleRoute           INFO  SingleRoute BEGINS: BODY: 300
    SingleRoute           INFO  SingleRoute ENDS: BODY: this is a response for id 300
    MainRoute             INFO  MainRoute ENDS: BODY: [this is a response for id 100, this is a response for id 200, this is a response for id 300]
    MainSupport           INFO  Duration max seconds triggering shutdown of the JVM
    AbstractCamelContext  INFO  Apache Camel 3.14.2 (camel-1) shutting down (timeout:45s)
    AbstractCamelContext  INFO  Routes stopped (total:3 stopped:3)
    AbstractCamelContext  INFO      Stopped SingleRoute (direct://singleRoute)
    AbstractCamelContext  INFO      Stopped MainRoute (direct://mainRoute)
    AbstractCamelContext  INFO      Stopped MainRouteTrigger (timer://mainRouteTrigger)
    AbstractCamelContext  INFO  Apache Camel 3.14.2 (camel-1) shutdown in 34ms (uptime:5s54ms)
    

    Note that

    [this is a response for id 100, this is a response for id 200, this is a response for id 300]
    

    Is a Java List that has been converted to a string automatically by .log.