/**
 * **************************************************************************
 *
 * <p>This code is provided for example purposes only. Oracle does not assume any responsibility or
 * liability for the consequences of using this code. If you choose to use this code for any reason,
 * including but not limited to its use as an example you do so at your own risk and without the
 * support of Oracle.
 *
 * <p>This code is provided under the following licenses:
 *
 * <p>GNU General Public License (GPL-2.0) COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
 * (CDDL-1.0)
 *
 * <p>
 *
 * <p>**************************************************************************** User:
 * jeffrey.a.west Date: Jan 15, 2011 Time: 7:35:04 AM
 */
@MessageDriven(
    messageListenerInterface = MessageListener.class,
    name = "UOOListenerEJB",
    mappedName = "com/oracle/example/jms/uoo/queue",
    activationConfig = {
      @ActivationConfigProperty(
          propertyName = "connectionFactoryJndiName",
          propertyValue = "com/oracle/example/jms/uoo/cf"),
      @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class UOOListenerBean implements MessageListener {
  private final String mdbId = java.util.UUID.randomUUID().toString();

  public UOOListenerBean() {}

  public void onMessage(Message message) {
    if (message instanceof TextMessage) {
      TextMessage msg = (TextMessage) message;

      try {
        String unitOfOrder = message.getStringProperty("JMS_BEA_UnitOfOrder");
        // Sleep for 2 seconds to demonstrate the messages are indeed
        // processes sequentially (in unit-of-order)
        Thread.sleep(2000);
        System.out.println(
            "UOOListener:: MDB=["
                + mdbId
                + "] UOO=["
                + unitOfOrder
                + "] Message=["
                + msg.getText()
                + "]");
      } catch (JMSException e) {
        e.printStackTrace();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}
  /**
   * Create a one time MessageProducer for this JMS OutTransport information. For simplicity and
   * best compatibility, this method uses only JMS 1.0.2b API. Please be cautious when making any
   * changes
   *
   * @return a JMSSender based on one-time use resources
   * @throws JMSException on errors, to be handled and logged by the caller
   */
  public JMSMessageSender createJMSSender(MessageContext msgCtx) throws JMSException {

    // digest the targetAddress and locate CF from the EPR
    loadConnectionFactoryFromProperties();

    // create a one time connection and session to be used
    String user = properties != null ? properties.get(JMSConstants.PARAM_JMS_USERNAME) : null;
    String pass = properties != null ? properties.get(JMSConstants.PARAM_JMS_PASSWORD) : null;

    QueueConnectionFactory qConFac = null;
    TopicConnectionFactory tConFac = null;

    int destType = -1;
    // TODO: there is something missing here for destination type generic
    if (JMSConstants.DESTINATION_TYPE_QUEUE.equals(destinationType)) {
      destType = JMSConstants.QUEUE;
      qConFac = (QueueConnectionFactory) connectionFactory;

    } else if (JMSConstants.DESTINATION_TYPE_TOPIC.equals(destinationType)) {
      destType = JMSConstants.TOPIC;
      tConFac = (TopicConnectionFactory) connectionFactory;
    } else {
      // treat jmsdestination type=queue(default is queue)
      destType = JMSConstants.QUEUE;
      qConFac = (QueueConnectionFactory) connectionFactory;
    }

    if (msgCtx.getProperty(JMSConstants.JMS_XA_TRANSACTION_MANAGER) != null) {
      XAConnection connection = null;
      if (user != null && pass != null) {
        if (qConFac != null) {
          connection = ((XAConnectionFactory) qConFac).createXAConnection(user, pass);
        } else if (tConFac != null) {
          connection = ((XAConnectionFactory) tConFac).createXAConnection(user, pass);
        }
      } else {
        if (qConFac != null) {
          connection = ((XAConnectionFactory) qConFac).createXAConnection();
        } else if (tConFac != null) {
          connection = ((XAConnectionFactory) tConFac).createXAConnection();
        }
      }

      if (connection == null) {
        connection = ((XAConnectionFactory) qConFac).createXAConnection();
      }

      XASession session = null;
      MessageProducer producer = null;

      if (connection != null) {
        if (destType == JMSConstants.QUEUE) {
          session = connection.createXASession();
          producer = session.createProducer(destination);
        } else {
          session = connection.createXASession();
          producer = session.createProducer(destination);
        }
      }

      XAResource xaResource = session.getXAResource();
      TransactionManager tx = null;
      Xid xid1 = null;
      Transaction transaction = null;
      java.util.UUID uuid = java.util.UUID.randomUUID();

      try {
        tx = (TransactionManager) msgCtx.getProperty(JMSConstants.JMS_XA_TRANSACTION_MANAGER);
        transaction = tx.getTransaction();
        msgCtx.setProperty(JMSConstants.JMS_XA_TRANSACTION_MANAGER, tx);
        msgCtx.setProperty(JMSConstants.JMS_XA_TRANSACTION, transaction);
        xid1 =
            new JMSXid(
                JMSConstants.JMS_XA_TRANSACTION_PREFIX.getBytes(StandardCharsets.UTF_8),
                1,
                uuid.toString().getBytes());
        msgCtx.setProperty("XID", xid1);
        xaResource.start(xid1, XAResource.TMNOFLAGS);
      } catch (SystemException e) {
        handleException("Error Occurred during starting getting Transaction.", e);
      } catch (XAException e) {
        handleException("Error Occurred during starting XA resource.", e);
      }
      return new JMSMessageSender(
          connection,
          session,
          producer,
          destination,
          jmsConnectionFactory == null ? this.cacheLevel : jmsConnectionFactory.getCacheLevel(),
          jmsSpecVersion,
          destType == -1 ? null : destType == JMSConstants.QUEUE ? Boolean.TRUE : Boolean.FALSE,
          transaction,
          xid1,
          xaResource);
    } else {
      Connection connection = null;
      if (user != null && pass != null) {
        if (qConFac != null) {
          connection = qConFac.createQueueConnection(user, pass);
        } else if (tConFac != null) {
          connection = tConFac.createTopicConnection(user, pass);
        }
      } else {
        if (qConFac != null) {
          connection = qConFac.createQueueConnection();
        } else if (tConFac != null) {
          connection = tConFac.createTopicConnection();
        }
      }

      if (connection == null) {
        connection = jmsConnectionFactory != null ? jmsConnectionFactory.getConnection() : null;
      }

      Session session = null;
      MessageProducer producer = null;

      if (connection != null) {
        if (destType == JMSConstants.QUEUE) {
          session =
              ((QueueConnection) connection).createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
          producer = ((QueueSession) session).createSender((Queue) destination);
        } else {
          session =
              ((TopicConnection) connection).createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
          producer = ((TopicSession) session).createPublisher((Topic) destination);
        }
      }
      return new JMSMessageSender(
          connection,
          session,
          producer,
          destination,
          jmsConnectionFactory == null ? this.cacheLevel : jmsConnectionFactory.getCacheLevel(),
          jmsSpecVersion,
          destType == -1 ? null : destType == JMSConstants.QUEUE ? Boolean.TRUE : Boolean.FALSE);
    }
  }