0

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

Olaf Kock
  • 46,930
  • 8
  • 59
  • 90

0 Answers0