Author |
Message
|
Renjith |
Posted: Fri Jan 09, 2009 3:42 am Post subject: XMS client for JMS MQ |
|
|
Newbie
Joined: 09 Jan 2009 Posts: 5
|
Hi,
I'm new to XMS as well as message brokers. Excuse me if the terminology what I'm using here is wrong. I'm a C++ developer and I'm facing an issue to read body of message which I recieve from MQ brokers.
I'm using XMS C++ client to receive message from JMS queues, which is being placed by WMB.
Message has been created in MQ as:
SET OutputRoot.MQRFH2.usr.MSG_ID=strID;
SET OutputRoot.MQRFH2.usr.USER='';
SET OutputRoot.BLOB.BLOB = CAST(strToCPP AS BLOB CCSID 1208);
My C++ program is written as:
pConnFact = new xms::ConnectionFactory();
pConnFact->setIntProperty(XMSC_CONNECTION_TYPE, XMSC_CT_WMQ);
pConnFact->setIntProperty(XMSC_WMQ_CONNECTION_MODE, XMSC_WMQ_CM_CLIENT);
pConnFact->setStringProperty(XMSC_WMQ_HOST_NAME, strHostName);
pConnFact->setIntProperty(XMSC_WMQ_PORT, iIP);
pConnFact->setIntProperty(XMSC_WMQ_TARGET_CLIENT,XMSC_WMQ_TARGET_DEST_JMS);
conn = pConnFact->createConnection();
sess = conn.createSession(xmsFALSE, XMSC_AUTO_ACKNOWLEDGE);
dest = xms::Destination(XMS_DESTINATION_TYPE_QUEUE, strDestQ);
consumer=sess.createConsumer(dest);
consumer.setMessageListener(msgListener);
conn.start();
xms::Message *pBase = NULL;
pBase = consumer.receive(70000);
xms::String xmsType = pBase->getJMSType();//output: mcd://none//?format=
xms::TextMessage TxtMsg(*pBase->ptr());
cout<<"Received data..."<<TxtMsg.getText().c_str()<<endl;//APP CRASH
Can anyone help me, pointing what went wrong in my C++ code. Did I miss setting up any flags?
Thanks in advance.
Renjith |
|
Back to top |
|
 |
Vitor |
Posted: Fri Jan 09, 2009 3:52 am Post subject: Re: XMS client for JMS MQ |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
Renjith wrote: |
Can anyone help me, pointing what went wrong in my C++ code. Did I miss setting up any flags?
|
What's the rest of the set up in the broker (the values of the rest of the RFH2 are missing, especially the mcd)? Why is the message being placed as a BLOB (using some interesting code) when you're attempting to read it as a text message?
The key issue is you're asking to be pointed to what's gone wrong in your code, but your post gives no indication of the nature of "the issue"! What is the issue? You run your app and get an error code? You run your app and the PC crashes? You run your app and a car crashes? Building attacked by giant space chickens? Flying monkeys? What?
Some clues here please.  _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
fjb_saper |
Posted: Sat Jan 10, 2009 3:50 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Some bizzare stuff. You are obviously using a client connection and setting up host and port ... where is the channel setup?
Now you say that your message is being sent by the WMB.
Did you check using RFHUtil/c (support pack IH03) that the RFH fields were set correctly as well as the MQMD fields.
Remember headers are linked.
What is the value of the format field on the RFH header?
What is the value for the Data CCSID on the RFH header ? (1208 ? )
You are trying to look at the JMSType however the broker has a tendency to set its own values. You do not check whether the message is an instance of TextMessage(more prudent route), yet you cast it to TextMessage... Do you have some alternate/error handling if the message is an instance of BytesMessage?
Enjoy  _________________ MQ & Broker admin |
|
Back to top |
|
 |
Renjith |
Posted: Sun Jan 11, 2009 10:31 pm Post subject: |
|
|
Newbie
Joined: 09 Jan 2009 Posts: 5
|
Hi,
Thanks for all for your comments.
Here is the entire story.
We are using a java program to submit a text (string) to WMB. Broker inturn will put the same along with some added properites into a JMS queue. My CPP program (build upon XMS lib) will fetch these information for futher processing. Brokers and CPP program are being executing from different geography.
Inorder to execute the CPP program (Visual Studio 2005), I installed XMS and MQ Client (V.6.0), added an env variable MQSERVER and provide its value something like SYSTEM.DEF.SVRCONN/TCP/10.123.456.78(1234).
Broker sets the message under following format.
SET OutputRoot.MQMD.Format = 'MQRFH2';
SET OutputRoot.MQRFH2.(MQRFH2.Field)Version= 2;
SET OutputRoot.MQRFH2.(MQRFH2.Field)Format = 'MQSTR';
SET OutputRoot.MQRFH2.(MQRFH2.Field)Encoding= 546;
SET OutputRoot.MQRFH2.(MQRFH2.Field)CodedCharSetId= 437;
SET OutputRoot.MQRFH2.(MQRFH2.Field)Flags= 0;
SET OutputRoot.MQRFH2.(MQRFH2.Field)NameValueCCSID = 1208;
SET OutputRoot.MQRFH2.mcd.Msd= 'jms_text';
SET OutputRoot.MQRFH2.mcd.Type= 'ASCII';
SET OutputRoot.MQRFH2.jms= '';
SET OutputRoot.MQRFH2.usr.MSG_ID= strMsgID;
SET OutputRoot.MQRFH2.usr.USER= '';
SET OutputRoot.MQRFH2.usr.timestart= time_start;
SET OutputRoot.BLOB.BLOB = CAST(strToCPP AS BLOB CCSID 1208);
CPP XMS client program implemented as:
pConnFact->setIntProperty(XMSC_CONNECTION_TYPE, XMSC_CT_WMQ);
pConnFact->setIntProperty(XMSC_WMQ_CONNECTION_MODE, XMSC_WMQ_CM_CLIENT);
pConnFact->setStringProperty(XMSC_WMQ_HOST_NAME, strHost);
pConnFact->setIntProperty(XMSC_WMQ_PORT, iIP);
pConnFact->setIntProperty(XMSC_WMQ_BROKER_VERSION, XMSC_WMQ_BROKER_V2);
pConnFact->setIntProperty(XMSC_WMQ_TARGET_CLIENT,XMSC_WMQ_TARGET_DEST_JMS);
conn = pConnFact->createConnection();
sess = conn.createSession(xmsFALSE, XMSC_AUTO_ACKNOWLEDGE);
dest = xms::Destination(XMS_DESTINATION_TYPE_QUEUE, SENDQUEUE);
consumer=sess.createConsumer(dest);
consumer.setMessageListener(msgListener);
conn.start();
xms::Message *pBase = NULL;
pBase = consumer.receive();
xmsMESSAGE_TYPE type=pBase->getTypeId(); //PLS NOTE: Here I get type as XMS_MESSAGE_TYPE_BASE.
In my CPP program, based on the type, I have option to cast the incoming body. But since the type is "_BASE", neither conversion will work.
I'll get an application crash when I try to cast blindly as:
xms::TextMessage TxtMsg(*pBase->ptr());
cout<<"Received data..."<<TxtMsg.getText().c_str()<<endl;
I agree, since body is NULL, crash is natural. Info from call stack at the point of crash is as:
WMB_Test.exe!std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const char * _Val=0x00000000) Line 742 + 0x12 bytes C++
Hope now I clarify my question.
Why I get an 'empty body' in my client program? How can I resolve this issue?
Thanks in advance.
Renjith |
|
Back to top |
|
 |
Vitor |
Posted: Mon Jan 12, 2009 12:47 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
Renjith wrote: |
Why I get an 'empty body' in my client program? How can I resolve this issue?
|
Here's a question - how does you deal with (for instance) the createConnection call failing? As a non-CPP coder, I'm having trouble seeing where you've implemented error handling.
Extending this, I would theorise you're getting a null message because you're doing a recieve against a null object. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
Renjith |
Posted: Mon Jan 12, 2009 2:35 am Post subject: |
|
|
Newbie
Joined: 09 Jan 2009 Posts: 5
|
Hi Victor,
problem is definitely not with the objects (either connection, session or destination).
I designed my function as:
bool Receiver()
{
try
{
.... and all other session like connection, session, destination etc (as in the above tray) comes here....
xms::Message *pBase = consumer.receive();
if(!pBase) return false;
xmsMESSAGE_TYPE type = pBase->getTypeId();
...other casting operations...
}
catch(xms::Exception & ex)
{
cerr << ex << endl;
}
return true;
}
to specify, I'm not getting Message object as NULL, I'm able to retreive all the properties being set from brokers.
i.e,
xms::Property proID = pBase->getProperty("MSG_ID");
cout<<"Msg ID : "<< proID.getString();
So the problem resides in getting the body of the Message object.
Thanks
Renjith |
|
Back to top |
|
 |
fjb_saper |
Posted: Mon Jan 12, 2009 3:05 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
fjb_saper wrote: |
You are trying to look at the JMSType however the broker has a tendency to set its own values. You do not check whether the message is an instance of TextMessage(more prudent route), yet you cast it to TextMessage... Do you have some alternate/error handling if the message is an instance of BytesMessage?
Enjoy |
renjit wrote: |
I'll get an application crash when I try to cast blindly as:
xms::TextMessage TxtMsg(*pBase->ptr());
cout<<"Received data..."<<TxtMsg.getText().c_str()<<endl;
I agree, since body is NULL, crash is natural. Info from call stack at the point of crash is as:
WMB_Test.exe!std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const char * _Val=0x00000000) Line 742 + 0x12 bytes C++ |
Your are not being asked to cast blindly. What you are being asked is to implement something like the instanceof check in Java...
On top of it you should never use *pBase->ptr() to cast to message but use something like TextMessage TxtMsg (*Msg->ptr());
You are trying to cast a property field to the message. You should not have ANY success accessing the message content like that.
Remember as well that if the message content is deemed to be binary (BytesMessage) you could potentially start with byte 00 which is a string terminator in c++ (IIRC)...
So it all comes back to your cast to TextMessage....
Enjoy  _________________ MQ & Broker admin
Last edited by fjb_saper on Mon Jan 12, 2009 3:16 am; edited 1 time in total |
|
Back to top |
|
 |
Vitor |
Posted: Mon Jan 12, 2009 3:12 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
fjb_saper wrote: |
fjb_saper wrote: |
You are trying to look at the JMSType however the broker has a tendency to set its own values. You do not check whether the message is an instance of TextMessage(more prudent route), yet you cast it to TextMessage... Do you have some alternate/error handling if the message is an instance of BytesMessage?
Enjoy |
|
 _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
fjb_saper |
Posted: Mon Jan 12, 2009 3:20 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Finally for your casts you are using pointer references...
Don't know how that works in c++, but in java you do the cast with the object.
Don't know if a cast with pointer references would ever throw a class cast exception...
Have fun  _________________ MQ & Broker admin |
|
Back to top |
|
 |
Renjith |
Posted: Mon Jan 12, 2009 4:26 am Post subject: |
|
|
Newbie
Joined: 09 Jan 2009 Posts: 5
|
Hi,
Thanks for your interest to involve with my issue.
One thing what I like to mention is,
xms::Message *pBase = NULL;
pBase = consumer.receive(70000);
xmsMESSAGE_TYPE type = pBase->getTypeId();
Here I'm getting type as "XMS_MESSAGE_TYPE_BASE". This is the major issue for me. This is the issue what I need to solve.
Casting, Yes I agree, I should do it in proper way. I can do it as below for 'Text' type.
xms::String text = reinterpret_cast<xms::TextMessage*>(pBase)-> getText();
But what I'm getting is "XMS_MESSAGE_TYPE_BASE". Why so?
Thanks
Renjith |
|
Back to top |
|
 |
mqjeff |
Posted: Mon Jan 12, 2009 7:45 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
The MQRFH2.Format field is wrong. It should be using a symbolic constant rather than a potentially wrong hardcoded value. |
|
Back to top |
|
 |
viswanath |
Posted: Thu Jan 15, 2009 1:58 am Post subject: |
|
|
Apprentice
Joined: 09 Jun 2005 Posts: 33
|
Jeff,
Could you please let us know what format to be set for sending the character data out of Broker?
Thanks for your help. |
|
Back to top |
|
 |
Vitor |
Posted: Thu Jan 15, 2009 2:24 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
viswanath wrote: |
Could you please let us know what format to be set for sending the character data out of Broker? |
I believe he means you should follow the best practice of using the MQFMT symbolic constant, rather than hard coding "MQSTR".
I could of course be putting the wrong words in his mouth, for which I apologise in advance. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
mqjeff |
Posted: Thu Jan 15, 2009 2:54 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
|
Back to top |
|
 |
Renjith |
Posted: Thu Jan 22, 2009 5:50 am Post subject: |
|
|
Newbie
Joined: 09 Jan 2009 Posts: 5
|
We tried the options commented by you, but still no change in the output what the XMS client receives! |
|
Back to top |
|
 |
|