ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum Index » IBM MQ Java / JMS » MQRFH2 and Java base classes

Post new topic  Reply to topic
 MQRFH2 and Java base classes « View previous topic :: View next topic » 
Author Message
speediii
PostPosted: Mon Mar 05, 2007 12:23 am    Post subject: MQRFH2 and Java base classes Reply with quote

Novice

Joined: 11 Apr 2006
Posts: 19

Hi

I need some advice please! We have a new system sending MQ messages in a RFH2 format. The MQ messages contain a file, and properties in the RFH2 header contain fields such as the desired filename etc.

I've read through this forum and it seems to me that the Java base api classes do not have any helper classes for reading and writing MQRFH2, is this correct? I understand that JMS messages sent to MQ are by default written in RFH2 format - in my case, my application is Java but the sending/receiving application might not be JMS, but C/C++, using the RFH2 format. Strange that the Java base classes don't have any get/set RFHProperty() type methods?

The answer seems to be "switch to JMS". If no one has any helper functions for RFH2 then I need to write a new JMS Reader & JMS Writer and use that instead of my native MQ adapters. Question: Could someone post some example code; I am confused about how to write these as some examples use pure javax.jms.* but wonder what the com.ibm.mqjms.jar is for?

A bit of decent example code would help me immensely! Or if anyone has some useful links as I've tried google and haven't had much luck, hence this post.

Thanks in advance!
Back to top
View user's profile Send private message
EddieA
PostPosted: Mon Mar 05, 2007 10:19 am    Post subject: Reply with quote

Jedi

Joined: 28 Jun 2001
Posts: 2453
Location: Los Angeles

No, there aren't any helper classes. If you search the site, you can find some Java "snippets" for reading/writing RFH2 headers.

You can also "tell" the JMS application to PUT messages without the RFH2 header, if the messages are destined for a non-JMS application.

Cheers,
_________________
Eddie Atherton
IBM Certified Solution Developer - WebSphere Message Broker V6.1
IBM Certified Solution Developer - WebSphere Message Broker V7.0
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Mon Mar 05, 2007 1:12 pm    Post subject: Reply with quote

Grand High Poobah

Joined: 18 Nov 2003
Posts: 20756
Location: LI,NY

And if working in C/C# you can use the XMS package (JMS for non java languages)...

Enjoy
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
speediii
PostPosted: Tue Mar 06, 2007 12:26 am    Post subject: Reply with quote

Novice

Joined: 11 Apr 2006
Posts: 19

But the sending application isn't JMS. It's a C/C++ but it's using MQRFH2 in the message structure for sending files over MQ.

It seems strange that I have to write a JMS adaptor just because of RFH2? RFH2 isn't just for JMS. Or?

Thanks
Back to top
View user's profile Send private message
Vitor
PostPosted: Tue Mar 06, 2007 12:52 am    Post subject: Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 26093
Location: Texas, USA

RFH2 is used for any message created from any language which needs to hold additional information, typically within a MQSI/WMB environment where you want to clue the broker in on message type for example, not just JMS. It's used in JMS apps because there's not enough space in the MQMD to hold all the fields of a JMS header.
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Tue Mar 06, 2007 1:05 pm    Post subject: Reply with quote

Grand High Poobah

Joined: 18 Nov 2003
Posts: 20756
Location: LI,NY

JMS and XMS are not a must but a very convenient way not to reinvent the wheel and ideal for RFH header manipulation...

Enjoy
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
speediii
PostPosted: Fri Mar 23, 2007 4:40 am    Post subject: Reply with quote

Novice

Joined: 11 Apr 2006
Posts: 19

For anyone who's interested I got the reading & writing of RFH2 to work using Java base classes. I think the below code is more complete than any other code examples on this forum:

For reading MQRFH2:
Code:
public void parseMQRFH2(com.ibm.mq.MQMessage mqMessage) throws Exception {
      mqMessage.seek(0); //Set read position back to the beginning of Message Data part
            
      rfhStrucID        = mqMessage.readString(4); //MQC.MQRFH_STRUC_ID
      rfhVersion        = mqMessage.readInt();     //MQRFH_VERSION_1 or MQRFH_VERSION_2
      rfhStrucLength    = mqMessage.readInt();     //MQRFH_STRUC_LENGTH_FIXED or MQRFH_STRUC_LENGTH_FIXED_2
      rfhEncoding       = mqMessage.readInt();     //MQC.MQENC_NATIVE
      rfhCodedCharSetId = mqMessage.readInt();     //MQC.MQCCSI_DEFAULT
      rfhFormat         = mqMessage.readString(8); //MQFMT_RF_HEADER_2
      rfhFlags          = mqMessage.readInt();     //MQC.MQRFH_NO_FLAGS
      rfhNameValueCCSID = mqMessage.readInt();     //1208 - UTF-8
      
      //
      // Validate Header
      if (!mqMessage.format.equals(MQC.MQFMT_RF_HEADER_2)) {
         throw new Exception("Invalid MQRFH2 format. MQFormat["+mqMessage.format+"] should be["+MQC.MQFMT_RF_HEADER_2+"]");
      }
               
      //The coded character set identifier of character data in the application
      //message data. The behavior of the readString, readLine, and writeString
      //methods is altered accordingly.
       mqMessage.characterSet = rfhNameValueCCSID;
            
      int hdrOffset = mqMessage.getDataOffset();

       //
       // Now parse through all the pairs of data (length, xml data)
       // Part 1:   <mcd></mcd>
       // Part 2:   <jms></jms>
       // Part 3:   <usr></usr>                 - Contains USER Set properties
       // ...etc ...
       // Last Part:   Trailing Message Data
       //
      int dataLen;
      String xml;
      while (hdrOffset < rfhStrucLength) {
         dataLen = mqMessage.readInt();   //Get the length of the XML Data part
         xml = mqMessage.readString(dataLen);  //Get the XML data
         hdrOffset += dataLen + 4;
         //
         //Try to parse XML element, and place the element in the HashMap store
         try {
            Document doc = XMLUtils.getXmlFromString(xml);
            Element e = doc.getRootElement();
            String xmlName = e.getName();
            rfhXmlSection.put(xmlName, e);
         } catch (Exception ex) {
            log.error("Failed to parse XML into JDOM Element.  XML String["+xml+"]", ex);
            throw ex;
         }
      }
      mqMessage.encoding = rfhEncoding;
      mqMessage.characterSet = rfhCodedCharSetId;
      
      //
      // Read Trailing Message Data
      int pos = mqMessage.getDataOffset(); //Current Position
      dataLen = mqMessage.getDataLength(); //Number of bytes remaining
      rfhDataBytes = new byte[dataLen]; 
      rfhDataString = mqMessage.readString(dataLen);
      mqMessage.seek(pos); //Set read position back to the beginning of Data part
      mqMessage.readFully(rfhDataBytes);
   }


And writing an MQRFH2 structure:
Code:
public com.ibm.mq.MQMessage createMQRFH2(Message message) throws Exception {
       com.ibm.mq.MQMessage mqMessage = new com.ibm.mq.MQMessage();
              
       //
       // Extract the mcd, jms, usr sections from the Message Properties
       constructXmlSectionFromProperties(message); 
                   
       if (message.isByteModified()) {
          rfhDataBytes = message.getMsgByte();
          m_writeMode = "BYTE ARRAY";
       } else if (message.isStrModified()) {
          rfhDataBytes = message.getMsgString().getBytes();
          m_writeMode = "STRING";
       } else if (message.getMsgByte() != null) {
          rfhDataBytes = message.getMsgByte();
          m_writeMode = "BYTE ARRAY";
       } else {
          rfhDataBytes = message.getMsgString().getBytes();
          m_writeMode = "STRING";
       }
                 
       //The StrucLength value must be a multiple of 4 (the data in the NameValueData/XML Section
      //fields can be padded with space characters to achieve this).     
      rfhStrucLength = MQC.MQRFH_STRUC_LENGTH_FIXED_2;
       while(m_mcd_data.getBytes().length % 4 != 0) {
         m_mcd_data += " ";
      }
      rfhStrucLength += m_mcd_data.getBytes().length;
      while(m_jms_data.getBytes().length % 4 != 0) {
         m_jms_data += " ";
      }
      rfhStrucLength += m_jms_data.getBytes().length;
      while(m_usr_data.getBytes().length % 4 != 0) {
         m_usr_data += " ";
      }
      rfhStrucLength += m_usr_data.getBytes().length;
      rfhStrucLength += 12;  //Add 4 bytes x 3 for each XML NameValueData section
      rfhStrucLength += rfhDataBytes.length;
         
      mqMessage.format = MQC.MQFMT_RF_HEADER_2;
                           
      //RFH2 Part 1: Header Part
      mqMessage.writeString(rfhStrucID);      //StrucID
      mqMessage.writeInt4(rfhVersion);        //Version
      mqMessage.writeInt4(rfhStrucLength );     //StrucLength
      mqMessage.writeInt4(rfhEncoding);       //Encoding
      mqMessage.writeInt4(rfhCodedCharSetId); //CodedCharSetID
      mqMessage.writeString(rfhFormat);       //Format
      mqMessage.writeInt4(rfhFlags);          //Flags
      mqMessage.writeInt4(rfhNameValueCCSID); //NameValueCCSID
      mqMessage.writeInt4(m_mcd_data.getBytes().length);//NameValueLength <mcd>
      mqMessage.writeString(m_mcd_data);      //NameValueData <mcd>
      mqMessage.writeInt4(m_jms_data.getBytes().length);//NameValueLength <mcd>
      mqMessage.writeString(m_jms_data);      //NameValueData <mcd>
      mqMessage.writeInt4(m_usr_data.getBytes().length);//NameValueLength <jms>
      mqMessage.writeString(m_usr_data);      //NameValueData <usr>
      mqMessage.write(rfhDataBytes);       //Actual MESSAGE data
            
      return mqMessage;
    }
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Fri Mar 23, 2007 1:29 pm    Post subject: Reply with quote

Grand High Poobah

Joined: 18 Nov 2003
Posts: 20756
Location: LI,NY

Great, now where do I have my getter setter methods for the usr folder (property / value pairs) and where does it enforce the CCSID for those? (see the limited list available...)

Thanks I'd rather stick with JMS that handles all this behind the scenes for me.

By the way you can in your classes stick with
javax.jms.* and javax.naming.*
but remember that those are just interfaces. You still need the implementation on the classpath and that's where the com.ibm.mqjms.jar packages comes in...

In fact for a successful JMS connection you will need on your classpath at a minimum:
  • com.ibm.mq.jar
  • com.ibm.mqjms.jar
  • connector.jar
  • fscontext.jar (if you use a file context)
  • jms.jar
  • jta.jar
  • jndi.jar
  • providerutil.jar
  • rmm.jar


Note that some are provided by your Web Applications Server provider (jms, jta, jndi)

Best practice is to use all those in <MQ_INSTALL>/java/lib and subtract the ones already provided by your WAS provider....

Enjoy
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
Mohd-Imran
PostPosted: Sun Apr 01, 2007 7:35 pm    Post subject: WebSphere MQ JAVA/JMS -- Visual basic Reply with quote

Novice

Joined: 01 Apr 2007
Posts: 12

Hi,

First time i am using MQ , I build application in Visual Basic 6.0 to connect mq and put message and get message. Issue is that I need to put message with MQRFH2 (message header) but i am unable to do this , Acutally i don't know how to do this , if anybody help me in this regard and if possible send me code so i add this code in my application.
Need this very very urgent.[quote]
Back to top
View user's profile Send private message
Vitor
PostPosted: Mon Apr 02, 2007 12:18 am    Post subject: Re: WebSphere MQ JAVA/JMS -- Visual basic Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 26093
Location: Texas, USA

Mohd-Imran wrote:
Issue is that I need to put message with MQRFH2 (message header) but i am unable to do this , Acutally i don't know how to do this , if anybody help me in this regard and if possible send me code so i add this code in my application.


MQRFH2 is one of the headers supplied in the .bas file you've already got included with your VB app if it's successfully connecting and putting messages. So all you need to do is add the header to the payload buffer, change whatever parts of the RFH2 you need to set (type and so forth), and change the MQMD.Format to the RFH2 constant. IIRC one of the samples deals with this, but it's been a while & I don't have VB6 installed atm to look.

Also, and a little pedantically, you should really have started a new thread in the Application Programming section rather than added to the bottom of an old one in the Java one. It'd get you a faster response to a non-Java issue. But that's a very esoteric point and I wouldn't loose sleep over it!

Welcome to MQ.
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
chrisgclark
PostPosted: Fri May 22, 2009 4:29 am    Post subject: Reply with quote

Apprentice

Joined: 26 Mar 2009
Posts: 35

Hi,

Sorry for replying on such an old post, but was using the sample code and found a problem. Thought i'd post my amended version in case anyone hits the same problem I did...

When using the 'For reading MQRFH2' code above I found an extra hex value was present after the rfhNameValueCCSID field and before the RFH2 folders beginning. This caused my message positions to be incorrect, therefore not extracting the RFH2 folders and message data.

I therefore added another field read before the while loop that gets the folders. This addition field read get the message position to the correct place going into the while loop.

i.e.
Code:

public void parseMQRFH2(com.ibm.mq.MQMessage mqMessage) throws Exception {
      mqMessage.seek(0); //Set read position back to the beginning of Message Data part
           
      rfhStrucID        = mqMessage.readString(4); //MQC.MQRFH_STRUC_ID
      rfhVersion        = mqMessage.readInt();     //MQRFH_VERSION_1 or MQRFH_VERSION_2
      rfhStrucLength    = mqMessage.readInt();     //MQRFH_STRUC_LENGTH_FIXED or MQRFH_STRUC_LENGTH_FIXED_2
      rfhEncoding       = mqMessage.readInt();     //MQC.MQENC_NATIVE
      rfhCodedCharSetId = mqMessage.readInt();     //MQC.MQCCSI_DEFAULT
      rfhFormat         = mqMessage.readString(8); //MQFMT_RF_HEADER_2
      rfhFlags          = mqMessage.readInt();     //MQC.MQRFH_NO_FLAGS
      rfhNameValueCCSID = mqMessage.readInt();     //1208 - UTF-8
      unknownRFHFieldContainingNoValue = mqMessage.readInt();  //unknown field containing hex value 00000000
.
.
.
.


My ammended is the last line of code. This moves to the correct message position to begin looping through the RFH2 folders.

Anyone know why I found an additional hex value after rfhNameValueCCSID ?

If not, don't worry, but hopefully this code will avoid someone the same problem.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic  Reply to topic Page 1 of 1

MQSeries.net Forum Index » IBM MQ Java / JMS » MQRFH2 and Java base classes
Jump to:  



You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Protected by Anti-Spam ACP
 
 


Theme by Dustin Baccetti
Powered by phpBB © 2001, 2002 phpBB Group

Copyright © MQSeries.net. All rights reserved.