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 » WebSphere Message Broker (ACE) Support » Reconstruct MQ message from Monitoring Event

Post new topic  Reply to topic
 Reconstruct MQ message from Monitoring Event « View previous topic :: View next topic » 
Author Message
dsteinmann
PostPosted: Wed Nov 21, 2018 10:51 pm    Post subject: Reconstruct MQ message from Monitoring Event Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

I configured Monitoring Event on a flow with MQ Input node and set the "include bitstream data in payload". I have another flow with an MQ Input node that reads those Monitoring Events from a Durable Subscription and writes the payload into a BLOB column in a database.

Now I would like to write a Java program that reads this BLOB and reconstruct an MQMessage from this BLOB. Unfortunately I don't see any way how to do this with the IBM MQ Java API.

I can do it interactively by writing the BLOB into a file and use RFHUTIL to read this file.

But I would like to do it from Java. Is it possible?
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Thu Nov 22, 2018 1:55 am    Post subject: Reply with quote

Grand High Poobah

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

Sure it is possible but it will be damn hard if you don't have the CCSID and format saved to the DB as well.
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
abhi_thri
PostPosted: Thu Nov 22, 2018 2:03 am    Post subject: Reply with quote

Knight

Joined: 17 Jul 2017
Posts: 516
Location: UK

Also what about the message headers (MQMD/RFH etc), are you saving those to the database as well?
Back to top
View user's profile Send private message
dsteinmann
PostPosted: Thu Nov 22, 2018 2:19 am    Post subject: Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

Quote:
Sure it is possible but it will be damn hard if you don't have the CCSID and format saved to the DB as well.

The Monitoring Event contains the whole MQ message (including MQMD, RFH2). This is why for example RFHUTIL can read it without problem. And MQMD and RFH2 contain the format and CCSID.

As I said, I would like to the same that RFHUTIL does, but with Java.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Thu Nov 22, 2018 6:36 pm    Post subject: Reply with quote

Grand High Poobah

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

dsteinmann wrote:
Quote:
Sure it is possible but it will be damn hard if you don't have the CCSID and format saved to the DB as well.

The Monitoring Event contains the whole MQ message (including MQMD, RFH2). This is why for example RFHUTIL can read it without problem. And MQMD and RFH2 contain the format and CCSID.

As I said, I would like to the same that RFHUTIL does, but with Java.

There should be a way. Look at the Java base interfaces and specially the one treating the message as stream source or target...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
dsteinmann
PostPosted: Thu Nov 22, 2018 10:35 pm    Post subject: Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

Quote:
There should be a way.

I know, it seems such a simple problem. I looked through the whole MQ Java API, but was not able to find such stream reading operations.

This is what I tried last and failed as well:
Code:
InputStream in = getClass().getResourceAsStream("/test-mq-messge.bin");
byte[] msg = StreamUtils.copyToByteArray(in);
MQMessage mqMessage = new MQMessage();
mqMessage.seek(0);
mqMessage.write(msg);
assertEquals("daniel", mqMessage.userId);

I really would be glad if someone could point out how to do this with the MQ Java API.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Fri Nov 23, 2018 1:18 am    Post subject: Reply with quote

Grand High Poobah

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

OK so look at the MQData interface in com.ibm.mq.headers, I believe you'll find it interesting...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
dsteinmann
PostPosted: Fri Nov 23, 2018 2:30 pm    Post subject: Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

Yes, the MQData was a good starting point, thank you!

The following method allGood() processes successfully my message

But the not so nice thing is that I hard-coded the headers. It would fail if the message has no RFH2 header.

Therefore I tried nothingParsed(), but as the name says, the headers are not parsed and the body is still the full message including MQMD and RFH2 header.
Code:
import java.io.DataInputStream;
import org.apache.commons.io.IOUtils;
import org.hamcrest.CoreMatchers;
import org.junit.*;
import com.ibm.mq.headers.*;

public class MqMsgTest {

   @Test
   public void allGood() throws Exception {
      DataInputStream dis = new DataInputStream(getClass().getResourceAsStream("/mq-msg.bin"));
      MQMD mqmd = new MQMD(dis);
      Assert.assertEquals("daniel", mqmd.getUserIdentifier().trim());
      MQRFH2 rfh2 = new MQRFH2(dis);
      Assert.assertEquals("AMQ.5BE355A587C71A20", rfh2.getStringFieldValue("usr", "MockResponseQueue"));
      String body = IOUtils.toString(dis, CCSID.getCodepage(rfh2.nextCharacterSet()));
      Assert.assertThat(body, CoreMatchers.startsWith("<port:getPartyResponse "));
   }

   @Test
   public void nothingParsed() throws Exception {
      DataInputStream dis = new DataInputStream(getClass().getResourceAsStream("/mq-msg.bin"));
      MQHeaderList headers = new MQHeaderList(dis, true);
      String body = new String((byte[])headers.getBody(), "UTF-8");
      Assert.assertThat(body, CoreMatchers.startsWith("<port:getPartyResponse "));
   }
}

Any idea what I am doing wrong with the MQHeaderList class?
Or is there another way to parse the headers dynamically?
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Sat Nov 24, 2018 2:27 am    Post subject: Reply with quote

Grand High Poobah

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

You are using a DataInputStream to create your header list...
Try doing it formally using a DataInput class
Also headers.getBody returns an Object. It is your assumption that the object is of type byte[] or can be cast to it... Furthermore it is your assumption that this byte[] is a representation of a string in UTF-8... I would go and look for the last header in the list and get the CCSID Field and Format Field to describe the actual data. Note the data might not be in UTF-8...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
dsteinmann
PostPosted: Sun Nov 25, 2018 6:06 am    Post subject: Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

Quote:
You are using a DataInputStream to create your header list...

DataInput is an interface, which the class DataInputStream implements. Here a snippet from the JDK implementation:
Code:
 public class DataInputStream extends FilterInputStream implements DataInput

And the DataInputStream class seems to work perfectly fine for the MQMD class (see my previous example).
Quote:
I would go and look for the last header in the list and get the CCSID

I would like to, but as I said in my problem description, the MQHeaderList does not parse the headers, so I can not access the CCSID information.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Sun Nov 25, 2018 7:01 am    Post subject: Reply with quote

Grand High Poobah

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

dsteinmann wrote:
Quote:
You are using a DataInputStream to create your header list...

DataInput is an interface, which the class DataInputStream implements. Here a snippet from the JDK implementation:
Code:
 public class DataInputStream extends FilterInputStream implements DataInput

And the DataInputStream class seems to work perfectly fine for the MQMD class (see my previous example).
Quote:
I would go and look for the last header in the list and get the CCSID

I would like to, but as I said in my problem description, the MQHeaderList does not parse the headers, so I can not access the CCSID information.

You have an inherent contradiction here.
On one hand you say the MQMD gets parsed fine, on the other hand you say that the headers do not get parsed...
so what happens if you do

Code:
int headercount = myheaderslist.size();


_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
dsteinmann
PostPosted: Sun Nov 25, 2018 1:02 pm    Post subject: Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

Maybe you misunderstood me. Following works fine:
Code:
DataInputStream dis = new DataInputStream(getClass().getResourceAsStream("/mq-msg.bin"));
MQMD mqmd = new MQMD(dis);

But this fails; headers.size() returns 0:
Code:
DataInputStream dis = new DataInputStream(getClass().getResourceAsStream("/mq-msg.bin"));
MQHeaderList headers = new MQHeaderList(dis, true);

I do not understand why MQHeaderList can not parse the headers.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Sun Nov 25, 2018 9:15 pm    Post subject: Reply with quote

Grand High Poobah

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

So your MQMD gets parsed fine.
Now assume you write the rest of the bitstream to an MQ Message. Can you then use the MQDATA obtained from that message to load the message?

I am thinking here that you might have some problems with the way the data has been stored. And maybe the header chaining or the data part is not quite right, possibly also an alignment problem? The RFH header is typically a 4 byte aligned header...

My guess is you'll have to look at the raw data to see what is wrong. Compare it to a bitstream saved from a correct MQMessage as MQData... This should show you where the differences are...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
dsteinmann
PostPosted: Sun Nov 25, 2018 11:42 pm    Post subject: Reply with quote

Novice

Joined: 09 Dec 2015
Posts: 15

Quote:
So your MQMD gets parsed fine.

Not only the MQMD, also the RFH2 as I wrote earlier:
Code:
DataInputStream dis = new DataInputStream(getClass().getResourceAsStream("/mq-msg.bin"));
MQMD mqmd = new MQMD(dis);
Assert.assertEquals("daniel", mqmd.getUserIdentifier().trim());
MQRFH2 rfh2 = new MQRFH2(dis);
Assert.assertEquals("AMQ.5BE355A587C71A20", rfh2.getStringFieldValue("usr", "MockResponseQueue"));
String body = IOUtils.toString(dis, CCSID.getCodepage(rfh2.nextCharacterSet()));
Assert.assertThat(body, CoreMatchers.startsWith("<port:getPartyResponse "));

So my data must be ok.

I am just trying to find a flexible way to parse the data, and the MQHeaderList class seems to be exactly what I need. I just don't understand why MQHeaderList does not work.
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 » WebSphere Message Broker (ACE) Support » Reconstruct MQ message from Monitoring Event
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.