3 Replies Latest reply on Jul 13, 2017 4:04 AM by byuva

    How to get JMS local transaction with JBOSS AS 7.2.0

    chintan.modha

      Hi All,

       

      I'm trying to obtain JMS local transaction with JBOSS AS 7.2.0, but unfortunately I'm unable to get one. The issue over here is that when I use

       

      session = conn.createQueueSession(true,QueueSession.AUTO_ACKNOWLEDGE);


      the session that I'm getting is not transacted, even when I pass "true" to the createQueueSession(boolean transacted, int acknowledgeMode) method.  I'm not sure what am I doing wrong over here . Also, I'm using IBM WMQ 6 as a JMS provider for this example.

       

      Here's my JMS code, which I'm invoking through a servlet.

       

      package com.example.test;
      
      import javax.jms.JMSException;
      import javax.jms.Message;
      import javax.jms.MessageListener;
      import javax.jms.Queue;
      import javax.jms.QueueConnection;
      import javax.jms.QueueConnectionFactory;
      import javax.jms.QueueReceiver;
      import javax.jms.QueueSession;
      import javax.jms.TextMessage;
      import javax.naming.Context;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      
      public class QueueConnectionTest implements MessageListener{
         
          private String jndiConnectionFactoryName = null;
          private String jndiQueueName = null;
          private QueueConnectionFactory factory = null;
          private QueueConnection conn = null;
          private QueueReceiver receiver = null;
          private QueueSession session = null;
          private Queue testQueue = null;
         
          public QueueConnectionTest(String jndiConnectionFactoryName, String jndiQueueName){
              this.jndiConnectionFactoryName = jndiConnectionFactoryName;
              this.jndiQueueName = jndiQueueName;       
          }
         
          public void initilize(){
              if(this.jndiConnectionFactoryName!=null && this.jndiQueueName!=null){
                  try{
                      Context context = new InitialContext();
                      factory = (QueueConnectionFactory) context.lookup(this.jndiConnectionFactoryName);
                      if(factory!=null){
                          testQueue = (Queue) context.lookup(this.jndiQueueName);
                          if(factory!=null && testQueue!=null){
                              conn =  factory.createQueueConnection();
                              session = conn.createQueueSession(true,QueueSession.AUTO_ACKNOWLEDGE);
                              receiver = session.createReceiver(testQueue);
                              receiver.setMessageListener(this);
                              conn.start();
                              System.out.println(":::: Receiver STARTED for accepting messages ::::");                   
                          }   
                      }
                  }catch(NamingException nx){
                      nx.printStackTrace();
                  }catch(JMSException ex){
                      ex.printStackTrace();
                  }
              }
          }   
         
         
          public void onMessage(Message msg) {
              // TODO Auto-generated method stub
              if(msg!=null && msg instanceof TextMessage){
                  TextMessage txtMsg = (TextMessage)msg;
                  try {
                      System.out.println("Got Message : "+txtMsg.getText());
                      System.out.println("Is session transacted...."+session.getTransacted());               
                  } catch (JMSException e) {
                      e.printStackTrace();
                  }
              }
          }   
      
      }
      
      
      

       

      Here's my servlet code which initializes and starts the inbound message receiver.

       

      package com.scholastic.test;
      import java.io.IOException;
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      /**
      * Servlet implementation class ConnectionServlet
      */
      @WebServlet("/ConnectionServlet")
      public class ConnectionServlet extends HttpServlet {
          private static final long serialVersionUID = 1L;
            
          /**
           * @see HttpServlet#HttpServlet()
           */
          public ConnectionServlet() {
              super();
              // TODO Auto-generated constructor stub
          }
      
          /**
           * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
           */
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // TODO Auto-generated method stub
              doPost(request,response);
          }
      
          /**
           * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
           */
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // TODO Auto-generated method stub
              QueueConnectionTest qConn = new QueueConnectionTest("jboss/jms/BPJMSQueueConnectionFactory","jboss/jms/BPJMSInboundQueue");
              qConn.initilize();       
          }
      
      }
      
      

       

      I'm also attaching the WMQ resource adapter configuration, which I have used for standalone-full.xml

       

      <subsystem xmlns="urn:jboss:domain:resource-adapters:1.1">
          <resource-adapters>
              <resource-adapter>
                  <archive>wmq.jmsra.rar</archive>
                  <transaction-support>LocalTransaction</transaction-support>
                  <config-property name="traceEnabled">true</config-property>
                  <config-property name="traceLevel">3</config-property>
                  <connection-definitions>
                      <connection-definition class-name="com.ibm.mq.connector.outbound.ManagedQueueConnectionFactoryImpl" jndi-name="java:jboss/jms/BPJMSQueueConnectionFactory" enabled="true" use-java-context="true" pool-name="BPJMSQueueConnectionFactoryPool">
                          <config-property name="port">1417</config-property>
                          <config-property name="hostName">xx.xx.xx.xxx</config-property>
                          <config-property name="channel">MQ.CLIENT</config-property>
                          <config-property name="transportType">CLIENT</config-property>
                          <config-property name="queueManager">MYQGMR</config-property>
                          <pool>
                              <min-pool-size>1</min-pool-size>
                              <max-pool-size>10</max-pool-size>
                          </pool>
                      </connection-definition>                       
                  </connection-definitions>
                  <admin-objects>
                      <admin-object class-name="com.ibm.mq.connector.outbound.MQQueueProxy" jndi-name="java:jboss/jms/BPJMSInboundQueue" enabled="true" use-java-context="true" pool-name="BPJMSInboundQueuePool">
                          <config-property name="baseQueueName">INBOUND.QUEUE.TESTING</config-property>
                          <config-property name="baseQueueManagerName">MYQGMR</config-property>
                          <config-property name="targetClient">JMS</config-property>
                      </admin-object>                       
                  </admin-objects>
              </resource-adapter>
          </resource-adapters>
      </subsystem>
      
      

       

      so whenever I run my test, I always get the below message in the logs

       

      13:45:56,735 INFO  [stdout] (http-localhost/192.168.245.128:8080-1) Got Message : Hello

       

      13:45:56,735 INFO  [stdout] (http-localhost/192.168.245.128:8080-1) Is session transacted....false

       

      Can someone please help me out in how to obtain transacted session ? I appreciate any insights on this is particular issue.

       

      Regard,

      Chintan

        • 1. Re: How to get JMS local transaction with JBOSS AS 7.2.0
          ybxiang.china

          You send message in servlet has NO transaction around!

          Your sevlet can call am EJB session which can be used to send your JMS.

           

          I hope bellow code snippet is useful to you:

           

          (a) get userTransabtion in EJB session:

           

          @Local(IGprsServerSocketService.class)

          @Singleton

          @Startup

          public class GprsServerSocketService implements IGprsServerSocketService{

          @Inject
          private UserTransaction userTransaction;

           

          (b) use it

           

              try {
             userTransaction.begin();  
             //检查这个NE 是否存在:
             if(! neList.contains(terminatorAddressHexString)){
             log.warn("NE["+terminatorAddressHexString+"]不存在,现在把它加入数据表中...");
             //不要调用com.ybxiang.nms.ejb.session.secure.ISecuredRemoteSession.addNe(Ne, Long),它有权限控制!
             //User u = em.find(User.class, 1L);
             NeGroup group = em.find(NeGroup.class, 1L);
             //
             Ne ne = new Ne();
             ne.setAddressHex(terminatorAddressHexString);
             ne.setName(terminatorAddressHexString);
             //ne.setCreator(u);
             ne.setGroup(group);
             ne.setLatestHeartBeat(new Date());//心跳!
             Ne freshNe = em.merge(ne);
             log.debug(freshNe.getId());
             //
             neList.add(terminatorAddressHexString);//首先添加到neList之中!
             }else{
             log.info("updateHearBeat:"+terminatorAddressHexString);      
             em.createQuery("UPDATE "+ Ne.class.getName()+ " obj SET obj."+Ne.FIELD_NAME_HEART_BEAT+"=:_hearBeat WHERE obj."+Ne.FIELD_NAME_ADDRESS_HEX+"=:_addressHex")
             .setParameter("_hearBeat",new Date())
             .setParameter("_addressHex",terminatorAddressHexString)
             .executeUpdate();
             }
            
            
             userTransaction.commit();
              } catch (Exception e) {
             log.error("updateHearBeat Exception:",e);
             neList.remove(terminatorAddressHexString);
              } finally {
                  try {
                      if (userTransaction.getStatus() == Status.STATUS_ACTIVE)
                          userTransaction.rollback();
                  } catch (Throwable e) {
                      log.error(e);
                  }
              }
          1 of 1 people found this helpful
          • 2. Re: How to get JMS local transaction with JBOSS AS 7.2.0
            chintan.modha

            Thank you Xiang for the prompt reply and for your suggestions. I'm looking here to obtain local JMS transaction, without using UserTransaction.To my knowledge UserTransaction and local JMS transaction are two different things. Also, I'm looking to not have an EJB as EJB's tend to be heavy as compared to lightweight POJO which uses JMS.

             

            Regards,

            Chintan

            • 3. Re: How to get JMS local transaction with JBOSS AS 7.2.0
              byuva

              Hello, we have same issue, please let us know if u found any solution for this.