Search code examples
apache-camel

camel splitter - stop looping on specific exception


How can we stop looping on camel splitter on specific exception? The "stopOnException()" is stopping the looping for every exception, but instead I want to stop looping only on some specific exceptions. And if the exception is "HttpOperationFailedException", I want to stop looping based on response code. For example if response code is "500" stop execution and if response code is 404 continue execution.

Is it possible?

Original Question

from("timer:categoryRouter?delay=0")
                    .process(new Processor() {
                        @Override
                        public void process(Exchange exchange) throws Exception {
                            exchange.getIn().setBody("A,F,B,D,C");
                        }
                    })
                // tell Splitter to use the aggregation strategy which handles and ignores exceptions
                .split(body(), new MyIgnoreFailureAggregationStrategy())
                    .stopOnException()
                    // log each splitted message
                    .log("Split line ${body}")
                    // and have them translated into a quote
                    .bean(WordTranslateBean.class)
                    // and send it to a mock
                    .to("mock:split")
                .end()
                // log the outgoing aggregated message
                .log("Aggregated ${body}")
                // and send it to a mock as well
                .to("mock:result");

Bean which throws exception:

public class WordTranslateBean {

private Map<String, String> words = new HashMap<String, String>();

public WordTranslateBean() {
    words.put("A", "Camel rocks");
    words.put("B", "Hi mom");
    words.put("C", "Yes it works");
}

public String translate(String key) throws HttpOperationFailedException {
    if (!words.containsKey(key)) {
        HttpOperationFailedException httpOperationFailedException = null;
        if(key.equals("F")) {
            httpOperationFailedException = new HttpOperationFailedException("uri",500,"Internal Server Error","location",null,"Key not a known word " + key);
        }
        else {
            httpOperationFailedException = new HttpOperationFailedException("uri",404,"Resource Not Found","location",null,"Operation not supported on word " + key);
        }
        throw httpOperationFailedException;
    }
    return words.get(key);
}

}

Working Solution:

from("timer:categoryRouter?delay=0")
                    .process(new Processor() {
                        @Override
                        public void process(Exchange exchange) throws Exception {
                            exchange.getIn().setBody("A,F,B,D,C");
                        }
                    })
                // tell Splitter to use the aggregation strategy which handles and ignores exceptions
                .split(body(), new MyIgnoreFailureAggregationStrategy())
                    .stopOnException()
                    // log each splitted message
                    .log("Split line ${body}")
                    // and have them translated into a quote
                    .doTry()
                        .bean(WordTranslateBean.class)
                        // and send it to a mock
                        .to("mock:split")
                    .doCatch(HttpOperationFailedException.class)
                        .process(new Processor() {
                            @Override
                            public void process(Exchange exchange) throws Exception {
                                HttpOperationFailedException e = (HttpOperationFailedException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
                                if(e.getStatusCode()!=404){
                                    throw e;
                                }
                            }
                        })
                    .end()
                .end()
                // log the outgoing aggregated message
                .log("Aggregated ${body}")
                // and send it to a mock as well
                .to("mock:result");

Solution

  • Why don't you throw a custom exception based on a response code ? That's one option . Basically you can catch the original http exception , check the response code , throw your custom exception. Can you post your route ? It's easy to implement this way, just want to see how you have organised your routes .