问题
I am parsing a CSV file, splitting it and routing it through multiple processors in camel. There are two endpoints , one having erroneous data while other has validated data.
I need suggestion in aggregating the data.
Let's say the CSV file has 10 records out of which 6 reached one endpoint while 4 reached to another. How can I know if all 10 has completed from the file at each endpoint and move ahead of aggregator. I need to create two files one with valid data and other with corrupt data from a single file.
回答1:
Lets look at what the splitter returns.
According to the documentation on Camel 2.2. or older the splitter will by default return the last split message using your example this would probably be the last line to complete its processor so it might not be line 10 (using your example).
On Camel 2.3 and newer the splitter will by default return the original input message i.e. all 10 lines. This is the default behavior and you dont need to code anything for this to work. When the splitter is finished by default it will pass this message along to the next end point.
So if I was using the following DSL on Camel 2.3 or newer:
<camelContext trace="false" id="blueprintContext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="splitExample">
<from uri="timer://myTimer?period=2000"/>
<setBody>
<simple>A\nB\nC</simple>
</setBody>
<log message="The message body before the splitter contains ${body}"/>
<split>
<tokenize token="\n"></tokenize>
<log message="Split line ${body}"/>
</split>
<log message="The message body after the splitter contains ${body}"/>
</route>
</camelContext>
The following would appear in the log:
INFO The message body before the splitter contains
A
B
C
INFO Split line A
INFO Split line B
INFO Split line C
INFO The message body after the splitter contains
A
B
C
As you can see camel by default combines the messages back into one after the splitter returns. To override this behavior you would need to implement your own aggregator. To do so create a class lets call it MyAggregationStrategy
and make the class implement AggregationStrategy
. I used the example in the apache documentation from here. example we will aggregate incoming bids and want to aggregate the highest bid.
private static class MyAggregationStrategy implements AggregationStrategy {
public Exchange aggregate(Exchange oldExchange, Exchange newExchange)
{
if (oldExchange == null)
{
// the first time we only have the new exchange so it wins the first round
return newExchange;
}
int oldPrice = oldExchange.getIn().getBody(Integer.class);
int newPrice = newExchange.getIn().getBody(Integer.class);
// return the "winner" that has the highest price
return newPrice > oldPrice ? newExchange : oldExchange;
}
}
After you have done this you then tell the splitter to use your aggregator by doing the following:
Spring/XML DSL:
<split strategyRef="MyAggregationStrategy ">
In Java:
from("direct:start")
// aggregated by header id and use our own strategy how to aggregate
.aggregate(new MyAggregationStrategy())
Hopefully this gives you enough insight about how the splitter works. In your case I would probably set a header value for each line indicating if it was successful or failed then I would use my customer aggregator to create a new message with failed and success grouped into two lists as the message body. One list with the failed and one list with the completed line items.
This new aggregated message can then be sent to a processor or another endpoint for further processing. For example you can then take the failed list and send that to a route which produces a file. The seda
component can help a lot here.
来源:https://stackoverflow.com/questions/26346772/camel-aggregation-strategy