@Override public boolean process(Exchange exchange, AsyncCallback callback) { // use atomic integer to be able to pass reference and keep track on the values AtomicInteger index = new AtomicInteger(); AtomicInteger count = new AtomicInteger(); // Intermediate conversion to String is needed when direct conversion to Integer is not // available // but evaluation result is a textual representation of a numeric value. String text = expression.evaluate(exchange, String.class); try { int num = ExchangeHelper.convertToMandatoryType(exchange, Integer.class, text); count.set(num); } catch (NoTypeConversionAvailableException e) { exchange.setException(e); callback.done(true); return true; } // we hold on to the original Exchange in case it's needed for copies final Exchange original = exchange; // per-iteration exchange Exchange target = exchange; // set the size before we start exchange.setProperty(Exchange.LOOP_SIZE, count); // loop synchronously while (index.get() < count.get()) { // and prepare for next iteration // if (!copy) target = exchange; else copy of original target = prepareExchange(exchange, index.get(), original); boolean sync = process(target, callback, index, count, original); if (!sync) { LOG.trace( "Processing exchangeId: {} is continued being processed asynchronously", target.getExchangeId()); // the remainder of the routing slip will be completed async // so we break out now, then the callback will be invoked which then continue routing from // where we left here return false; } LOG.trace( "Processing exchangeId: {} is continued being processed synchronously", target.getExchangeId()); // increment counter before next loop index.getAndIncrement(); } // we are done so prepare the result ExchangeHelper.copyResults(exchange, target); LOG.trace("Processing complete for exchangeId: {} >>> {}", exchange.getExchangeId(), exchange); callback.done(true); return true; }
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") @Override public void process(Exchange exchange) throws Exception { if (exchange.getIn().getBody() instanceof InputStream) { exchange.getIn().setBody(exchange.getContext().getStreamCachingStrategy().cache(exchange)); } Exchange tempExchange = exchange.copy(true); try { for (int retry = 0; retry < endpoint.getMaxTries(); ++retry) { if (endpoint.getRetryDelay() > 0 && retry > 0) { Thread.sleep(endpoint.getRetryDelay()); } endpoint.getTargetProducer().process(tempExchange); if (tempExchange.getException() == null) { onSuccess(tempExchange); return; // success } FailRetryException failure = getExceptionMatching(tempExchange.getException(), FailRetryException.class); if (failure != null) { if (!failure.isConsumed()) { failure.setConsumed(); // make it non-failure for surrounding retries return; // forward exception } } if (getExceptionMatching(tempExchange.getException(), endpoint.getException()) != null) { // retry LOGGER.debug("{} try {} failed", endpoint.getEndpointUri(), retry + 1); tempExchange = exchange.copy(true); if (exchange.getIn().getBody() instanceof StreamCache) { StreamCache is = (StreamCache) exchange.getIn().getBody(); is.reset(); } } else { return; // forward exception } } onExhausted(exchange); tempExchange.setException( new RetryExhaustedException("Retry exhausted", tempExchange.getException())); } finally { ExchangeHelper.copyResults(exchange, tempExchange); } }
/** * 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); }