Search in sources :

Example 21 with AsyncProcessor

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;
}
Also used : CamelExchangeException(org.apache.camel.CamelExchangeException) AsyncProcessor(org.apache.camel.AsyncProcessor) Processor(org.apache.camel.Processor) AsyncCallback(org.apache.camel.AsyncCallback) StopWatch(org.apache.camel.util.StopWatch) AtomicExchange(org.apache.camel.util.concurrent.AtomicExchange) Exchange(org.apache.camel.Exchange) Producer(org.apache.camel.Producer) Endpoint(org.apache.camel.Endpoint) AsyncProcessor(org.apache.camel.AsyncProcessor) TracedRouteNodes(org.apache.camel.spi.TracedRouteNodes)

Example 22 with AsyncProcessor

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;
}
Also used : Exchange(org.apache.camel.Exchange) DefaultExchange(org.apache.camel.impl.DefaultExchange) CamelExchangeException(org.apache.camel.CamelExchangeException) Producer(org.apache.camel.Producer) Endpoint(org.apache.camel.Endpoint) AsyncProcessor(org.apache.camel.AsyncProcessor) AsyncCallback(org.apache.camel.AsyncCallback) CamelExchangeException(org.apache.camel.CamelExchangeException) StopWatch(org.apache.camel.util.StopWatch)

Example 23 with AsyncProcessor

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);
    }
}
Also used : RouteBuilder(org.apache.camel.builder.RouteBuilder) SimpleRegistry(org.apache.camel.impl.SimpleRegistry) InetSocketAddress(java.net.InetSocketAddress) NettyComponent(org.apache.camel.component.netty4.NettyComponent) AsyncCallback(org.apache.camel.AsyncCallback) ByteBuf(io.netty.buffer.ByteBuf) ByteBuffer(java.nio.ByteBuffer) DefaultCamelContext(org.apache.camel.impl.DefaultCamelContext) Exchange(org.apache.camel.Exchange) DefaultManagementNameStrategy(org.apache.camel.impl.DefaultManagementNameStrategy) AsyncProcessor(org.apache.camel.AsyncProcessor) SyslogConnection(org.opennms.netmgt.syslogd.api.SyslogConnection)

Aggregations

AsyncProcessor (org.apache.camel.AsyncProcessor)23 AsyncCallback (org.apache.camel.AsyncCallback)11 Exchange (org.apache.camel.Exchange)11 Processor (org.apache.camel.Processor)10 Producer (org.apache.camel.Producer)7 Endpoint (org.apache.camel.Endpoint)5 StopWatch (org.apache.camel.util.StopWatch)5 ExchangePattern (org.apache.camel.ExchangePattern)4 FailedToCreateProducerException (org.apache.camel.FailedToCreateProducerException)4 AsyncProducerCallback (org.apache.camel.AsyncProducerCallback)3 CamelExchangeException (org.apache.camel.CamelExchangeException)3 DefaultExchange (org.apache.camel.impl.DefaultExchange)2 TracedRouteNodes (org.apache.camel.spi.TracedRouteNodes)2 AtomicExchange (org.apache.camel.util.concurrent.AtomicExchange)2 ByteBuf (io.netty.buffer.ByteBuf)1 InetSocketAddress (java.net.InetSocketAddress)1 ByteBuffer (java.nio.ByteBuffer)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 CamelContextAware (org.apache.camel.CamelContextAware)1 ErrorHandlerFactory (org.apache.camel.ErrorHandlerFactory)1