I am new to Apache Camel and I am having problems understanding how to implement a simple integration task:
- A REST service is calling a Spring Bean through Apache Camel route
- Spring Bean returns a collection of classes (ArrayList)
I need to iterate over each item in the collection and convert it to another type through the custom converter.
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?
UPDATE 1
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.
So the use case is
- Call some endpoint; e.g a GET request on rest service, in my case:
from("endpoint")
- Call a bean and get it's return value; like
List
,to("bean:someBean")
) - Transform returned value to another
List
- Return transformed
List
to consumer
UPDATE 2
So, I can confirm than using end()
method does not solve my problem.
Here is the code:
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.
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.
you are right with splitter and aggregator, the "Split aggregate request/reply sample" from http://camel.apache.org/splitter.html shows what you need.
Do you need a "converted" list of objects after the splitter? If yes, the point "Using a List in AggregationStrategy" from http://camel.apache.org/aggregator2.html looks right for your needs.
kind regards, soilworker
For future reference, another way you can iterate over a list is using the
loop
construct of the Java DSL. Here's an example:The
LOOP_INDEX
property will contain the current iteration, starting from 0 up to the LIST_LENGHT header value, so you can use it to get the current element from the list.Notice the double
end()
method call: one is for ending the loop and the other one is to end the route.Documentation: http://camel.apache.org/loop.html