Example #1
0
  @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;
  }
Example #2
0
 @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);
   }
 }
Example #3
0
  /**
   * 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);
  }