Java tutorial
/* * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.transport.rabbitmq; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import org.apache.axiom.om.OMOutputFormat; import org.apache.axis2.AxisFault; import org.apache.axis2.context.MessageContext; import org.apache.axis2.transport.MessageFormatter; import org.apache.axis2.transport.base.BaseUtils; import org.apache.axis2.transport.rabbitmq.utils.RabbitMQUtils; import org.apache.axis2.util.MessageProcessorSelector; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.UnsupportedCharsetException; import java.util.Hashtable; import java.util.Map; import java.util.UUID; /** * Class that performs the actual sending of a RabbitMQ AMQP message, */ public class RabbitMQMessageSender { private static final Log log = LogFactory.getLog(RabbitMQMessageSender.class); private Connection connection = null; private String targetEPR = null; private Hashtable<String, String> properties; /** * Create a RabbitMQSender using a ConnectionFactory and target EPR * * @param factory the ConnectionFactory * @param targetEPR the targetAddress */ public RabbitMQMessageSender(ConnectionFactory factory, String targetEPR) { try { this.connection = factory.getConnectionPool(); } catch (IOException e) { handleException("Error while creating connection pool", e); } this.targetEPR = targetEPR; if (!targetEPR.startsWith(RabbitMQConstants.RABBITMQ_PREFIX)) { handleException("Invalid prefix for a AMQP EPR : " + targetEPR); } else { this.properties = BaseUtils.getEPRProperties(targetEPR); } } /** * Perform the creation of exchange/queue and the Outputstream * * @param message the RabbitMQ AMQP message * @param msgContext the Axis2 MessageContext */ public void send(RabbitMQMessage message, MessageContext msgContext) throws AxisRabbitMQException { String exchangeName = null; AMQP.BasicProperties basicProperties = null; byte[] messageBody = null; if (connection != null) { Channel channel = null; String queueName = properties.get(RabbitMQConstants.QUEUE_NAME); String routeKey = properties.get(RabbitMQConstants.QUEUE_ROUTING_KEY); exchangeName = properties.get(RabbitMQConstants.EXCHANGE_NAME); String exchangeType = properties.get(RabbitMQConstants.EXCHANGE_TYPE); String durable = properties.get(RabbitMQConstants.EXCHANGE_DURABLE); String replyTo = properties.get(RabbitMQConstants.RABBITMQ_REPLY_TO); //if the user defined any replyTo value it will be set if (replyTo != null) { message.setReplyTo(replyTo); } try { if (routeKey == null && !"x-consistent-hash".equals(exchangeType)) { log.info("rabbitmq.queue.routing.key property not found. Using queue name as " + "the routing key."); routeKey = queueName; } channel = connection.createChannel(); //Declaring the queue if (queueName != null && !queueName.equals("")) { Boolean queueAvailable = false; try { // check availability of the named queue // if an error is encountered, including if the // queue does not exist and if the queue is // exclusively owned by another connection channel.queueDeclarePassive(queueName); queueAvailable = true; } catch (java.io.IOException e) { log.info("Queue :" + queueName + " not found.Declaring queue."); } if (!queueAvailable) { // Declare the named queue if it does not exists. if (!channel.isOpen()) { channel = connection.createChannel(); } try { channel.queueDeclare(queueName, RabbitMQUtils.isDurableQueue(properties), RabbitMQUtils.isExclusiveQueue(properties), RabbitMQUtils.isAutoDeleteQueue(properties), null); } catch (java.io.IOException e) { handleException("Error while creating queue: " + queueName + e); return; } } } //Declaring the exchange if (exchangeName != null && !exchangeName.equals("")) { Boolean exchangeAvailable = false; try { // check availability of the named exchange // Throws:java.io.IOException - the server will raise a // 404 channel exception if the named exchange does not // exists. channel.exchangeDeclarePassive(exchangeName); exchangeAvailable = true; } catch (java.io.IOException e) { log.info("Exchange :" + exchangeName + " not found.Declaring exchange."); } if (!exchangeAvailable) { // Declare the named exchange if it does not exists. if (!channel.isOpen()) { channel = connection.createChannel(); } try { if (exchangeType != null && !exchangeType.equals("")) { if (durable != null && !durable.equals("")) { channel.exchangeDeclare(exchangeName, exchangeType, Boolean.parseBoolean(durable)); } else { channel.exchangeDeclare(exchangeName, exchangeType, true); } } else { channel.exchangeDeclare(exchangeName, "direct", true); } } catch (java.io.IOException e) { handleException("Error occurred while declaring exchange."); } } if (queueName != null && !"x-consistent-hash".equals(exchangeType)) { // Create bind between the queue & // provided routeKey try { // no need to have configure permission to // perform channel.queueBind channel.queueBind(queueName, exchangeName, routeKey); } catch (java.io.IOException e) { handleException("Error occurred while creating the bind between the queue: " + queueName + " & exchange: " + exchangeName + e); } } } AMQP.BasicProperties.Builder builder = buildBasicProperties(message); // set delivery mode (default is Persistent): 1=NonPersistent , 2=Persistent String deliveryModeString = properties.get(RabbitMQConstants.QUEUE_DELIVERY_MODE); int deliveryMode = 2; if (deliveryModeString != null) { deliveryMode = Integer.parseInt(deliveryModeString); } builder.deliveryMode(deliveryMode); basicProperties = builder.build(); OMOutputFormat format = BaseUtils.getOMOutputFormat(msgContext); MessageFormatter messageFormatter = null; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { messageFormatter = MessageProcessorSelector.getMessageFormatter(msgContext); } catch (AxisFault axisFault) { throw new AxisRabbitMQException("Unable to get the message formatter to use", axisFault); } //server plugging should be enabled before using x-consistent hashing //for x-consistent-hashing only exchangeName, exchangeType and routingKey should be // given. Queue/exchange creation, bindings should be done at the broker try { // generate random value as routeKey if the exchangeType is // x-consistent-hash type if (exchangeType != null && exchangeType.equals("x-consistent-hash")) { routeKey = UUID.randomUUID().toString(); } } catch (UnsupportedCharsetException ex) { handleException("Unsupported encoding " + format.getCharSetEncoding(), ex); } try { messageFormatter.writeTo(msgContext, format, out, false); messageBody = out.toByteArray(); } catch (IOException e) { handleException("IO Error while creating BytesMessage", e); } finally { if (out != null) { out.close(); channel.abort(); } } } catch (IOException e) { handleException("Error while publishing message to the queue ", e); } try { if (connection != null) { try { channel = connection.createChannel(); if (exchangeName != null && exchangeName != "") channel.basicPublish(exchangeName, routeKey, basicProperties, messageBody); else channel.basicPublish("", routeKey, basicProperties, messageBody); } catch (IOException e) { log.error("Error while publishing the message"); } finally { if (channel != null) { channel.close(); } } } } catch (IOException e) { handleException("Error while publishing message to the queue ", e); } } } /** * Close the connection */ public void close() { if (connection != null && connection.isOpen()) { try { connection.close(); } catch (IOException e) { handleException("Error while closing the connection ..", e); } finally { connection = null; } } } /** * Build and populate the AMQP.BasicProperties using the RabbitMQMessage * * @param message the RabbitMQMessage to be used to get the properties * @return AMQP.BasicProperties object */ private AMQP.BasicProperties.Builder buildBasicProperties(RabbitMQMessage message) { AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties().builder(); builder.messageId(message.getMessageId()); builder.contentType(message.getContentType()); builder.replyTo(message.getReplyTo()); builder.correlationId(message.getCorrelationId()); builder.contentEncoding(message.getContentEncoding()); Map<String, Object> headers = message.getHeaders(); headers.put(RabbitMQConstants.SOAP_ACTION, message.getSoapAction()); builder.headers(headers); return builder; } private void handleException(String s) { log.error(s); throw new AxisRabbitMQException(s); } private void handleException(String message, Exception e) { log.error(message, e); throw new AxisRabbitMQException(message, e); } }