MQ

 View Only
  • 1.  Websphere MQ filter Support for more fields

    Posted Mon March 20, 2023 09:23 AM

    Team,

    with java code, we are reading Queue messages, and also reading with filter.

    We are using the below function to read queue messages with a filter. this function supports only 6 fields but Queue has more than 25 fields

    1) gmo.matchOptions =
    MQConstants.MQMO_MATCH_MSG_SEQ_NUMBER;

    2) gmo.matchOptions = MQConstants.MQMO_MATCH_GROUP_ID;

    3) gmo.matchOptions =
    MQConstants.MQMO_MATCH_CORREL_ID;

    4) gmo.matchOptions = MQConstants.MQMO_MATCH_MSG_ID;

    5) gmo.matchOptions =
    MQConstants.MQMO_MATCH_MSG_TOKEN;

    6) gmo.matchOptions = MQConstants.MQMO_MATCH_OFFSET;

    We want to filter data with all the fields. Can you please support the filter for all the fields ?

    we are using the below IBM MQ Jars

    com.ibm.mq
    com.ibm.mq.jmqi
    com.ibm.mq.pcf

    please let us know If any other method available which supports all the fields.



    ------------------------------
    Ranjitha YM
    ------------------------------


  • 2.  RE: Websphere MQ filter Support for more fields
    Best Answer

    IBM Champion
    Posted Mon March 20, 2023 01:35 PM

    Hi Ranjitha,

    The fields you show us that can be matched on are not queue attributes, but message attributes.

    Match Option Message attribute
    MQMO_MATCH_MSG_SEQ_NUMBER MQMD.MsgSeqNumber
    MQMO_MATCH_GROUP_ID MQMD.GroupId
    MQMO_MATCH_CORREL_ID MQMD.CorrelId
    MQMO_MATCH_MSG_ID MQMD.MsgId
    MQMO_MATCH_MSG_TOKEN MQGMO.MsgToken
    MQMO_MATCH_OFFSET MQMD.Offset

    You can use an SQL selector string to match on any field in the MQMD. Some example selector strings are shown in this post. You can use the selector string using the JMS API thus:-

          // Create consumer with selector
          String selector = "Root.MQMD.MsgType = 4";         
          MessageConsumer cons = session.createConsumer(queDest, selector);

    Cheers,
    Morag



    ------------------------------
    Morag Hughson
    MQ Technical Education Specialist
    MQGem Software Limited
    Website: https://www.mqgem.com
    ------------------------------



  • 3.  RE: Websphere MQ filter Support for more fields

    Posted Thu May 04, 2023 07:20 AM

    Can you please let us know how to pass the Message Consumer variable to get function?
    following is our code 

    and which jar do we need to use ? Is it javax.jms.jar?

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Hashtable;
    import com.ibm.mq.MQException;
    import com.ibm.mq.MQGetMessageOptions;
    import com.ibm.mq.MQMessage;
    import com.ibm.mq.MQQueue;
    import com.ibm.mq.MQQueueManager;
    import com.ibm.mq.constants.CMQC;
    import com.ibm.mq.constants.MQConstants;
     
     
     
    public class ReadMQ {
     
    public static void main(String[] args) throws MQException {
     
     
     
    String host = "10.65.139.19";
    String port = "port";
    String username = "UN";
    String password = "Pass";
    String queueManager = "QM";
    String channel = "channel";
     
    MQQueueManager manager;
    MQQueue queue = null;
    boolean getMore = true;
     
    Hashtable<String, Object> mqht = new Hashtable<>();
     
     
    mqht.put(CMQC.CHANNEL_PROPERTY,channel);
    mqht.put(CMQC.HOST_NAME_PROPERTY, host);
    mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
    mqht.put(CMQC.USER_ID_PROPERTY, username);
    mqht.put(CMQC.PASSWORD_PROPERTY, password);
     
     
    manager=new MQQueueManager(queueManager, mqht);
     
    int openOptions = MQConstants.MQOO_BROWSE | MQConstants.MQOO_INPUT_EXCLUSIVE | MQConstants.MQOO_INQUIRE;        
    queue = manager.accessQueue("QA.QUEUE.1",openOptions);
     
    MQGetMessageOptions gmo = new MQGetMessageOptions();
    // MessageSelector Selector =new  MessageSelector(manager);
    // Selector.setFilter("priority", Selector., 0);
     
     
     
    // gmo.options = MQConstants.MQGMO_WAIT + MQConstants.MQGMO_FAIL_IF_QUIESCING
    // + MQConstants.MQGMO_CONVERT
    // + MQConstants.MQGMO_NO_SYNCPOINT;
     
     
    gmo.options = MQConstants.MQGMO_WAIT + MQConstants.MQGMO_FAIL_IF_QUIESCING 
    + MQConstants.MQGMO_CONVERT + MQConstants.MQGMO_BROWSE_NEXT ;
    }
    try {
     
    while(getMore)
    {
    MQMessage message = new MQMessage();
    queue.get(message, gmo);
    byte[] b = new byte[message.getMessageLength()];
    message.readFully(b);
     
    System.out.println(new String(b));
     
    if (IsDestructiveRead) {
     
    //System.out.println(message.expiry);
     
    OutputStream out = new FileOutputStream("C:\\Users\\adminqa\\Documents\\Newfolder\\filename.dat");
    out.write(message.expiry);
    out.close();
     
    manager.commit();
    }
     
    }
     
     
     
    } catch (MQException e) {
     
    if (e.reasonCode == 2033)
    {
    System.out.println("No message available");
    }
     
    if ( (e.completionCode == CMQC.MQCC_FAILED) &&(e.reasonCode == CMQC.MQRC_NO_MSG_AVAILABLE) ) {
     
    }
    else
    {
    System.out.println("MQException: " + e.getLocalizedMessage());
    System.out.println("CC=" + e.completionCode + " : RC=" + e.reasonCode);
    getMore = false;
    }
     
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
     
    //manager.commit();
    // manager.disconnect();
    // queue.close();
     
    }
     
    }






    ------------------------------
    Ranjitha YM
    ------------------------------



  • 4.  RE: Websphere MQ filter Support for more fields

    Posted Sat May 06, 2023 10:14 PM

    Using com.ibm.mqjms TPL I tried to implement filter, am able to filter messages  based on the below properties 

    But I want to filter messages based on Message Data 

    EX:  we have message data, 1) Manager 2) Employee 3) Lead 4) Manager 

    I want to read messages where message data equal to Manager 

     JMSMessage class
    JMSType
    JMSDeliveryMode
    JMSDeliveryDelay
    JMSDeliveryTime
    JMSExpiration
     JMSPriority
    JMSMessageID
     JMSTimestamp
    JMSCorrelationID
    JMSDestination
    JMSReplyTo
    JMSRedelivered
    JMSXAppID
    JMSXDeliveryCount
    JMSXUserID
    JMS_IBM_Character_Set
    JMS_IBM_Encoding
    JMS_IBM_Format
     JMS_IBM_MsgType
    JMS_IBM_PutApplType
     JMS_IBM_PutDate
    JMS_IBM_PutTime

    import javax.jms.Destination;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageConsumer;
    import javax.jms.Queue;
    import javax.jms.QueueConnection;
    import javax.jms.Session;
    import javax.jms.TextMessage;
     
    import com.ibm.mq.jms.MQQueueConnectionFactory;
    import com.ibm.msg.client.wmq.WMQConstants;
     
    public class IBMMQ_JMSFilter{
     
    public static void main(String[] args) throws NumberFormatException, JMSException {
     
    QueueConnection Queue_Con;
    MessageConsumer consumer;
     
    String host = "host";
    String port = "port";
    String username = "UN";
    String password = "Pass";
    String queueManager = "QM";
    String channel = "QA.APP.SVRCONN";
     
    // Create queue manager connection
    MQQueueConnectionFactory MQ_conFact = new MQQueueConnectionFactory();
    MQ_conFact.setHostName (host);
    MQ_conFact.setPort (Integer.parseInt(port));
    MQ_conFact.setQueueManager (queueManager);
    MQ_conFact.setChannel (channel);
        MQ_conFact.setTransportType (WMQConstants.WMQ_CM_CLIENT);
    //Queue_Con = MQ_conFact.createQueueConnection ();
    Queue_Con = (QueueConnection) MQ_conFact.createConnection(username, password);
     
    //Create session
    Session session = 
    Queue_Con.createSession(false, Session.CLIENT_ACKNOWLEDGE);  // non-transacted session (more)
    // Queue queue = session.createQueue("QA.QUEUE.1"); 
    //Create queue connection
    Destination queDest= session.createQueue("QA.QUEUE.1");
    String selector = "JMS_IBM_MsgType =8";  
      
    consumer = session.createConsumer(queDest, selector);
    //consumer = session.createConsumer(queDest);
    Queue_Con.start();                                             // start the connection (more)
    while (true) {                                           // run forever
    Message msg = consumer.receiveNoWait();                      // blocking! (more)
    // if (! (msg instanceof TextMessage))
    // throw new RuntimeException("Expected a TextMessage");
    TextMessage tm = (TextMessage) msg;
    System.out.println(tm.getText());                      // print message content
    }
    }
     
    }



    ------------------------------
    Ranjitha YM
    ------------------------------



  • 5.  RE: Websphere MQ filter Support for more fields

    IBM Champion
    Posted Mon May 08, 2023 05:29 PM

    I'm very confused by the different questions you have asked.

    > EX:  we have message data, 1) Manager 2) Employee 3) Lead 4) Manager
    > I want to read messages where message data equal to Manager 

    What does that mean? 

    Also, do you understand what this code does?

    String selector = "JMS_IBM_MsgType =8";  
    consumer = session.createConsumer(queDest, selector);

    You are selecting messages that have a Message Type of MQMT_DATAGRAM.

    No offence intended, but you appear to be new to IBM MQ.  Queues like a database table should have a single focus or data type going to it.  As I always tell my customers, you should hand out queues like candy on Halloween.  Having multiple-purpose queues only leads to far more complicated code.

    (1) 90% of the applications set a tag or field in the message data to denote the type of data contained
    (2) 10% of the applications set a Named Property (aka Message Property) to denote the type of data contained 
    (3) 0.001% of the applications set the message's Message Type field to have a unique value

    (1) If the messages you are processing have the type set in the message data then you will need to code your application to handle it or use a solution like Message Broker/IIB/ACE. i.e. The code will have to browse all messages then destructively retrieve those messages that match.  Not a very good design!!  Note: MQ does not select messages based on message data or values in the message data.

    (2) If the type is in a Named Property, you can use a Message Selector to retrieve those messages.

    (3) Have the sending application set a unique type in the Message Type field of the message.  You can define your own message types. They just have to start at 65536 or higher.

    i.e.
    In C you would do:

    #define MT_MANAGER                   65536
    #define MT_EMPLOYEE                  65537
    #define MT_LEAD                      65538


    In Java you would do:
    public static final int MT_MANAGER  = 65536;
    public static final int MT_EMPLOYEE = 65537;
    public static final int MT_LEAD     = 65538;

    Now you can use a simple selector like this:

    String selector = "JMS_IBM_MsgType ="+MT_MANAGER;  
    consumer = session.createConsumer(queDest, selector);

    And it will retrieve just those messages matching the Message Type.




    ------------------------------
    Roger Lacroix
    CTO
    Capitalware Inc.
    London ON Canada
    https://capitalware.com
    ------------------------------



  • 6.  RE: Websphere MQ filter Support for more fields

    Posted Tue May 09, 2023 03:53 AM

    Thank You for responding,

    My query is, I have the following messages in my queue. I want to select messages where message data is equal to Data 01.

    for the selector string, I want to pass filter condition Message Data = Data o1 and expect 2 records as output 

    what is the JMS header property to filter message data?  EX: for msg type header property is JMS_IBM_MsgType  like this what is the property for message data?


    Following is the JMS response, able to see the header property for all the fields except Message Data, it is at the end without any property.
    Can you please let me know how to filter message data/syntax for the message data selector?

    JMSMessage class: jms_text
      JMSType:          null
      JMSDeliveryMode:  1
      JMSDeliveryDelay: 0
      JMSDeliveryTime:  0
      JMSExpiration:    0
      JMSPriority:      0
      JMSMessageID:     ID:414d5120514d5f594d522020202020207c2d566402a80040
      JMSTimestamp:     1683371640590
      JMSCorrelationID: null
      JMSDestination:   null
      JMSReplyTo:       null
      JMSRedelivered:   true
        JMSXAppID: MQ Explorer 9.3.1           
        JMSXDeliveryCount: 10
        JMSXUserID: adminqa     
        JMS_IBM_Character_Set: UTF-8
        JMS_IBM_Encoding: 546
        JMS_IBM_Format: MQSTR   
        JMS_IBM_MQMD_AccountingToken: 16010515000000942326C4DFF13E182CD9CC38F003000000000000000000000B
        JMS_IBM_MQMD_ApplIdentityData:                                 
        JMS_IBM_MQMD_ApplOriginData:     
        JMS_IBM_MQMD_BackoutCount: 9
        JMS_IBM_MQMD_CodedCharSetId: 1208
        JMS_IBM_MQMD_CorrelId: 000000000000000000000000000000000000000000000000
        JMS_IBM_MQMD_Encoding: 546
        JMS_IBM_MQMD_Expiry: -1
        JMS_IBM_MQMD_Feedback: 0
        JMS_IBM_MQMD_Format: MQSTR   
        JMS_IBM_MQMD_GroupId: 000000000000000000000000000000000000000000000000
        JMS_IBM_MQMD_MsgFlags: 0
        JMS_IBM_MQMD_MsgId: 414D5120514D5F594D522020202020207C2D566402A80040
        JMS_IBM_MQMD_MsgSeqNumber: 1
        JMS_IBM_MQMD_MsgType: 8
        JMS_IBM_MQMD_Offset: 0
        JMS_IBM_MQMD_OriginalLength: -1
        JMS_IBM_MQMD_Persistence: 0
        JMS_IBM_MQMD_Priority: 0
        JMS_IBM_MQMD_PutApplName: MQ Explorer 9.3.1           
        JMS_IBM_MQMD_PutApplType: 11
        JMS_IBM_MQMD_PutDate: 20230506
        JMS_IBM_MQMD_PutTime: 11140059
        JMS_IBM_MQMD_ReplyToQ:                                                 
        JMS_IBM_MQMD_ReplyToQMgr: QM_YMR                                          
        JMS_IBM_MQMD_Report: 0
        JMS_IBM_MQMD_UserIdentifier: adminqa     
        JMS_IBM_MsgType: 8
        JMS_IBM_PutApplType: 11
        JMS_IBM_PutDate: 20230506
        JMS_IBM_PutTime: 11140059
    Data 01



    ------------------------------
    Ranjitha YM
    ------------------------------



  • 7.  RE: Websphere MQ filter Support for more fields

    IBM Champion
    Posted Tue May 09, 2023 01:57 PM

    what is the JMS header property to filter message data?  EX: for msg type header property is JMS_IBM_MsgType  like this what is the property for message data?

    I already answered that question in my previous response (please re-read it).

    (1) If the messages you are processing have the type set in the message data then you will need to code your application to handle it or use a solution like Message Broker/IIB/ACE. i.e. The code will have to browse all messages then destructively retrieve those messages that match.  Not a very good design!!  Note: MQ does not select messages based on message data or values in the message data.

    To be clear, there is no message selector for selecting messages from a queue based on the message data. Your code needs to do all of the work!!!

    That is why options #2 and #3 in my previous post are far, far betters options to use and it keeps the design nice and simple.

    If I was designing the consumer application, the first thing I would ask "is the sender application using the MQMD Correlation Id (aka CorrelId) field?". Because if not, then the simple solution that will work for both Java (non-JMS) and JMS/Java (also C/C++/C#/COBOL/etc..) is to have the sender application set a value (i.e. MANAGER, EMPLOYEE or LEAD) in the CorrelId field and then in your consuming, you have the code to match on CorrelId.
    i.e.

    MQGetMessageOptions gmo = new MQGetMessageOptions();
    gmo.options = CMQC.MQGMO_NO_SYNCPOINT | CMQC.MQGMO_NO_WAIT | CMQC.MQGMO_CONVERT | CMQC.MQGMO_FAIL_IF_QUIESCING;
    gmo.matchOptions = CMQC.MQMO_MATCH_CORREL_ID;

    MQMessage receiveMsg = new MQMessage();
    receiveMsg.messageId = CMQC.MQMI_NONE;
    receiveMsg.correlationId = "EMPLOYEE".getBytes();

    // get the message on the queue
    inQ.get(receiveMsg, gmo);



    ------------------------------
    Roger Lacroix
    CTO
    Capitalware Inc.
    London ON Canada
    https://capitalware.com
    ------------------------------



  • 8.  RE: Websphere MQ filter Support for more fields

    IBM Champion
    Posted Wed May 10, 2023 04:02 AM

    Why is nobody talking about the message properties?
    If you want to filter on specific values, make sure that value is set as a message property by the sending application.
    You should then be able to create a filter with the corresponding property = value clause.
    For more specific information see https://www.ibm.com/docs/en/ibm-mq/9.3?topic=messages-message-selectors-in-jms
    Hope this helps



    ------------------------------
    Francois Brandelik
    ------------------------------



  • 9.  RE: Websphere MQ filter Support for more fields

    IBM Champion
    Posted Wed May 10, 2023 02:45 PM

    Hi FB,

    > Why is nobody talking about the message properties?

    Actually, that was my point #2 in my 1st posting above.  See Named Properties (aka Message Properties) comment.

    What bugs about IBM's design of Named/Message Properties Selectors is that they excluded Java (non-JMS) from using them.  It's one of those SMFH moments!!

    99% of the Java code I write is non-JMS, so I cannot use this normal selection method.



    ------------------------------
    Roger Lacroix
    CTO
    Capitalware Inc.
    London ON Canada
    https://capitalware.com
    ------------------------------