javaapache-camelintegration-patterns

Do Camel Splitters preserve exchange body after they execute?


Java 8 and Apache Camel 2.19.5 here. I have the following bean processors:

@Component("foobarResolver")
public class FoobarResolver {
  public List<Foobar> resolve(Fizzbuzz fizzbuzz) {
    List<Foobar> foobars = new ArrayList<Foobar>();

    // Use some logic in here to make the fizzbuzz populate the foobars list.

    return foobars;
  }
}

@Component("fizzbuzzProcessor")
public class FizzbuzzProcessor {
  public FizzbuzzOutput process(Fizzbuzz fizzbuzz) {
    // Blah whatever
  }
}

And the following Camel route:

<route id="fizzbuzzHandler">
  <!-- XML '<fizzbuzz>' messages get sent here by an upstream process -->
  <from uri="activemq:fizzbuzzes"/>

  <!-- Use XStream to deserialize the XML into a 'Fizzbuzz' POJO instance -->
  <unmarshal ref="xs"/>

  <split>
    <method ref="bean:foobarResolver"/>
    <to uri="activemq:analyze"/>
  </split>

  <!-- Now assuming our body is once again the Fizzbuzz we can just continue as normal... -->

  <!-- Process the fizzbuzz -->
  <to uri="bean:fizzbuzzProcessor"/>

  <!-- Send fizzbuzzProcessor's output to 'output' queue -->
  <to uri="activemq:output"/>
</route>

So as you can see, the deserialized Fizzbuzz instance gets sent to the FoobarResolver bean processor, which turns that instance into a List<Foobar> and then sends each Foobar off to the analyze queue, one by one. At least thats the intention of my design anyways!

What I'm curious is: after the split, what does the exchange body become? Does it "revert" back to the Fizzbuzz (which is what I want), or is the exchange body now the List<Foobar> produced by the FoobarResolver (which is NOT what I want)? If the body is now the List<Foobar>, how could I reconfigure things so that the FizzbuzzProcessor receives a Fizzbuzz instead?


Solution

  • It appears to revert to the pre-split body:

    @SpringBootApplication
    public class SocamelApplication extends RouteBuilder implements ApplicationRunner {
        @Autowired
        private FooProcessor fooProcessor;
    
        public static void main(String[] args) {
            SpringApplication.run(SocamelApplication.class, args);
        }
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            Thread.sleep(5000);
        }
    
        @Override
        public void configure() throws Exception {
            from("timer://foo?period=100&repeatCount=1").setBody()
                                                        .constant(Arrays.asList("Hello", "World"))
                                                        .log("1 >>> ${body} ")
                                                        .split(body())
                                                        .log("2 >>> ${body}")
                                                        .bean(fooProcessor)
                                                        .log("3 >>> ${body}")
                                                        .end()
                                                        .log("4 >>> ${body}");
    
        }
    
        @Bean
        public FooProcessor fooProcessor() {
            return new FooProcessor();
        }
    
    }
    
    class FooProcessor implements Processor {
    
        @Override
        public void process(Exchange exchange) throws Exception {
            String reverseMe = exchange.getIn()
                                       .getBody(String.class);
    
            String reversed = new StringBuilder(reverseMe).reverse()
                                                          .toString();
    
            exchange.getOut()
                    .setBody(reversed);
        }
    
    }
    

    Yields:

    1 >>> Hello,World 
    2 >>> Hello
    3 >>> olleH
    2 >>> World
    3 >>> dlroW
    4 >>> Hello,World