use of org.apache.camel.AsyncProcessor in project camel by apache.
the class InterceptSendToEndpoint method createProducer.
public Producer createProducer() throws Exception {
producer = delegate.createProducer();
return new DefaultAsyncProducer(delegate) {
public Endpoint getEndpoint() {
return producer.getEndpoint();
}
public Exchange createExchange() {
return producer.createExchange();
}
public Exchange createExchange(ExchangePattern pattern) {
return producer.createExchange(pattern);
}
@Deprecated
public Exchange createExchange(Exchange exchange) {
return producer.createExchange(exchange);
}
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
// process the detour so we do the detour routing
if (LOG.isDebugEnabled()) {
LOG.debug("Sending to endpoint: {} is intercepted and detoured to: {} for exchange: {}", new Object[] { getEndpoint(), detour, exchange });
}
// add header with the real endpoint uri
exchange.getIn().setHeader(Exchange.INTERCEPTED_ENDPOINT, delegate.getEndpointUri());
// detour the exchange using synchronous processing
try {
detour.process(exchange);
} catch (Exception e) {
exchange.setException(e);
}
// check for error if so we should break out
if (!continueProcessing(exchange, "skip sending to original intended destination: " + getEndpoint(), LOG)) {
callback.done(true);
return true;
}
// determine if we should skip or not
boolean shouldSkip = skip;
// if then interceptor had a when predicate, then we should only skip if it matched
Boolean whenMatches = (Boolean) exchange.removeProperty(Exchange.INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED);
if (whenMatches != null) {
shouldSkip = skip && whenMatches;
}
if (!shouldSkip) {
if (exchange.hasOut()) {
// replace OUT with IN as detour changed something
exchange.setIn(exchange.getOut());
exchange.setOut(null);
}
// route to original destination leveraging the asynchronous routing engine if possible
if (producer instanceof AsyncProcessor) {
AsyncProcessor async = (AsyncProcessor) producer;
return async.process(exchange, callback);
} else {
try {
producer.process(exchange);
} catch (Exception e) {
exchange.setException(e);
}
callback.done(true);
return true;
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Stop() means skip sending exchange to original intended destination: {} for exchange: {}", getEndpoint(), exchange);
}
callback.done(true);
return true;
}
}
public boolean isSingleton() {
return producer.isSingleton();
}
public void start() throws Exception {
ServiceHelper.startService(detour);
// here we also need to start the producer
ServiceHelper.startService(producer);
}
public void stop() throws Exception {
// do not stop detour as it should only be stopped when the interceptor stops
// we should stop the producer here
ServiceHelper.stopService(producer);
}
};
}
use of org.apache.camel.AsyncProcessor in project camel by apache.
the class Pipeline method process.
private boolean process(final Exchange original, final Exchange exchange, final AsyncCallback callback, final Iterator<Processor> processors, final AsyncProcessor asyncProcessor) {
// this does the actual processing so log at trace level
LOG.trace("Processing exchangeId: {} >>> {}", exchange.getExchangeId(), exchange);
// implement asynchronous routing logic in callback so we can have the callback being
// triggered and then continue routing where we left
boolean sync = asyncProcessor.process(exchange, new AsyncCallback() {
public void done(boolean doneSync) {
// we only have to handle async completion of the pipeline
if (doneSync) {
return;
}
// continue processing the pipeline asynchronously
Exchange nextExchange = exchange;
while (continueRouting(processors, nextExchange)) {
AsyncProcessor processor = AsyncProcessorConverterHelper.convert(processors.next());
// check for error if so we should break out
if (!continueProcessing(nextExchange, "so breaking out of pipeline", LOG)) {
break;
}
nextExchange = createNextExchange(nextExchange);
doneSync = process(original, nextExchange, callback, processors, processor);
if (!doneSync) {
LOG.trace("Processing exchangeId: {} is continued being processed asynchronously", exchange.getExchangeId());
return;
}
}
ExchangeHelper.copyResults(original, nextExchange);
LOG.trace("Processing complete for exchangeId: {} >>> {}", original.getExchangeId(), original);
callback.done(false);
}
});
return sync;
}
use of org.apache.camel.AsyncProcessor in project camel by apache.
the class Pipeline method process.
public boolean process(Exchange exchange, AsyncCallback callback) {
Iterator<Processor> processors = getProcessors().iterator();
Exchange nextExchange = exchange;
boolean first = true;
while (continueRouting(processors, nextExchange)) {
if (first) {
first = false;
} else {
// prepare for next run
nextExchange = createNextExchange(nextExchange);
}
// get the next processor
Processor processor = processors.next();
AsyncProcessor async = AsyncProcessorConverterHelper.convert(processor);
boolean sync = process(exchange, nextExchange, callback, processors, async);
// continue as long its being processed synchronously
if (!sync) {
LOG.trace("Processing exchangeId: {} is continued being processed asynchronously", exchange.getExchangeId());
// 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", exchange.getExchangeId());
// check for error if so we should break out
if (!continueProcessing(nextExchange, "so breaking out of pipeline", LOG)) {
break;
}
}
// logging nextExchange as it contains the exchange that might have altered the payload and since
// we are logging the completion if will be confusing if we log the original instead
// we could also consider logging the original and the nextExchange then we have *before* and *after* snapshots
LOG.trace("Processing complete for exchangeId: {} >>> {}", exchange.getExchangeId(), nextExchange);
// copy results back to the original exchange
ExchangeHelper.copyResults(exchange, nextExchange);
callback.done(true);
return true;
}
use of org.apache.camel.AsyncProcessor in project camel by apache.
the class RedeliveryErrorHandler method deliverToFailureProcessor.
/**
* All redelivery attempts failed so move the exchange to the dead letter queue
*/
protected boolean deliverToFailureProcessor(final Processor processor, final boolean isDeadLetterChannel, final Exchange exchange, final RedeliveryData data, final AsyncCallback callback) {
boolean sync = true;
Exception caught = exchange.getException();
// we did not success with the redelivery so now we let the failure processor handle it
// clear exception as we let the failure processor handle it
exchange.setException(null);
final boolean shouldHandle = shouldHandle(exchange, data);
final boolean shouldContinue = shouldContinue(exchange, data);
// regard both handled or continued as being handled
boolean handled = false;
// always handle if dead letter channel
boolean handleOrContinue = isDeadLetterChannel || shouldHandle || shouldContinue;
if (handleOrContinue) {
// its handled then remove traces of redelivery attempted
exchange.getIn().removeHeader(Exchange.REDELIVERED);
exchange.getIn().removeHeader(Exchange.REDELIVERY_COUNTER);
exchange.getIn().removeHeader(Exchange.REDELIVERY_MAX_COUNTER);
exchange.removeProperty(Exchange.REDELIVERY_EXHAUSTED);
// and remove traces of rollback only and uow exhausted markers
exchange.removeProperty(Exchange.ROLLBACK_ONLY);
exchange.removeProperty(Exchange.UNIT_OF_WORK_EXHAUSTED);
handled = true;
} else {
// must decrement the redelivery counter as we didn't process the redelivery but is
// handling by the failure handler. So we must -1 to not let the counter be out-of-sync
decrementRedeliveryCounter(exchange);
}
// we should allow using the failure processor if we should not continue
// or in case of continue then the failure processor is NOT a dead letter channel
// because you can continue and still let the failure processor do some routing
// before continue in the main route.
boolean allowFailureProcessor = !shouldContinue || !isDeadLetterChannel;
if (allowFailureProcessor && processor != null) {
// prepare original IN body if it should be moved instead of current body
if (data.useOriginalInMessage) {
log.trace("Using the original IN message instead of current");
Message original = ExchangeHelper.getOriginalInMessage(exchange);
exchange.setIn(original);
if (exchange.hasOut()) {
log.trace("Removing the out message to avoid some uncertain behavior");
exchange.setOut(null);
}
}
// reset cached streams so they can be read again
MessageHelper.resetStreamCache(exchange.getIn());
// invoke custom on prepare
if (onPrepareProcessor != null) {
try {
log.trace("OnPrepare processor {} is processing Exchange: {}", onPrepareProcessor, exchange);
onPrepareProcessor.process(exchange);
} catch (Exception e) {
// a new exception was thrown during prepare
exchange.setException(e);
}
}
log.trace("Failure processor {} is processing Exchange: {}", processor, exchange);
// store the last to endpoint as the failure endpoint
exchange.setProperty(Exchange.FAILURE_ENDPOINT, exchange.getProperty(Exchange.TO_ENDPOINT));
// and store the route id so we know in which route we failed
UnitOfWork uow = exchange.getUnitOfWork();
if (uow != null && uow.getRouteContext() != null) {
exchange.setProperty(Exchange.FAILURE_ROUTE_ID, uow.getRouteContext().getRoute().getId());
}
// fire event as we had a failure processor to handle it, which there is a event for
final boolean deadLetterChannel = processor == data.deadLetterProcessor;
EventHelper.notifyExchangeFailureHandling(exchange.getContext(), exchange, processor, deadLetterChannel, deadLetterUri);
// the failure processor could also be asynchronous
AsyncProcessor afp = AsyncProcessorConverterHelper.convert(processor);
sync = afp.process(exchange, new AsyncCallback() {
public void done(boolean sync) {
log.trace("Failure processor done: {} processing Exchange: {}", processor, exchange);
try {
prepareExchangeAfterFailure(exchange, data, isDeadLetterChannel, shouldHandle, shouldContinue);
// fire event as we had a failure processor to handle it, which there is a event for
EventHelper.notifyExchangeFailureHandled(exchange.getContext(), exchange, processor, deadLetterChannel, deadLetterUri);
} finally {
// if the fault was handled asynchronously, this should be reflected in the callback as well
data.sync &= sync;
callback.done(data.sync);
}
}
});
} else {
try {
// invoke custom on prepare
if (onPrepareProcessor != null) {
try {
log.trace("OnPrepare processor {} is processing Exchange: {}", onPrepareProcessor, exchange);
onPrepareProcessor.process(exchange);
} catch (Exception e) {
// a new exception was thrown during prepare
exchange.setException(e);
}
}
// no processor but we need to prepare after failure as well
prepareExchangeAfterFailure(exchange, data, isDeadLetterChannel, shouldHandle, shouldContinue);
} finally {
// callback we are done
callback.done(data.sync);
}
}
// create log message
String msg = "Failed delivery for " + ExchangeHelper.logIds(exchange);
msg = msg + ". Exhausted after delivery attempt: " + data.redeliveryCounter + " caught: " + caught;
if (processor != null) {
if (isDeadLetterChannel && deadLetterUri != null) {
msg = msg + ". Handled by DeadLetterChannel: [" + URISupport.sanitizeUri(deadLetterUri) + "]";
} else {
msg = msg + ". Processed by failure processor: " + processor;
}
}
// log that we failed delivery as we are exhausted
logFailedDelivery(false, false, handled, false, isDeadLetterChannel, exchange, msg, data, null);
return sync;
}
use of org.apache.camel.AsyncProcessor in project camel by apache.
the class TryProcessor method process.
public boolean process(Exchange exchange, AsyncCallback callback) {
Iterator<Processor> processors = next().iterator();
Object lastHandled = exchange.getProperty(Exchange.EXCEPTION_HANDLED);
exchange.setProperty(Exchange.EXCEPTION_HANDLED, null);
while (continueRouting(processors, exchange)) {
exchange.setProperty(Exchange.TRY_ROUTE_BLOCK, true);
ExchangeHelper.prepareOutToIn(exchange);
// process the next processor
Processor processor = processors.next();
AsyncProcessor async = AsyncProcessorConverterHelper.convert(processor);
boolean sync = process(exchange, callback, processors, async, lastHandled);
// continue as long its being processed synchronously
if (!sync) {
LOG.trace("Processing exchangeId: {} is continued being processed asynchronously", exchange.getExchangeId());
// 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", exchange.getExchangeId());
}
ExchangeHelper.prepareOutToIn(exchange);
exchange.removeProperty(Exchange.TRY_ROUTE_BLOCK);
exchange.setProperty(Exchange.EXCEPTION_HANDLED, lastHandled);
LOG.trace("Processing complete for exchangeId: {} >>> {}", exchange.getExchangeId(), exchange);
callback.done(true);
return true;
}
Aggregations