use of org.apache.camel.AsyncProcessor in project camel by apache.
the class MulticastProcessor method doProcessSequential.
private boolean doProcessSequential(final Exchange original, final AtomicExchange result, final Iterable<ProcessorExchangePair> pairs, final Iterator<ProcessorExchangePair> it, final ProcessorExchangePair pair, final AsyncCallback callback, final AtomicInteger total) {
boolean sync = true;
final Exchange exchange = pair.getExchange();
Processor processor = pair.getProcessor();
final Producer producer = pair.getProducer();
TracedRouteNodes traced = exchange.getUnitOfWork() != null ? exchange.getUnitOfWork().getTracedRouteNodes() : null;
// compute time taken if sending to another endpoint
final StopWatch watch = producer != null ? new StopWatch() : null;
try {
// prepare tracing starting from a new block
if (traced != null) {
traced.pushBlock();
}
if (producer != null) {
EventHelper.notifyExchangeSending(exchange.getContext(), exchange, producer.getEndpoint());
}
// let the prepared process it, remember to begin the exchange pair
AsyncProcessor async = AsyncProcessorConverterHelper.convert(processor);
pair.begin();
sync = async.process(exchange, new AsyncCallback() {
public void done(boolean doneSync) {
// we are done with the exchange pair
pair.done();
// okay we are done, so notify the exchange was sent
if (producer != null) {
long timeTaken = watch.stop();
Endpoint endpoint = producer.getEndpoint();
// emit event that the exchange was sent to the endpoint
EventHelper.notifyExchangeSent(exchange.getContext(), exchange, endpoint, timeTaken);
}
// we only have to handle async completion of the routing slip
if (doneSync) {
return;
}
// continue processing the multicast asynchronously
Exchange subExchange = exchange;
// Decide whether to continue with the multicast or not; similar logic to the Pipeline
// remember to test for stop on exception and aggregate before copying back results
boolean continueProcessing = PipelineHelper.continueProcessing(subExchange, "Sequential processing failed for number " + total.get(), LOG);
if (stopOnException && !continueProcessing) {
if (subExchange.getException() != null) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, subExchange.getException()));
} else {
// we want to stop on exception, and the exception was handled by the error handler
// this is similar to what the pipeline does, so we should do the same to not surprise end users
// so we should set the failed exchange as the result and be done
result.set(subExchange);
}
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
try {
if (parallelAggregate) {
doAggregateInternal(getAggregationStrategy(subExchange), result, subExchange);
} else {
doAggregate(getAggregationStrategy(subExchange), result, subExchange);
}
} catch (Throwable e) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, e));
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
total.incrementAndGet();
// maybe there are more processors to multicast
while (it.hasNext()) {
// prepare and run the next
ProcessorExchangePair pair = it.next();
subExchange = pair.getExchange();
updateNewExchange(subExchange, total.get(), pairs, it);
boolean sync = doProcessSequential(original, result, pairs, it, pair, callback, total);
if (!sync) {
LOG.trace("Processing exchangeId: {} is continued being processed asynchronously", original.getExchangeId());
return;
}
// Decide whether to continue with the multicast or not; similar logic to the Pipeline
// remember to test for stop on exception and aggregate before copying back results
continueProcessing = PipelineHelper.continueProcessing(subExchange, "Sequential processing failed for number " + total.get(), LOG);
if (stopOnException && !continueProcessing) {
if (subExchange.getException() != null) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, subExchange.getException()));
} else {
// we want to stop on exception, and the exception was handled by the error handler
// this is similar to what the pipeline does, so we should do the same to not surprise end users
// so we should set the failed exchange as the result and be done
result.set(subExchange);
}
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
// must catch any exceptions from aggregation
try {
if (parallelAggregate) {
doAggregateInternal(getAggregationStrategy(subExchange), result, subExchange);
} else {
doAggregate(getAggregationStrategy(subExchange), result, subExchange);
}
} catch (Throwable e) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, e));
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
total.incrementAndGet();
}
// do the done work
subExchange = result.get() != null ? result.get() : null;
doDone(original, subExchange, pairs, callback, false, true);
}
});
} finally {
// pop the block so by next round we have the same staring point and thus the tracing looks accurate
if (traced != null) {
traced.popBlock();
}
}
return sync;
}
use of org.apache.camel.AsyncProcessor in project camel by apache.
the class Enricher method process.
/**
* Enriches the input data (<code>exchange</code>) by first obtaining
* additional data from an endpoint represented by an endpoint
* <code>producer</code> and second by aggregating input data and additional
* data. Aggregation of input data and additional data is delegated to an
* {@link AggregationStrategy} object set at construction time. If the
* message exchange with the resource endpoint fails then no aggregation
* will be done and the failed exchange content is copied over to the
* original message exchange.
*
* @param exchange input data.
*/
public boolean process(final Exchange exchange, final AsyncCallback callback) {
// which producer to use
final Producer producer;
final Endpoint endpoint;
// use dynamic endpoint so calculate the endpoint to use
Object recipient = null;
try {
recipient = expression.evaluate(exchange, Object.class);
endpoint = resolveEndpoint(exchange, recipient);
// acquire the consumer from the cache
producer = producerCache.acquireProducer(endpoint);
} catch (Throwable e) {
if (isIgnoreInvalidEndpoint()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Endpoint uri is invalid: " + recipient + ". This exception will be ignored.", e);
}
} else {
exchange.setException(e);
}
callback.done(true);
return true;
}
final Exchange resourceExchange = createResourceExchange(exchange, ExchangePattern.InOut);
final Endpoint destination = producer.getEndpoint();
EventHelper.notifyExchangeSending(exchange.getContext(), resourceExchange, destination);
// record timing for sending the exchange using the producer
final StopWatch watch = new StopWatch();
AsyncProcessor ap = AsyncProcessorConverterHelper.convert(producer);
boolean sync = ap.process(resourceExchange, new AsyncCallback() {
public void done(boolean doneSync) {
// we only have to handle async completion of the routing slip
if (doneSync) {
return;
}
// emit event that the exchange was sent to the endpoint
long timeTaken = watch.stop();
EventHelper.notifyExchangeSent(resourceExchange.getContext(), resourceExchange, destination, timeTaken);
if (!isAggregateOnException() && resourceExchange.isFailed()) {
// copy resource exchange onto original exchange (preserving pattern)
copyResultsPreservePattern(exchange, resourceExchange);
} else {
prepareResult(exchange);
try {
// prepare the exchanges for aggregation
ExchangeHelper.prepareAggregation(exchange, resourceExchange);
Exchange aggregatedExchange = aggregationStrategy.aggregate(exchange, resourceExchange);
if (aggregatedExchange != null) {
// copy aggregation result onto original exchange (preserving pattern)
copyResultsPreservePattern(exchange, aggregatedExchange);
}
} catch (Throwable e) {
// if the aggregationStrategy threw an exception, set it on the original exchange
exchange.setException(new CamelExchangeException("Error occurred during aggregation", exchange, e));
callback.done(false);
// we failed so break out now
return;
}
}
// set property with the uri of the endpoint enriched so we can use that for tracing etc
exchange.setProperty(Exchange.TO_ENDPOINT, producer.getEndpoint().getEndpointUri());
// return the producer back to the cache
try {
producerCache.releaseProducer(endpoint, producer);
} catch (Exception e) {
// ignore
}
callback.done(false);
}
});
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());
// emit event that the exchange was sent to the endpoint
long timeTaken = watch.stop();
EventHelper.notifyExchangeSent(resourceExchange.getContext(), resourceExchange, destination, timeTaken);
if (!isAggregateOnException() && resourceExchange.isFailed()) {
// copy resource exchange onto original exchange (preserving pattern)
copyResultsPreservePattern(exchange, resourceExchange);
} else {
prepareResult(exchange);
try {
// prepare the exchanges for aggregation
ExchangeHelper.prepareAggregation(exchange, resourceExchange);
Exchange aggregatedExchange = aggregationStrategy.aggregate(exchange, resourceExchange);
if (aggregatedExchange != null) {
// copy aggregation result onto original exchange (preserving pattern)
copyResultsPreservePattern(exchange, aggregatedExchange);
}
} catch (Throwable e) {
// if the aggregationStrategy threw an exception, set it on the original exchange
exchange.setException(new CamelExchangeException("Error occurred during aggregation", exchange, e));
callback.done(true);
// we failed so break out now
return true;
}
}
// set property with the uri of the endpoint enriched so we can use that for tracing etc
exchange.setProperty(Exchange.TO_ENDPOINT, producer.getEndpoint().getEndpointUri());
// return the producer back to the cache
try {
producerCache.releaseProducer(endpoint, producer);
} catch (Exception e) {
// ignore
}
callback.done(true);
return true;
}
use of org.apache.camel.AsyncProcessor in project opennms by OpenNMS.
the class SyslogReceiverCamelNettyImpl method run.
/**
* The execution context.
*/
@Override
public void run() {
// Setup logging and create the dispatcher
super.run();
SimpleRegistry registry = new SimpleRegistry();
// Adding netty component to camel in order to resolve OSGi loading issues
NettyComponent nettyComponent = new NettyComponent();
m_camel = new DefaultCamelContext(registry);
// Set the context name so that it shows up nicely in JMX
//
// @see org.apache.camel.management.DefaultManagementNamingStrategy
//
// m_camel.setManagementName("org.opennms.features.events.syslog.listener");
m_camel.setName("syslogdListenerCamelNettyContext");
m_camel.setManagementNameStrategy(new DefaultManagementNameStrategy(m_camel, "#name#", null));
m_camel.addComponent("netty4", nettyComponent);
m_camel.getShutdownStrategy().setShutdownNowOnTimeout(true);
m_camel.getShutdownStrategy().setTimeout(15);
m_camel.getShutdownStrategy().setTimeUnit(TimeUnit.SECONDS);
try {
m_camel.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
String from = String.format("netty4:udp://%s:%d?sync=false&allowDefaultCodec=false&receiveBufferSize=%d&connectTimeout=%d", InetAddressUtils.str(m_host), m_port, Integer.MAX_VALUE, SOCKET_TIMEOUT);
from(from).routeId("syslogListen").process(new AsyncProcessor() {
@Override
public void process(Exchange exchange) throws Exception {
final ByteBuf buffer = exchange.getIn().getBody(ByteBuf.class);
// NettyConstants.NETTY_REMOTE_ADDRESS is a SocketAddress type but because
// we are listening on an InetAddress, it will always be of type InetAddressSocket
InetSocketAddress source = (InetSocketAddress) exchange.getIn().getHeader(NettyConstants.NETTY_REMOTE_ADDRESS);
// Synchronously invoke the dispatcher
m_dispatcher.send(new SyslogConnection(source, buffer.nioBuffer())).get();
}
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
final ByteBuf buffer = exchange.getIn().getBody(ByteBuf.class);
// NettyConstants.NETTY_REMOTE_ADDRESS is a SocketAddress type but because
// we are listening on an InetAddress, it will always be of type InetAddressSocket
InetSocketAddress source = (InetSocketAddress) exchange.getIn().getHeader(NettyConstants.NETTY_REMOTE_ADDRESS);
ByteBuffer bufferCopy = ByteBuffer.allocate(buffer.readableBytes());
buffer.getBytes(buffer.readerIndex(), bufferCopy);
m_dispatcher.send(new SyslogConnection(source, bufferCopy)).whenComplete((r, e) -> {
if (e != null) {
exchange.setException(e);
}
callback.done(false);
});
return false;
}
});
}
});
m_camel.start();
} catch (Throwable e) {
LOG.error("Could not configure Camel routes for syslog receiver", e);
}
}
Aggregations