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

org.hornetq.jms.client.HornetQMessageProducer 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).

There is a newer version: 35.0.0.Beta1
Show newest version
/*
 * Copyright 2005-2014 Red Hat, Inc.
 * Red Hat 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.hornetq.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.hornetq.api.core.HornetQException;
import org.hornetq.api.core.SimpleString;
import org.hornetq.api.core.client.ClientMessage;
import org.hornetq.api.core.client.ClientProducer;
import org.hornetq.api.core.client.ClientSession;
import org.hornetq.api.core.client.SendAcknowledgementHandler;
import org.hornetq.utils.UUID;
import org.hornetq.utils.UUIDGenerator;
/**
 * HornetQ implementation of a JMS MessageProducer.
 *
 * @author Ovidiu Feodorov
 * @author Tim Fox
 * @author Andy Taylor
 */
public class HornetQMessageProducer implements MessageProducer, QueueSender, TopicPublisher
{
   private final HornetQConnection 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 HornetQDestination defaultDestination;
   // Constructors --------------------------------------------------

   protected HornetQMessageProducer(final HornetQConnection connection, final ClientProducer producer,
                                    final HornetQDestination 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 HornetQJMSClientBundle.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 (HornetQException e)
      {
         throw JMSExceptionHelper.convertFromHornetQException(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((HornetQDestination)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((HornetQDestination)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((HornetQDestination)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((HornetQDestination)queue, message, deliveryMode, priority, timeToLive, null);
   }

   public Queue getQueue() throws JMSException
   {
      return (Queue)getDestination();
   }

   // Public --------------------------------------------------------

   @Override
   public String toString()
   {
      return "HornetQMessageProducer->" + 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 HornetQDestination))
      {
         throw new InvalidDestinationException("Not a HornetQ Destination:" + destination);
      }
      if (destination != null && defaultDestination != null)
      {
         throw new UnsupportedOperationException("Cannot specify destination if producer has a default destination");
      }
      if (destination == null)
      {
         throw HornetQJMSClientBundle.BUNDLE.nullTopic();
      }
   }

   private void checkCompletionListener(CompletionListener completionListener)
   {
      if (completionListener == null)
      {
         throw HornetQJMSClientBundle.BUNDLE.nullArgumentNotAllowed("CompletionListener");
      }
   }


   private void doSendx(HornetQDestination 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.BindingQuery query = clientSession.bindingQuery(address);
               if (!query.isExists())
               {
                  throw new InvalidDestinationException("Destination " + address + " does not exist");
               }
               else
               {
                  connection.addKnownDestination(address);
               }
            }
            catch (HornetQException e)
            {
               throw JMSExceptionHelper.convertFromHornetQException(e);
            }
         }
      }

      HornetQMessage hqJmsMessage;

      boolean foreign = false;

      // First convert from foreign message if appropriate
      if (!(jmsMessage instanceof HornetQMessage))
      {
         // 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)
         {
            hqJmsMessage = new HornetQBytesMessage((BytesMessage)jmsMessage, clientSession);
         }
         else if (jmsMessage instanceof MapMessage)
         {
            hqJmsMessage = new HornetQMapMessage((MapMessage)jmsMessage, clientSession);
         }
         else if (jmsMessage instanceof ObjectMessage)
         {
            hqJmsMessage = new HornetQObjectMessage((ObjectMessage)jmsMessage, clientSession);
         }
         else if (jmsMessage instanceof StreamMessage)
         {
            hqJmsMessage = new HornetQStreamMessage((StreamMessage)jmsMessage, clientSession);
         }
         else if (jmsMessage instanceof TextMessage)
         {
            hqJmsMessage = new HornetQTextMessage((TextMessage)jmsMessage, clientSession);
         }
         else
         {
            hqJmsMessage = new HornetQMessage(jmsMessage, clientSession);
         }

         // Set the destination on the original message
         jmsMessage.setJMSDestination(destination);

         foreign = true;
      }
      else
      {
         hqJmsMessage = (HornetQMessage)jmsMessage;
      }

      if (!disableMessageID)
      {
         // Generate a JMS id

         UUID uid = UUIDGenerator.getInstance().generateUUID();

         hqJmsMessage.getCoreMessage().setUserID(uid);

         hqJmsMessage.resetMessageID(null);
      }

      if (foreign)
      {
         jmsMessage.setJMSMessageID(hqJmsMessage.getJMSMessageID());
      }

      hqJmsMessage.setJMSDestination(destination);

      try
      {
         hqJmsMessage.doBeforeSend();
      }
      catch (Exception e)
      {
         JMSException je = new JMSException(e.getMessage());

         je.initCause(e);

         throw je;
      }

      if (defaultDeliveryDelay > 0)
      {
         hqJmsMessage.setJMSDeliveryTime(System.currentTimeMillis() + defaultDeliveryDelay);
      }

      ClientMessage coreMessage = hqJmsMessage.getCoreMessage();
      coreMessage.putStringProperty(HornetQConnection.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 (HornetQException e)
      {
         throw JMSExceptionHelper.convertFromHornetQException(e);
      }
   }

   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 HornetQMessageProducer producer;

      /**
       * @param jmsMessage
       * @param producer
       */
      public CompletionListenerWrapper(CompletionListener listener, Message jmsMessage, HornetQMessageProducer producer)
      {
         this.completionListener = listener;
         this.jmsMessage = jmsMessage;
         this.producer = producer;
      }

      @Override
      public void sendAcknowledged(org.hornetq.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