org.apache.activemq.artemis.jms.client.ActiveMQMessageProducer Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.activemq.artemis.jms.client;
import javax.jms.BytesMessage;
import javax.jms.CompletionListener;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.IllegalStateException;
import javax.jms.InvalidDestinationException;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueSender;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicPublisher;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQInterruptedException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.SendAcknowledgementHandler;
import org.apache.activemq.artemis.utils.UUID;
import org.apache.activemq.artemis.utils.UUIDGenerator;
/**
* ActiveMQ Artemis implementation of a JMS MessageProducer.
*/
public class ActiveMQMessageProducer implements MessageProducer, QueueSender, TopicPublisher {
private final ActiveMQConnection connection;
private final SimpleString connID;
private final ClientProducer clientProducer;
private final ClientSession clientSession;
private boolean disableMessageID = false;
private boolean disableMessageTimestamp = false;
private int defaultPriority = Message.DEFAULT_PRIORITY;
private long defaultTimeToLive = Message.DEFAULT_TIME_TO_LIVE;
private int defaultDeliveryMode = Message.DEFAULT_DELIVERY_MODE;
private long defaultDeliveryDelay = Message.DEFAULT_DELIVERY_DELAY;
private final ActiveMQDestination defaultDestination;
// Constructors --------------------------------------------------
protected ActiveMQMessageProducer(final ActiveMQConnection connection,
final ClientProducer producer,
final ActiveMQDestination defaultDestination,
final ClientSession clientSession) throws JMSException {
this.connection = connection;
connID = connection.getClientID() != null ? new SimpleString(connection.getClientID()) : connection.getUID();
this.clientProducer = producer;
this.defaultDestination = defaultDestination;
this.clientSession = clientSession;
}
// MessageProducer implementation --------------------------------
public void setDisableMessageID(final boolean value) throws JMSException {
checkClosed();
disableMessageID = value;
}
public boolean getDisableMessageID() throws JMSException {
checkClosed();
return disableMessageID;
}
public void setDisableMessageTimestamp(final boolean value) throws JMSException {
checkClosed();
disableMessageTimestamp = value;
}
public boolean getDisableMessageTimestamp() throws JMSException {
checkClosed();
return disableMessageTimestamp;
}
public void setDeliveryMode(final int deliveryMode) throws JMSException {
checkClosed();
if (deliveryMode != DeliveryMode.NON_PERSISTENT && deliveryMode != DeliveryMode.PERSISTENT) {
throw ActiveMQJMSClientBundle.BUNDLE.illegalDeliveryMode(deliveryMode);
}
defaultDeliveryMode = deliveryMode;
}
public int getDeliveryMode() throws JMSException {
checkClosed();
return defaultDeliveryMode;
}
public void setPriority(final int defaultPriority) throws JMSException {
checkClosed();
if (defaultPriority < 0 || defaultPriority > 9) {
throw new JMSException("Illegal priority value: " + defaultPriority);
}
this.defaultPriority = defaultPriority;
}
public int getPriority() throws JMSException {
checkClosed();
return defaultPriority;
}
public void setTimeToLive(final long timeToLive) throws JMSException {
checkClosed();
defaultTimeToLive = timeToLive;
}
public long getTimeToLive() throws JMSException {
checkClosed();
return defaultTimeToLive;
}
public Destination getDestination() throws JMSException {
checkClosed();
return defaultDestination;
}
public void close() throws JMSException {
connection.getThreadAwareContext().assertNotCompletionListenerThread();
try {
clientProducer.close();
}
catch (ActiveMQException e) {
throw JMSExceptionHelper.convertFromActiveMQException(e);
}
}
public void send(final Message message) throws JMSException {
checkDefaultDestination();
doSendx(defaultDestination, message, defaultDeliveryMode, defaultPriority, defaultTimeToLive, null);
}
public void send(final Message message,
final int deliveryMode,
final int priority,
final long timeToLive) throws JMSException {
checkDefaultDestination();
doSendx(defaultDestination, message, deliveryMode, priority, timeToLive, null);
}
public void send(final Destination destination, final Message message) throws JMSException {
send(destination, message, defaultDeliveryMode, defaultPriority, defaultTimeToLive);
}
public void send(final Destination destination,
final Message message,
final int deliveryMode,
final int priority,
final long timeToLive) throws JMSException {
checkClosed();
checkDestination(destination);
doSendx((ActiveMQDestination) destination, message, deliveryMode, priority, timeToLive, null);
}
@Override
public void setDeliveryDelay(long deliveryDelay) throws JMSException {
this.defaultDeliveryDelay = deliveryDelay;
}
@Override
public long getDeliveryDelay() throws JMSException {
return defaultDeliveryDelay;
}
@Override
public void send(Message message, CompletionListener completionListener) throws JMSException {
send(message, defaultDeliveryMode, defaultPriority, defaultTimeToLive, completionListener);
}
@Override
public void send(Message message,
int deliveryMode,
int priority,
long timeToLive,
CompletionListener completionListener) throws JMSException {
checkCompletionListener(completionListener);
checkDefaultDestination();
doSendx(defaultDestination, message, deliveryMode, priority, timeToLive, completionListener);
}
@Override
public void send(Destination destination,
Message message,
CompletionListener completionListener) throws JMSException {
send(destination, message, defaultDeliveryMode, defaultPriority, defaultTimeToLive, completionListener);
}
@Override
public void send(Destination destination,
Message message,
int deliveryMode,
int priority,
long timeToLive,
CompletionListener completionListener) throws JMSException {
checkClosed();
checkCompletionListener(completionListener);
checkDestination(destination);
doSendx((ActiveMQDestination) destination, message, deliveryMode, priority, timeToLive, completionListener);
}
// TopicPublisher Implementation ---------------------------------
public Topic getTopic() throws JMSException {
return (Topic) getDestination();
}
public void publish(final Message message) throws JMSException {
send(message);
}
public void publish(final Topic topic, final Message message) throws JMSException {
send(topic, message);
}
public void publish(final Message message,
final int deliveryMode,
final int priority,
final long timeToLive) throws JMSException {
send(message, deliveryMode, priority, timeToLive);
}
public void publish(final Topic topic,
final Message message,
final int deliveryMode,
final int priority,
final long timeToLive) throws JMSException {
checkDestination(topic);
doSendx((ActiveMQDestination) topic, message, deliveryMode, priority, timeToLive, null);
}
// QueueSender Implementation ------------------------------------
public void send(final Queue queue, final Message message) throws JMSException {
send((Destination) queue, message);
}
public void send(final Queue queue,
final Message message,
final int deliveryMode,
final int priority,
final long timeToLive) throws JMSException {
checkDestination(queue);
doSendx((ActiveMQDestination) queue, message, deliveryMode, priority, timeToLive, null);
}
public Queue getQueue() throws JMSException {
return (Queue) getDestination();
}
// Public --------------------------------------------------------
@Override
public String toString() {
return "ActiveMQMessageProducer->" + clientProducer;
}
/**
* Check if the default destination has been set
*/
private void checkDefaultDestination() {
if (defaultDestination == null) {
throw new UnsupportedOperationException("Cannot specify destination if producer has a default destination");
}
}
/**
* Check if the destination is sent correctly
*/
private void checkDestination(Destination destination) throws InvalidDestinationException {
if (destination != null && !(destination instanceof ActiveMQDestination)) {
throw new InvalidDestinationException("Foreign destination:" + destination);
}
if (destination != null && defaultDestination != null) {
throw new UnsupportedOperationException("Cannot specify destination if producer has a default destination");
}
if (destination == null) {
throw ActiveMQJMSClientBundle.BUNDLE.nullTopic();
}
}
private void checkCompletionListener(CompletionListener completionListener) {
if (completionListener == null) {
throw ActiveMQJMSClientBundle.BUNDLE.nullArgumentNotAllowed("CompletionListener");
}
}
private void doSendx(ActiveMQDestination destination,
final Message jmsMessage,
final int deliveryMode,
final int priority,
final long timeToLive,
CompletionListener completionListener) throws JMSException {
jmsMessage.setJMSDeliveryMode(deliveryMode);
jmsMessage.setJMSPriority(priority);
if (timeToLive == 0) {
jmsMessage.setJMSExpiration(0);
}
else {
jmsMessage.setJMSExpiration(System.currentTimeMillis() + timeToLive);
}
if (!disableMessageTimestamp) {
jmsMessage.setJMSTimestamp(System.currentTimeMillis());
}
else {
jmsMessage.setJMSTimestamp(0);
}
SimpleString address = null;
if (destination == null) {
if (defaultDestination == null) {
throw new UnsupportedOperationException("Destination must be specified on send with an anonymous producer");
}
destination = defaultDestination;
}
else {
if (defaultDestination != null) {
if (!destination.equals(defaultDestination)) {
throw new UnsupportedOperationException("Where a default destination is specified " + "for the sender and a destination is " + "specified in the arguments to the send, " + "these destinations must be equal");
}
}
address = destination.getSimpleAddress();
if (!connection.containsKnownDestination(address)) {
try {
ClientSession.AddressQuery query = clientSession.addressQuery(address);
// if it's autoCreateJMSQueue we will let the PostOffice.route to execute the creation at the server's side
// as that's a more efficient path for such operation
if (!query.isExists() && !query.isAutoCreateJmsQueues()) {
throw new InvalidDestinationException("Destination " + address + " does not exist");
}
else {
connection.addKnownDestination(address);
}
}
catch (ActiveMQException e) {
throw JMSExceptionHelper.convertFromActiveMQException(e);
}
}
}
ActiveMQMessage activeMQJmsMessage;
boolean foreign = false;
// First convert from foreign message if appropriate
if (!(jmsMessage instanceof ActiveMQMessage)) {
// JMS 1.1 Sect. 3.11.4: A provider must be prepared to accept, from a client,
// a message whose implementation is not one of its own.
if (jmsMessage instanceof BytesMessage) {
activeMQJmsMessage = new ActiveMQBytesMessage((BytesMessage) jmsMessage, clientSession);
}
else if (jmsMessage instanceof MapMessage) {
activeMQJmsMessage = new ActiveMQMapMessage((MapMessage) jmsMessage, clientSession);
}
else if (jmsMessage instanceof ObjectMessage) {
activeMQJmsMessage = new ActiveMQObjectMessage((ObjectMessage) jmsMessage, clientSession);
}
else if (jmsMessage instanceof StreamMessage) {
activeMQJmsMessage = new ActiveMQStreamMessage((StreamMessage) jmsMessage, clientSession);
}
else if (jmsMessage instanceof TextMessage) {
activeMQJmsMessage = new ActiveMQTextMessage((TextMessage) jmsMessage, clientSession);
}
else {
activeMQJmsMessage = new ActiveMQMessage(jmsMessage, clientSession);
}
// Set the destination on the original message
jmsMessage.setJMSDestination(destination);
foreign = true;
}
else {
activeMQJmsMessage = (ActiveMQMessage) jmsMessage;
}
if (!disableMessageID) {
// Generate a JMS id
UUID uid = UUIDGenerator.getInstance().generateUUID();
activeMQJmsMessage.getCoreMessage().setUserID(uid);
activeMQJmsMessage.resetMessageID(null);
}
if (foreign) {
jmsMessage.setJMSMessageID(activeMQJmsMessage.getJMSMessageID());
}
activeMQJmsMessage.setJMSDestination(destination);
try {
activeMQJmsMessage.doBeforeSend();
}
catch (Exception e) {
JMSException je = new JMSException(e.getMessage());
je.initCause(e);
throw je;
}
if (defaultDeliveryDelay > 0) {
activeMQJmsMessage.setJMSDeliveryTime(System.currentTimeMillis() + defaultDeliveryDelay);
}
ClientMessage coreMessage = activeMQJmsMessage.getCoreMessage();
coreMessage.putStringProperty(ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME, connID);
try {
/**
* Using a completionListener requires wrapping using a {@link CompletionListenerWrapper},
* so we avoid it if we can.
*/
if (completionListener != null) {
clientProducer.send(address, coreMessage, new CompletionListenerWrapper(completionListener, jmsMessage, this));
}
else {
clientProducer.send(address, coreMessage);
}
}
catch (ActiveMQInterruptedException e) {
JMSException jmsException = new JMSException(e.getMessage());
jmsException.initCause(e);
throw jmsException;
}
catch (ActiveMQException e) {
throw JMSExceptionHelper.convertFromActiveMQException(e);
}
catch (java.lang.IllegalStateException e) {
JMSException je = new IllegalStateException(e.getMessage());
je.setStackTrace(e.getStackTrace());
je.initCause(e);
throw je;
}
}
private void checkClosed() throws JMSException {
if (clientProducer.isClosed() || clientSession.isClosed()) {
throw new IllegalStateException("Producer is closed");
}
}
private static final class CompletionListenerWrapper implements SendAcknowledgementHandler {
private final CompletionListener completionListener;
private final Message jmsMessage;
private final ActiveMQMessageProducer producer;
/**
* @param jmsMessage
* @param producer
*/
public CompletionListenerWrapper(CompletionListener listener,
Message jmsMessage,
ActiveMQMessageProducer producer) {
this.completionListener = listener;
this.jmsMessage = jmsMessage;
this.producer = producer;
}
@Override
public void sendAcknowledged(org.apache.activemq.artemis.api.core.Message clientMessage) {
if (jmsMessage instanceof StreamMessage) {
try {
((StreamMessage) jmsMessage).reset();
}
catch (JMSException e) {
// HORNETQ-1209 XXX ignore?
}
}
if (jmsMessage instanceof BytesMessage) {
try {
((BytesMessage) jmsMessage).reset();
}
catch (JMSException e) {
// HORNETQ-1209 XXX ignore?
}
}
try {
producer.connection.getThreadAwareContext().setCurrentThread(true);
completionListener.onCompletion(jmsMessage);
}
finally {
producer.connection.getThreadAwareContext().clearCurrentThread(true);
}
}
@Override
public String toString() {
return CompletionListenerWrapper.class.getSimpleName() + "( completionListener=" + completionListener + ")";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy