I have big file of xml and I want make a split for multiple of elements with Apache Camel
public void configure() {
from("timer://foo?period=30000") // Create a message every 5 seconds
.setProperty("elementTagToSplit", constant("ARTICLE"))
.setBody(constant("<ARTICLE>A</ARTICLE>\r\n"
+ "<ARTICLE>B</ARTICLE>\r\n"
+ "<ORDER>O3</ORDER>\r\n"
+ "<ORDER>O4</ORDER>\r\n"
+ "<ARTICLE>C</ARTICLE>\r\n"
+ "<ARTICLE>D</ARTICLE>\r\n"
+ "<ARTICLE>E</ARTICLE>\r\n"
+ "<ARTICLE>F</ARTICLE>\r\n"
+ "<ARTICLE>G</ARTICLE>\r\n"
+ "<ORDER>O1</ORDER>\r\n"
+ "<ORDER>O2</ORDER>\r\n"
+ "<ORDER>O5</ORDER>\r\n"
+ "<ORDER>O6</ORDER>\r\n"
+ "<ORDER>O7</ORDER>"))
.loop("ARTICLE,ORDER".contains(",") ? "ARTICLE,ORDER".split(",").length : 1)
.process(new SplitterStreamingProcessor("ARTICLE,ORDER"))
.split()
// .method(MyRouteBuilder.class, "extract")
.tokenizeXML("${exchangeProperty.elementTagToSplit}")
.streaming()
.process(exchange -> {
String s = exchange.getIn().getBody(String.class);
System.out.println(s);
System.out.println("------------");
})
.to("log:mylogger");
}
});
static class SplitterStreamingProcessor implements Processor {
private String elementTagName;
/**
* Instantiates a new splitter streaming processor.
*
* @param elementTagName the element tag name
*/
public SplitterStreamingProcessor(String elementTagName) {
this.elementTagName = elementTagName;
}
@Override
public void process(Exchange exchange) throws Exception {
if (!StringUtils.isEmpty(elementTagName)) {
if (elementTagName.contains(",")) {
final Integer loopIndex = exchange.getProperty(Exchange.LOOP_INDEX, Integer.class);
exchange.setProperty("elementTagToSplit", elementTagName.split(",")[loopIndex]);
} else {
exchange.setProperty("elementTagToSplit", elementTagName);
}
System.out.println(exchange.getProperty("elementTagToSplit"));
}
}
My first solution caused memory problem it's with bean that load big list in memory
.split()
.method(MyRouteBuilder.class, "extract")
public static List<String> extract(Exchange exchange) throws Exception {
final String splitToken = exchange.getProperty("elementTagToSplit", String.class);
TokenizeLanguage tok = new TokenizeLanguage();
tok.setXml(true);
tok.setToken(splitToken);
Expression expression = tok.createExpression();
List<String> lista = expression.evaluate(exchange, List.class);
if (lista.isEmpty()) {
throw new Exception();
}
return lista;
}
So i´ve found another way with tokenizeXML
.tokenizeXML("${exchangeProperty.elementTagToSplit}")
My problem is how i can pass variable of exchange in tokenizeXML.
I tried with simple() and constant(), ${header.elementTagToSplit} Is there a way to do the split with streaming mode, and my list will be not all loaded in memory