Topic
5 replies Latest Post - ‏2013-07-02T10:00:45Z by pnickoll
mbang
mbang
3 Posts
ACCEPTED ANSWER

Pinned topic Liberty profile 8.5.5 and jms

‏2013-06-16T20:21:24Z |

Hi,

I'm trying to use WAS Liberty profile to connect to MQ on z/OS. I have tried both directly and through a bus defined on a WebSphere application server 8.

The solution uses a temporary queue and I can see that I get a response object of type com.ibm.ws.sib.api.jms.impl.JmsTextMessageImpl, but if I cast it to a javax.jms.TextMessage I get a Null Pointer exception when I access this casted variable. Has anyone tried this and possibly send me in the right direction.

Regards,

Michael

  • pnickoll
    pnickoll
    3 Posts
    ACCEPTED ANSWER

    Re: Liberty profile 8.5.5 and jms

    ‏2013-06-17T14:18:37Z  in response to mbang

    Hi Michael,

    Thanks for posting this info, I'd like to dig deeper into this and try and find the problem but I think I'd need to ask for more information so that I can understand this better. You mention you are trying to connect to MQ on z/OS directly and through a bus defined on WebSphere Application Server 8, could you go into more details on this as we'd like to understand your setup more - for example where are your JMS resources defined, where are messages sent and received from? Any info along these lines might help us see what is happening. Was your plan to use MQ on z/OS directly but since you had problems with that you tried going indirectly via WebSphere Application Server 8? If so would you like us to focus on figuring how to move forward with the direct approach (which I believe would be the simpler option)?

    There does seem to be a combination of using MQ as well as using either the integrated JMS provider or Service Integration bus provider. The message type of com.ibm.ws.sib.api.jms.impl.JmsTextMessageImpl implies the usage of the integrated JMS provider or the Service Integration bus provider but I believe you are trying to create an MQ setup and this may be part of the problem.

    The null pointer exception you experienced, do you have the stack trace for that available as we'd very much like to take a look at that too? Also you say the NPE occurs when you access the cast variable, have you checked if the object is null before you cast?

    In your server.xml file are you defining your JMS resources? If you are attempting to use MQ JMS resources then this document in the info centre may be of use - and please feel free to ask any questions if you want to clarify anything from this document.

    http://www14.software.ibm.com/webapp/wsbroker/redirect?version=phil&product=was-nd-mp&topic=twlp_dep_msg_wmq

    Would we be able to see your server configuration - the server.xml file (or the relevant parts of if)?

    Thanks again for posting this and I hope we can get you past this problem quickly :)

    • mbang
      mbang
      3 Posts
      ACCEPTED ANSWER

      Re: Liberty profile 8.5.5 and jms

      ‏2013-06-26T11:18:39Z  in response to pnickoll

      Hi,

      Thanks for your reply.

      On our developer machines we have 3 WebSphere application server jvms running: Two for some security framework and one for the applications. We would like to make the developer experience better and we are therefore looking at the Liberty profile. First of all we would take the two jvms running the security framework and move to liberty profile. One component in this security framework is using a native java mq solution. The solution uses the native mq classes to access a queue manager on a mainframe. When we look at that solution we can see that we are using a lot of deprecated methods. We would like to change to jms instead of using the native mq classes and also change from making the connection to mq in the code ourselves to use jndi connection factory and queues. I have tried 3 different approaches to get the solution to run from a Liberty profile. First I have tried the native mq method (included the mq classes from the rar file from a WebSphere MQ 7.5.0.1 with APAR IC92914). This works as before.

      The second approach has been to create a Service Integration Bus on a WebSphere 8.0.0.4 with a MQ Link created and an alias for the queue I want to use. This approach uses two channels on the mq server side, one for response and one for reply. The Liberty profile configuration looks like this:

          <!-- Enable features -->

          <featureManager>

              <feature>jsp-2.2</feature>

                               <feature>jndi-1.0</feature>

                               <feature>wasJmsClient-1.1</feature>

                               <feature>wasJmsServer-1.0</feature>

                      <feature>localConnector-1.0</feature>

                  </featureManager>

       

          <httpEndpointhost="localhost" httpPort="9082" httpsPort="9445" id="defaultHttpEndpoint"/>

       

       

          <webContainerdeferServletLoad="false"/>

                 

                  <loggingmaxFileSize="20" maxFiles="10" traceFileName="trace.log" traceFormat="BASIC" traceSpecification="com.ibm.ws.sib*=FINE"/>

                  <jmsQueueConnectionFactoryjndiName="jndi_JMS_BASE_QCF">

                               <properties.wasJmsbusName="JMSBus" remoteServerAddress="testsrv1:7279:BootStrapBasicMessaging" targetTransportChain="InboundBasicMessaging" />

                  </jmsQueueConnectionFactory>

                  <jmsQueuejndiName="jndi_INPUT_Q">

                               <properties.wasJmsqueueName="Q1"/>

                  </jmsQueue>

      I have attached the resources.xml file from the WAS side.

       

      With this approach I get a null pointer exception when I try to access the TextMessage that I receive. I can see that I get a message return, but I seems like it is in a wrong CCSID. Can I set it use the CCSID from the queue ? The error I get is as follows:

      Message sent

      Message type is: class com.ibm.ws.sib.api.jms.impl.JmsTextMessageImpl

      InstanceOf TextMessage: true

      [err] java.lang.NullPointerException

      [WARNING ] WLTC0033W: Resource jndi_JMS_BASE_QCF rolled back in cleanup of LocalTransactionContainment.

      [WARNING ] WLTC0032W: One or more local transaction resources were rolled back during the cleanup of a LocalTransactionContainment.

      [err]       at com.ibm.ws.sib.mfp.impl.JsJmsTextMessageImpl.getText(JsJmsTextMessageImpl.java:128)

      [err]       at [internal classes]

      I have included the program that I'm using to test in the end.

      last I have tried to use a connection directly (using jndi) with a server config as shown below:

      <variablename="wmqJmsClient.rar.location" value="${shared.resource.dir}/wmq.jmsra.rar"/>

       

          <!-- Enable features -->

          <featureManager>

              <feature>jsp-2.2</feature>

                      <feature>localConnector-1.0</feature>

                               <feature>wmqJmsClient-1.1</feature>

                      <feature>wasJmsClient-1.1</feature>

                  <feature>jndi-1.0</feature>

                  </featureManager>

       

          <httpEndpointhost="localhost" httpPort="9082" httpsPort="9445" id="defaultHttpEndpoint"/>

                       

          <jmsQueueConnectionFactoryjndiName="TestQCF" id="TestQCFid">

                  <properties.wmqJmschannel="VPT1.CLIENT" failIfQuiesce="true" hostName="MVS" queueManager="T1" providerVersion="7" targetClientMatching="true" tempQPrefix="TEMP.*"/>

          </jmsQueueConnectionFactory>

          <jmsQueuejndiName="TestQueue">

                  <properties.wmqJmsbaseQueueManagerName="T1" baseQueueName="T1" receiveConversion="QMGR" targetClient="MQ"/>

          </jmsQueue>

      This works as far as I'm able to send a message and get a reply, but this brings me to my second problem. The solution uses the applicationIdData method which is available on a MQMessage. I far as I have found out this information is part of the MQMD structure which needs to be given access to on the queue. I haven't been able to find the right settings to get this working. Any ideas ?

      Test program

      importjava.io.IOException;

      importjava.io.PrintWriter;

       

      importjavax.annotation.Resource;

      importjavax.jms.JMSException;

      importjavax.jms.Message;

      importjavax.jms.Queue;

      importjavax.jms.QueueConnection;

      importjavax.jms.QueueConnectionFactory;

      importjavax.jms.QueueReceiver;

      importjavax.jms.QueueSender;

      importjavax.jms.QueueSession;

      importjavax.jms.Session;

      importjavax.jms.TemporaryQueue;

      importjavax.jms.TextMessage;

      importjavax.servlet.ServletException;

      importjavax.servlet.annotation.WebServlet;

      importjavax.servlet.http.HttpServlet;

      importjavax.servlet.http.HttpServletRequest;

      importjavax.servlet.http.HttpServletResponse;

       

      /**

       * Servlet implementation class ServerCaller

       */

      @WebServlet("/ServerCaller")

      public classServerCaller extendsHttpServlet {

          private static final long serialVersionUID= 1L;

       

          @Resource(name="jndi_JMS_BASE_QCF")

          QueueConnectionFactory factory;

       

          @Resource(name="jndi_INPUT_Q")

          Queue ioQueue;

       

          /**

          * @seeHttpServlet#HttpServlet()

          */

          publicServerCaller() {

              super();

          }

       

          /**

          * @seeHttpServlet#doGet(HttpServletRequest request, HttpServletResponse

          *      response)

          */

          protected voiddoGet(HttpServletRequest request,

              HttpServletResponse response) throwsServletException, IOException {

              PrintWriter writer = response.getWriter();

              writer.print("Invoked");

       

              // Attempt to retrieve a Queue from the JNDI namespace

              QueueConnection connection;

              try{

                  connection = factory.createQueueConnection();

                  connection.start();

                  QueueSession session = connection.createQueueSession(true,

                     Session.SESSION_TRANSACTED);

       

                  QueueSender queueSender = session.createSender(ioQueue);

                  TemporaryQueue tempQueue = session.createTemporaryQueue();

       

                  QueueReceiver queueReceiver = session.createReceiver(tempQueue);

       

                  TextMessage requestMessage = session.createTextMessage();

                  requestMessage.setJMSReplyTo(tempQueue);

                  requestMessage.setStringProperty("username", "");

       

                  String requestString = "Message";

                  requestMessage.setText(requestString);

       

                  queueSender.send(requestMessage);

       

                  try{

                      session.commit();

                  } catch(Exception e) {

                      e.printStackTrace();

                  }

                  queueSender.close();

       

                  System.out.println("Message sent");

       

                  booleandone = false;

       

                  while(!done) {

                      Message o = queueReceiver.receive();

                      try{

                          System.out.println("Message type is: "+ o.getClass());

                     booleant = o instanceofTextMessage;

                     System.out.println("InstanceOf TextMessage: "+ t);

                      } catch(NullPointerException np) {

                     System.out.println("Nullpointer with object");

                      }

                      TextMessage replyMessage = (TextMessage) o;

                      if(replyMessage == null) {

                     System.out.println("upps null");

       

                      }

                      replyMessage.acknowledge();

                      System.out.println("Replymessage: "+ replyMessage.getText());

                   }

                 } catch(JMSException e) {

                   e.printStackTrace();

                 } catch(NullPointerException npe) {

                   npe.printStackTrace();

                 }

       

            }

      }

       

      Attachments

      • pnickoll
        pnickoll
        3 Posts
        ACCEPTED ANSWER

        Re: Liberty profile 8.5.5 and jms

        ‏2013-06-27T13:47:40Z  in response to mbang

        Hi Michael,

        For the option that uses MQ JMS directly via JNDI you can specify a property on the JMS queue to allow you to see MQMD properties on a message. On a quick test we did we specified a JMS Destination like this:

            <jmsQueue id="MyQueue1" jndiName="MyQueue1">
              <properties.wmqJms baseQueueName="Q1"    baseQueueManagerName="QM1"
             arbitraryProperties='MDREAD="YES"'/>
            </jmsQueue>

        If you add the part in bold to your JMS Queue you should then be able to view the MQMD fields, I believe that is what you were after? Let me know if this isn't what you were after.

        My test message then looks like:

         

        JMSMessage class: jms_text 
        JMSType:          null 
        JMSDeliveryMode:  2 
        JMSExpiration:    0 
        JMSPriority:      4 
        JMSMessageID:     ID:414d5120514d5f46524f4e54464f4f548ea7c95120002907 
        JMSTimestamp:     1372340429348 
        JMSCorrelationID: null 
        JMSDestination:   queue://QM1/Q1?mdReadEnabled=true 
        JMSReplyTo:       null 
        JMSRedelivered:   false   
        JMSXAppID: jar                            
        JMSXDeliveryCount: 0   
        JMSXUserID: pnickoll       
        JMS_IBM_MQMD_AccountingToken: 16010515000000EF224225DA3B1E73E6A1B971E903000000000000000000000B   
        JMS_IBM_MQMD_ApplIdentityData:                                    
        JMS_IBM_MQMD_ApplOriginData:        
        JMS_IBM_MQMD_BackoutCount: 0   
        JMS_IBM_MQMD_CodedCharSetId: 1208   
        JMS_IBM_MQMD_CorrelId: 000000000000000000000000000000000000000000000000   
        JMS_IBM_MQMD_Encoding: 273   
        JMS_IBM_MQMD_Expiry: -1   
        JMS_IBM_MQMD_Feedback: 0   
        JMS_IBM_MQMD_Format: MQHRF2     
        JMS_IBM_MQMD_GroupId: 000000000000000000000000000000000000000000000000   
        JMS_IBM_MQMD_MsgFlags: 0   
        JMS_IBM_MQMD_MsgId: 414D5120514D5F46524F4E54464F4F548EA7C95120002907   
        JMS_IBM_MQMD_MsgSeqNumber: 1   
        JMS_IBM_MQMD_MsgType: 8   
        JMS_IBM_MQMD_Offset: 0   
        JMS_IBM_MQMD_OriginalLength: -1   
        JMS_IBM_MQMD_Persistence: 1   
        JMS_IBM_MQMD_Priority: 4   
        JMS_IBM_MQMD_PutApplName: jar                            
        JMS_IBM_MQMD_PutApplType: 28   
        JMS_IBM_MQMD_PutDate: 20130627   
        JMS_IBM_MQMD_PutTime: 13402935   
        JMS_IBM_MQMD_ReplyToQ: null   
        JMS_IBM_MQMD_ReplyToQMgr: null   
        JMS_IBM_MQMD_Report: 0   
        JMS_IBM_MQMD_UserIdentifier: pnickoll       
        JMS_IBM_PutApplType: 28   
        JMS_IBM_PutDate: 20130627   
        JMS_IBM_PutTime: 13402935

         

        We are also looking into the problem using the SIBus and MQ Link approach and we'll get back to you once we have more info.

         

        • mbang
          mbang
          3 Posts
          ACCEPTED ANSWER

          Re: Liberty profile 8.5.5 and jms

          ‏2013-06-28T08:43:41Z  in response to pnickoll

          Hi Philip,

          Thanks for your quick response. I have tried to put the MDREAD and also MDWRITE property on the queue and I can see that the on the request I get the MQMD properties, but not on the tempqueue. I have included the output from getQueueName on the request and on the tempQueue below:

          Queue: queue://T1/QUEUE?mdReadEnabled=true&receiveConversion=2&mdWriteEnabled=true&targetClient=1
          TempQueue: queue://T1/TEMP.CB9429022A18E4AC?persistence=1

          How do I get it to work on the tempQueue as well. (I have also tried to put the MDREAD property on the Queue Connection Factory as well, but with no result)

          I have in this document (http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/index.jsp?topic=%2Fcom.ibm.mq.csqzak.doc%2Ffr13040_.htm) found a note about two parameters/settings: MQPMO_SET_IDENTITY_CONTEXT or MQPMO_SET_ALL_CONTEXT how do I set them on the queue definition in Liberty ?

          Regards,

          Michael

  • pnickoll
    pnickoll
    3 Posts
    ACCEPTED ANSWER

    Re: Liberty profile 8.5.5 and jms

    ‏2013-07-02T10:00:45Z  in response to mbang

    Hi Michael,

    Unfortunately it's not possible to configure temporary destinations with those fields, if you'd like to be able to do this then you could raise a request for change at http://www.ibm.com/developerworks/rfe/execute?use_case=submitRfe&BRAND_ID=181&PROD_FAM_ID=262&PROD_ID=544&COMP_ID=17&OS_ID=16&PRI_ID=3&PRESELECT_DROPDOWNS=true

    Would an option be to use static destinations and message selectors or correl ID to ensure you get the message you are interested in?

    With regards to the MQPMO_SET_IDENTITY_CONTEXT or MQPMO_SET_ALL_CONTEXT properties, you can also specify those using arbitrary properties field. The field would be MDMSGCTX and you would set it to one of the following values:

    SET_INDENTITY_CONTEXT=0x400
    SET_ALL_CONTEXT=0x800

    So you'd need to specify MDMSGCTX=0x400 or MDMSGCTX=0x800 in your arbitrary properties.

    This isn't an ideal way to use these properties, but to expose them as JMS fields that we can configure in Liberty's server.xml we'd need to make an update. Again you could raise a request for this at http://www.ibm.com/developerworks/rfe/execute?use_case=submitRfe if you find this to be a problem.

    If you submit a request for this please ensure that these fields are set:

    Brand: WebSphere
    Product Family: Connectivity and Integration
    Product WebSphere MQ