Exchanging a formatted record with a non-JMS application

Follow the steps suggested in this task to design and build a data conversion exit, and a JMS client application that can exchange messages with a non-JMS application using JMSBytesMessage. The exchange of a formatted message with a non-JMS application can take place with or without calling a data conversion exit.

Before you begin

You might be able to design a simpler solution to exchanging messages with a non-JMS application using a JMSTextMessage. Eliminate that possibility before following the steps in this task.

About this task

A JMS client is easier to write if it is not involved in the details of formatting JMS messages exchanged with other JMS clients. As long as the message type is JMSTextMessage, JMSMapMessage, JMSStreamMessage, or JMSObjectMessage, WebSphere MQ looks after the details of formatting the message. WebSphere MQ deals with differences in code pages and numeric encoding on different platforms.

You can use these message types to exchange messages with non-JMS applications. To do so, you must understand how these messages are constructed by WebSphere MQ classes for JMS. You might be able to modify the non-JMS application to interpret the messages; see Mapping JMS messages onto WebSphere MQ messages.

An advantage of using one of these message types is the JMS client programming does not depend on the type of application that it is exchanging messages with. A disadvantage is that it might require a modification to another program, and you might not be able to change the other program.

An alternative approach is to write a JMS client application that can deal with existing message formats. Often existing messages are fixed format and contain a mixture of unformatted data, text, and numbers. Use the steps in this task, and the example JMS client in Writing classes to encapsulate a record layout in a JMSBytesMessage, as a starting point for building a JMS client that can exchange formatted records with non-JMS applications.

Procedure

  1. Define the record layout, or use one of the predefined WebSphere MQ header classes.

    For handling predefined WebSphere MQ headers, see Handling WebSphere MQ message headers.

    Figure 1 is an example of a user defined, fixed-length record layout, which can be processed by the data conversion utility.

  2. Create the data conversion exit.

    Follow the instructions in Writing a data-conversion exit program to write a data conversion exit.

    To try out the example in Writing classes to encapsulate a record layout in a JMSBytesMessage, name the data conversion exit MYRECORD.

  3. Write Java classes to encapsulate the record layout, and sending and receiving record. Two approaches you might take are:
  4. Decide what coded character set to exchange messages in.
  5. Configure the destination to exchange MQ-type messages, without a JMS MQRFH2 header.

    Both the sending and receiving destination must be configured to exchange MQ-type messages. You can use the same destination for both sending and receiving.

    The application can override the destination message body property:
    ((MQDestination)destination).setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ);
    The example in Writing classes to encapsulate a record layout in a JMSBytesMessage overrides the destination message body property, ensuring an MQ-style message is sent.
  6. Test the solution with JMS and non-JMS applications
    Useful tools to test a data conversion exit are:
    • The amqsgetc0.c sample program is useful to test receiving a message sent by a JMS client. See the suggested modifications to use the example header, RECORD.h, in Figure 2. With the modifications, amqsgetc0.c receives a message sent by the example JMS client, TryMyRecord.java; see Writing classes to encapsulate a record layout in a JMSBytesMessage.
    • The sample WebSphere MQ browse program, amqsbcg0.c, is useful to inspect the contents of the message header, the JMS header, MQRFH2, and the message contents.
    • The rfhutil program, previously available in SupportPac IH03, allows test messages to be captured and stored in files, and then used to drive Message Flows. Output messages can also be read and displayed in a variety of formats. The formats include two types of XML as well as matching against a COBOL copybook. The data can be in EBCDIC or ASCII. An RFH2 header can be added to the message before the message is sent.

    If you try to receive messages using the modified amqsgetc0.c sample program, and get an error with reason code 2080, check whether the message has an MQRFH2. The modifications assume that the message has been sent to a destination that specifies no MQRFH2.

Examples

Figure 1. RECORD.h
struct RECORD { MQCHAR StrucID[4];
                MQLONG Version;
                MQLONG StructLength;
                MQLONG Encoding;
                MQLONG CodeCharSetId;
                MQCHAR Format[8];
                MQLONG Flags;
                MQCHAR RecordData[32];
    };
Figure 2. Modify amqsget0.c
  • Declare the RECORD.h data structure
    struct tagRECORD {
       MQCHAR4    StrucId;            
       MQLONG     Version;            
       MQLONG     StrucLength;
       MQLONG     Encoding; 
       MQLONG     CCSID;  
       MQCHAR8    Format;
       MQLONG     Flags;
       MQCHAR32   RecordData;
     };   
    typedef struct tagRECORD RECORD;
       typedef RECORD MQPOINTER PRECORD;
       RECORD record;
       PRECORD pRecord = &(record);   
    
  • Modify the MQGET call to use RECORD,
    1. Before modification:
          MQGET(Hcon,            /* connection handle     */
                Hobj,            /* object handle         */
                &md,             /* message descriptor    */
                &gmo,            /* get message options   */
                buflen,          /* buffer length         */
                buffer,          /* message buffer        */
                &messlen,        /* message length        */
                &CompCode,       /* completion code       */
                &Reason);        /* reason code           */
    2. After modification:
          MQGET(Hcon,            /* connection handle     */
                Hobj,            /* object handle         */
                &md,             /* message descriptor    */
                &gmo,            /* get message options   */
                sizeof(RECORD),  /* buffer length         */
                pRecord,         /* message buffer        */
                &messlen,        /* message length        */
                &CompCode,       /* completion code       */
                &Reason);        /* reason code           */
  • Change the print statement,
    1. From:
      buffer[messlen] = '\0';            /* add terminator          */
      printf("message <%s>\n", buffer);
    2. To:
      /* buffer[messlen] = '\0';            add terminator          */
      printf("ccsid <%d>, flags <%d>, message <%32.32s>\n \0",
              md.CodedCharSetId, record.Flags, record.RecordData);