/** Strategy to determine if the exchange is done so we can continue */ protected boolean isDone(Exchange exchange) { boolean answer = isCancelledOrInterrupted(exchange); // only done if the exchange hasn't failed // and it has not been handled by the failure processor // or we are exhausted if (!answer) { answer = exchange.getException() == null || ExchangeHelper.isFailureHandled(exchange) || ExchangeHelper.isRedeliveryExhausted(exchange); } log.trace("Is exchangeId: {} done? {}", exchange.getExchangeId(), answer); return answer; }
/** * Common work which must be done when we are done multicasting. * * <p>This logic applies for both running synchronous and asynchronous as there are multiple exist * points when using the asynchronous routing engine. And therefore we want the logic in one * method instead of being scattered. * * @param original the original exchange * @param subExchange the current sub exchange, can be <tt>null</tt> for the synchronous part * @param pairs the pairs with the exchanges to process * @param callback the callback * @param doneSync the <tt>doneSync</tt> parameter to call on callback * @param forceExhaust whether or not error handling is exhausted */ protected void doDone( Exchange original, Exchange subExchange, final Iterable<ProcessorExchangePair> pairs, AsyncCallback callback, boolean doneSync, boolean forceExhaust) { // we are done so close the pairs iterator if (pairs != null && pairs instanceof Closeable) { IOHelper.close((Closeable) pairs, "pairs", LOG); } AggregationStrategy strategy = getAggregationStrategy(subExchange); // invoke the on completion callback if (strategy instanceof CompletionAwareAggregationStrategy) { ((CompletionAwareAggregationStrategy) strategy).onCompletion(subExchange); } // cleanup any per exchange aggregation strategy removeAggregationStrategyFromExchange(original); // we need to know if there was an exception, and if the stopOnException option was enabled // also we would need to know if any error handler has attempted redelivery and exhausted boolean stoppedOnException = false; boolean exception = false; boolean exhaust = forceExhaust || subExchange != null && (subExchange.getException() != null || ExchangeHelper.isRedeliveryExhausted(subExchange)); if (original.getException() != null || subExchange != null && subExchange.getException() != null) { // there was an exception and we stopped stoppedOnException = isStopOnException(); exception = true; } // must copy results at this point if (subExchange != null) { if (stoppedOnException) { // if we stopped due an exception then only propagte the exception original.setException(subExchange.getException()); } else { // copy the current result to original so it will contain this result of this eip ExchangeHelper.copyResults(original, subExchange); } } // .. and then if there was an exception we need to configure the redelivery exhaust // for example the noErrorHandler will not cause redelivery exhaust so if this error // handled has been in use, then the exhaust would be false (if not forced) if (exception) { // multicast uses error handling on its output processors and they have tried to redeliver // so we shall signal back to the other error handlers that we are exhausted and they should // not // also try to redeliver as we will then do that twice original.setProperty(Exchange.REDELIVERY_EXHAUSTED, exhaust); } callback.done(doneSync); }