All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazon.sqs.javamessaging.SQSMessageProducer Maven / Gradle / Ivy

Go to download

The Amazon SQS Java Messaging Library holds the Java Message Service compatible classes, that are used for communicating with Amazon Simple Queue Service.

There is a newer version: 2.1.4
Show newest version
/*
 * Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazon.sqs.javamessaging;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.jms.Destination;
import javax.jms.IllegalStateException;
import javax.jms.InvalidDestinationException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageFormatException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueSender;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazon.sqs.javamessaging.message.SQSBytesMessage;
import com.amazon.sqs.javamessaging.message.SQSMessage;
import com.amazon.sqs.javamessaging.message.SQSObjectMessage;
import com.amazon.sqs.javamessaging.message.SQSTextMessage;
import com.amazon.sqs.javamessaging.message.SQSMessage.JMSMessagePropertyValue;
import com.amazonaws.util.Base64;

import com.amazonaws.services.sqs.model.MessageAttributeValue;
import com.amazonaws.services.sqs.model.SendMessageRequest;

/**
 * A client uses a MessageProducer object to send messages to a queue
 * destination. A MessageProducer object is created by passing a Destination
 * object to a message-producer creation method supplied by a session.
 * 

* A client also has the option of creating a message producer without supplying * a queue destination. In this case, a destination must be provided with every send * operation. *

*/ public class SQSMessageProducer implements MessageProducer, QueueSender { private static final Log LOG = LogFactory.getLog(SQSMessageProducer.class); /** This field is not actually used. */ private long timeToLive; /** This field is not actually used. */ private int defaultPriority; /** This field is not actually used. */ private int deliveryMode; /** This field is not actually used. */ private boolean disableMessageTimestamp; /** This field is not actually used. */ private boolean disableMessageID; /** * State of MessageProducer. * True if MessageProducer is closed. */ final AtomicBoolean closed = new AtomicBoolean(false); private final AmazonSQSMessagingClientWrapper amazonSQSClient; private final SQSQueueDestination sqsDestination; private final SQSSession parentSQSSession; SQSMessageProducer(AmazonSQSMessagingClientWrapper amazonSQSClient, SQSSession parentSQSSession, SQSQueueDestination destination) throws JMSException { this.sqsDestination = destination; this.amazonSQSClient = amazonSQSClient; this.parentSQSSession = parentSQSSession; } void sendInternal(Queue queue, Message message) throws JMSException { checkClosed(); String sqsMessageBody = null; String messageType = null; if (message instanceof SQSMessage) { message.setJMSDestination(queue); if (message instanceof SQSBytesMessage) { sqsMessageBody = Base64.encodeAsString(((SQSBytesMessage) message).getBodyAsBytes()); messageType = SQSMessage.BYTE_MESSAGE_TYPE; } else if (message instanceof SQSObjectMessage) { sqsMessageBody = ((SQSObjectMessage) message).getMessageBody(); messageType = SQSMessage.OBJECT_MESSAGE_TYPE; } else if (message instanceof SQSTextMessage) { sqsMessageBody = ((SQSTextMessage) message).getText(); messageType = SQSMessage.TEXT_MESSAGE_TYPE; } } else { throw new MessageFormatException( "Unrecognized message type. Messages have to be one of: SQSBytesMessage, SQSObjectMessage, or SQSTextMessage"); } if (sqsMessageBody == null || sqsMessageBody.isEmpty()) { throw new JMSException("Message body cannot be null or empty"); } Map messageAttributes = propertyToMessageAttribute((SQSMessage) message); addMessageTypeReservedAttribute(messageAttributes, (SQSMessage) message, messageType); SendMessageRequest sendMessageRequest = new SendMessageRequest(((SQSQueueDestination) queue).getQueueUrl(), sqsMessageBody); sendMessageRequest.setMessageAttributes(messageAttributes); String messageId = amazonSQSClient.sendMessage(sendMessageRequest).getMessageId(); LOG.info("Message sent to SQS with SQS-assigned messageId: " + messageId); /** TODO: Do not support disableMessageID for now.*/ message.setJMSMessageID(String.format(SQSMessagingClientConstants.MESSAGE_ID_FORMAT, messageId)); ((SQSMessage)message).setSQSMessageId(messageId); } @Override public Queue getQueue() throws JMSException { return sqsDestination; } /** * Sends a message to a queue. * * @param queue * the queue destination to send this message to * @param message * the message to send * @throws InvalidDestinationException * If a client uses this method with a destination other than * SQS queue destination. * @throws MessageFormatException * If an invalid message is specified. * @throws UnsupportedOperationException * If a client uses this method with a MessageProducer that * specified a destination at creation time. * @throws JMSException * If session is closed or internal error. */ @Override public void send(Queue queue, Message message) throws JMSException { if (!(queue instanceof SQSQueueDestination)) { throw new InvalidDestinationException( "Incompatible implementation of Queue. Please use SQSQueueDestination implementation."); } checkIfDestinationAlreadySet(); sendInternal(queue, message); } /** * Not verified on the client side, but SQS Attribute names must be valid * letter or digit on the basic multilingual plane in addition to allowing * '_', '-' and '.'. No component of an attribute name may be empty, thus an * attribute name may neither start nor end in '.'. And it may not contain * "..". */ Map propertyToMessageAttribute(SQSMessage message) throws JMSException { Map messageAttributes = new HashMap(); Enumeration propertyNames = message.getPropertyNames(); while (propertyNames.hasMoreElements()) { String propertyName = propertyNames.nextElement(); // This is generated from SQS message attribute "ApproximateReceiveCount" if (propertyName.equals(SQSMessagingClientConstants.JMSX_DELIVERY_COUNT)) { continue; } JMSMessagePropertyValue propertyObject = message.getJMSMessagePropertyValue(propertyName); MessageAttributeValue messageAttributeValue = new MessageAttributeValue(); messageAttributeValue.setDataType(propertyObject.getType()); messageAttributeValue.setStringValue(propertyObject.getStringMessageAttributeValue()); messageAttributes.put(propertyName, messageAttributeValue); } return messageAttributes; } /** * Adds the message type attribute during send as part of the send message * request. */ private void addMessageTypeReservedAttribute(Map messageAttributes, SQSMessage message, String value) throws JMSException { MessageAttributeValue messageAttributeValue = new MessageAttributeValue(); messageAttributeValue.setDataType(SQSMessagingClientConstants.STRING); messageAttributeValue.setStringValue(value); /** * This will override the existing attribute if exists. Everything that * has prefix JMS_ is reserved for JMS Provider, but if the user sets that * attribute, it will be overwritten. */ messageAttributes.put(SQSMessage.JMS_SQS_MESSAGE_TYPE, messageAttributeValue); } /** * Sends a message to a queue. *

* Send does not support deliveryMode, priority, and timeToLive. It will * ignore anything in deliveryMode, priority, and timeToLive. * * @param queue * the queue destination to send this message to * @param message * the message to send * @param deliveryMode * @param priority * @param timeToLive * @throws InvalidDestinationException * If a client uses this method with a destination other than * SQS queue destination. * @throws MessageFormatException * If an invalid message is specified. * @throws UnsupportedOperationException * If a client uses this method with a MessageProducer that * specified a destination at creation time. * @throws JMSException * If session is closed or internal error. */ @Override public void send(Queue queue, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { send(queue, message); } /** * Gets the destination associated with this MessageProducer. * * @return this producer's queue destination */ @Override public Destination getDestination() throws JMSException { return sqsDestination; } /** * Closes the message producer. */ @Override public void close() throws JMSException { if (closed.compareAndSet(false, true)) { parentSQSSession.removeProducer(this); } } /** * Sends a message to a destination created during the creation time of this * message producer. * * @param message * the message to send * @throws MessageFormatException * If an invalid message is specified. * @throws UnsupportedOperationException * If a client uses this method with a MessageProducer that did * not specify a destination at creation time. * @throws JMSException * If session is closed or internal error. */ @Override public void send(Message message) throws JMSException { if (sqsDestination == null) { throw new UnsupportedOperationException( "MessageProducer has to specify a destination at creation time."); } sendInternal((Queue) sqsDestination, message); } /** * Sends a message to a destination created during the creation time of this * message producer. *

* Send does not support deliveryMode, priority, and timeToLive. It will * ignore anything in deliveryMode, priority, and timeToLive. * * @param message * the message to send * @param deliveryMode * @param priority * @param timeToLive * @throws MessageFormatException * If an invalid message is specified. * @throws UnsupportedOperationException * If a client uses this method with a MessageProducer that did * not specify a destination at creation time. * @throws JMSException * If session is closed or internal error. */ @Override public void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { send(message); } /** * Sends a message to a queue destination. * * @param destination * the queue destination to send this message to * @param message * the message to send * @throws InvalidDestinationException * If a client uses this method with a destination other than * valid SQS queue destination. * @throws MessageFormatException * If an invalid message is specified. * @throws UnsupportedOperationException * If a client uses this method with a MessageProducer that * specified a destination at creation time. * @throws JMSException * If session is closed or internal error. */ @Override public void send(Destination destination, Message message) throws JMSException { if (destination == null) { throw new InvalidDestinationException("Destination cannot be null"); } if (destination instanceof SQSQueueDestination) { send((Queue) destination, message); } else { throw new InvalidDestinationException("Incompatible implementation of Destination. Please use SQSQueueDestination implementation."); } } /** * Sends a message to a queue destination. *

* Send does not support deliveryMode, priority, and timeToLive. It will * ignore anything in deliveryMode, priority, and timeToLive. * * @param destination * the queue destination to send this message to * @param message * the message to send * @param deliveryMode * @param priority * @param timeToLive * @throws InvalidDestinationException * If a client uses this method with a destination other than * valid SQS queue destination. * @throws MessageFormatException * If an invalid message is specified. * @throws UnsupportedOperationException * If a client uses this method with a MessageProducer that * specified a destination at creation time. * @throws JMSException * If session is closed or internal error. */ @Override public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { send(destination, message); } /** This method is not supported. */ @Override public void setDisableMessageID(boolean value) throws JMSException { this.disableMessageID = value; } /** This method is not supported. */ @Override public boolean getDisableMessageID() throws JMSException { return disableMessageID; } /** This method is not supported. */ @Override public void setDisableMessageTimestamp(boolean value) throws JMSException { this.disableMessageTimestamp = value; } /** This method is not supported. */ @Override public boolean getDisableMessageTimestamp() throws JMSException { return disableMessageTimestamp; } /** This method is not supported. */ @Override public void setDeliveryMode(int deliveryMode) throws JMSException { this.deliveryMode = deliveryMode; } /** This method is not supported. */ @Override public int getDeliveryMode() throws JMSException { return deliveryMode; } /** This method is not supported. */ @Override public void setPriority(int defaultPriority) throws JMSException { this.defaultPriority = defaultPriority; } /** This method is not supported. */ @Override public int getPriority() throws JMSException { return defaultPriority; } /** This method is not supported. */ @Override public void setTimeToLive(long timeToLive) throws JMSException { this.timeToLive = timeToLive; } /** This method is not supported. */ @Override public long getTimeToLive() throws JMSException { return timeToLive; } void checkClosed() throws IllegalStateException { if (closed.get()) { throw new IllegalStateException("The producer is closed."); } } void checkIfDestinationAlreadySet() { if (sqsDestination != null) { throw new UnsupportedOperationException( "MessageProducer already specified a destination at creation time."); } } /* * Unit Tests Utility Functions */ AtomicBoolean isClosed() { return closed; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy