Package amqp.spring.camel.component

Source Code of amqp.spring.camel.component.SpringAMQPProducer$AMQPProducerTask

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

package amqp.spring.camel.component;

import org.apache.camel.AsyncCallback;
import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultAsyncProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpConnectException;
import org.springframework.amqp.AmqpIOException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;

public class SpringAMQPProducer extends DefaultAsyncProducer {
    private static transient final Logger LOG = LoggerFactory.getLogger(SpringAMQPProducer.class);
   
    protected SpringAMQPEndpoint endpoint;
    private org.springframework.amqp.core.Exchange exchange;
    private ExecutorService threadPool;
   
    public SpringAMQPProducer(SpringAMQPEndpoint endpoint) {
        super(endpoint);
        this.endpoint = endpoint;
    }

    @Override
    public boolean process(Exchange exchange, AsyncCallback callback) {
        if(! isRunAllowed()) {
            if(exchange.getException() == null)
                exchange.setException(new RejectedExecutionException("SpringAMQPProducer not started yet!"));
            callback.done(true);
            return true;
        }
       
        if(this.threadPool == null) {
            if(exchange.getException() == null)
                exchange.setException(new RejectedExecutionException("SpringAMQPProducer is not yet initialized!"));
            callback.done(true);
            return true;
        }
       
        this.threadPool.submit(new AMQPProducerTask(exchange, callback));
        return false;
    }
   
    @Override
    public void process(Exchange exchange) throws Exception {
        if(! isRunAllowed() && exchange.getException() == null) {
            exchange.setException(new RejectedExecutionException("SpringAMQPProducer not started yet!"));
        }
       
        //This is an intentional synchronous invocation of run(), don't mock me
        new AMQPProducerTask(exchange).run();
    }

    @Override
    public void doStart() throws Exception {
        super.doStart();
       
        this.exchange = this.endpoint.createAMQPExchange();
        if (this.endpoint.isUsingDefaultExchange()) {
            LOG.info("Using default exchange of type {}", this.exchange.getClass().getSimpleName());
        } else {
            LOG.info("Declaring exchange {} of type {}", this.exchange.getName(), this.exchange.getClass().getSimpleName());
            try {
                this.endpoint.amqpAdministration.declareExchange(this.exchange);
            } catch(AmqpIOException e) {
                //The actual reason for failed exceptions is often swallowed up by Camel or Spring, find it
                Throwable rootCause = SpringAMQPComponent.findRootCause(e);
                LOG.error("Could not initialize exchange!", rootCause);
                throw e;
            } catch (AmqpConnectException e) {
                LOG.error("Producer cannot connect to broker - stopping endpoint {}", this.endpoint.toString(), e);
                stop();
                this.endpoint.stop();
                return;
            }
        }

        //Initialize execution pool
        //TODO In Camel 2.9+ this becomes ExecutorServiceManager
        this.threadPool = this.endpoint.getCamelContext().getExecutorServiceStrategy().newDefaultThreadPool(this, "amqp-producer");
    }

    @Override
    public void doShutdown() throws Exception {
        super.doShutdown();
       
        if(this.threadPool != null) {
            this.threadPool.shutdown();
            this.threadPool = null;
        }
    }
   
    @Override
    public void doStop() throws Exception {
        super.doStop();
       
        if(this.threadPool != null) {
            this.threadPool.shutdown();
            this.threadPool = null;
        }
    }
   
    private class AMQPProducerTask implements Runnable {
        Exchange exchange;
        AsyncCallback callback;
       
        public AMQPProducerTask(Exchange exchange) {
            this(exchange, null);
        }
       
        public AMQPProducerTask(Exchange exchange, AsyncCallback callback) {
            this.exchange = exchange;
            this.callback = callback;
        }
       
        @Override
        public void run() {
            org.apache.camel.Message message = exchange.getIn();
            SpringAMQPMessage inMessage = new SpringAMQPMessage(message);
            exchange.setIn(inMessage); //Swap out the old message format

            MessageConverter msgConverter;
            if(endpoint.getAmqpTemplate() instanceof RabbitTemplate) {
                RabbitTemplate rabbitTemplate = (RabbitTemplate) endpoint.getAmqpTemplate();
                msgConverter = rabbitTemplate.getMessageConverter();
            } else {
                LOG.warn("Cannot find RabbitMQ AMQP Template, falling back to simple message converter");
                msgConverter = new SimpleMessageConverter();
            }
           
            String routingKeyHeader = message.getHeader(SpringAMQPComponent.ROUTING_KEY_HEADER, String.class);
            String routingKey = routingKeyHeader != null ? routingKeyHeader : endpoint.routingKey;

            try {
                if(exchange.getPattern().isOutCapable()) {
                    LOG.debug("Synchronous send and request for exchange {}", exchange.getExchangeId());
                    Message amqpResponse = endpoint.getAmqpTemplate().sendAndReceive(endpoint.exchangeName, routingKey, inMessage.toAMQPMessage(msgConverter));
                    SpringAMQPMessage camelResponse = SpringAMQPMessage.fromAMQPMessage(msgConverter, amqpResponse);

                    Boolean isExceptionCaught = (Boolean)camelResponse.getHeader(SpringAMQPMessage.IS_EXCEPTION_CAUGHT);
                    if (isExceptionCaught != null && isExceptionCaught.equals(Boolean.TRUE)) {
                        Object caughtObject = camelResponse.getBody();
                        if (caughtObject == null) {
                            exchange.setException(new RuntimeException("Null exception caught from Camel."));
                        } else if (caughtObject instanceof Throwable) {
                            exchange.setException((Throwable)caughtObject);
                        } else {
                            exchange.setException(new RuntimeException(caughtObject.toString()));
                        }
                    } else {
                        exchange.setOut(camelResponse);
                    }
                } else {
                    LOG.debug("Synchronous send for exchange {}", exchange.getExchangeId());
                    endpoint.getAmqpTemplate().send(endpoint.exchangeName, routingKey, inMessage.toAMQPMessage(msgConverter));
                }
            } catch (Throwable t) {
                LOG.error("Could not deliver message via AMQP", t);
            }
           
            if(callback != null)
                callback.done(false);
        }
    }
}
TOP

Related Classes of amqp.spring.camel.component.SpringAMQPProducer$AMQPProducerTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.