|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
SOAP with Attachment -- JavaCompute node and MIME parser |
« View previous topic :: View next topic » |
Author |
Message
|
msukup |
Posted: Wed Jul 26, 2006 7:12 am Post subject: SOAP with Attachment -- JavaCompute node and MIME parser |
|
|
Acolyte
Joined: 11 Feb 2002 Posts: 56
|
I am trying to do the following (WMB V6):
HTTPInput -> JavaCompute -> HTTPReply
where the input is a SOAP request, and the reply is a multipart MIME message, first part SOAP reply (text/xml), second part a pdf attachment. Since I am constructing the pdf attachment in a java compute node, i want to construct the MIME message and attach the pdf in the JCN as well.
I am running into the following problem when constructing the MIME message: when trying to attach the data to the MIME part (/MIME/Parts/Part/Data/BLOB/BLOB), i am receiving the following exception message:
'Last child of Data not owned by BLOB parser'
However, when I try to specify the parser for /MIME/Parts/Part/Data/BLOB as 'BLOB' with the following:
MbElement outBlob1 = outData1.createElementAsLastChild("BLOB");
outBlob1.setName("BLOB");
these result in the exception: 'The request for service /WBIMB failed.2230 Caught exception and rethrowing,ImbJniNode::evaluate,2310 Could not create parser,ImbMessageGroup::createParser,'
How exactly can I specify a non-XML (XML, XMLNS, XMLNSC) domain for an element in the JavaCompute node? In particular for BLOB parser?
thanks,
-m |
|
Back to top |
|
 |
fjb_saper |
Posted: Wed Jul 26, 2006 2:23 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Look up the help and examples in java.
You need a specific syntax to declare a node with parser.
Enjoy  _________________ MQ & Broker admin |
|
Back to top |
|
 |
msukup |
Posted: Thu Jul 27, 2006 7:19 am Post subject: |
|
|
Acolyte
Joined: 11 Feb 2002 Posts: 56
|
Actually, I have pored over all of the examples in the user-defined extensions manual as well as the examples in the sample gallery for java and java compute node, have had successful results using these nodes when just xml.
Back to my original problem, now that I have established that I have referenced the manuals and samples: The code snippet that I have included should associate a parser domain with an element, as per the manual. This full snippet is:
copyMessageHeaders(inMessage, outMessage);
// ----------------------------------------------------------
// Add user code below
//Set Properties content type to multipart
MbElement outRoot = outMessage.getRootElement();
MbElement outProps = outRoot.getFirstElementByPath("/Properties");
MbElement outPropDomain = outProps.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Domain", "MIME");
outPropDomain.setValue("MIME");
MbElement outPropContentType = outRoot.getFirstElementByPath("/Properties/ContentType");
outPropContentType.setValue(multipart);
//Set HTTP Header content type to multipart
MbElement HTTPHdr = outRoot.getFirstElementByPath("/HTTPInputHeader");
MbElement outMimeHTTPCT = HTTPHdr.getFirstElementByPath("/Content-Type");
if (outMimeHTTPCT == null){
outMimeHTTPCT = HTTPHdr.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "Content-Type", multipart);
}else{
outMimeHTTPCT.setValue(multipart);
}
//Create MIME Header
MbElement outMime = outRoot.createElementAsLastChild("MIME");
MbElement outMimeVersion = outMime.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "MIME-version", "1.0");
MbElement outMimeHdrCT = outMime.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "Content-Type", multipart);
MbElement outParts = outMime.createElementAsLastChild(MbElement.TYPE_NAME, "Parts", null);
MbElement outPart1 = outParts.createElementAsLastChild(MbElement.TYPE_NAME, "Part", null);
MbElement outContent1 = outPart1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-Type", "text/xml");
MbElement outContentId1 = outPart1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-ID", "part1");
MbElement outData1 = outPart1.createElementAsLastChild(MbElement.TYPE_NAME, "Data", null);
byte[] myByteArray2 = {5, 6, 7, 8};
byte[] bitstream = inMessage.getBuffer();
//MbElement outBlob = outData1.createElementAsLastChildFromBitstream(bitstream, "BLOB", "", "", "", 0, 0, 0);
MbElement outBlob1 = outData1.createElementAsLastChild("BLOB");
outBlob1.setName("BLOB");
//MbElement outBlob1 = outData1.createElementAsLastChild(MbElement.TYPE_NAME, "BLOB", null);
MbElement outBlob1a = outBlob1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", bitstream);
MbElement outPart2 = outParts.createElementAsLastChild(MbElement.TYPE_NAME, "Part", null);
MbElement outContent2 = outPart2.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-Type", "text/plain");
MbElement outContentId2 = outPart2.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-ID", "part2");
MbElement outData2 = outPart2.createElementAsLastChild(MbElement.TYPE_NAME, "Data", null);
//MbElement outBlob2 = outData2.createElementAsLastChildFromBitstream(myByteArray2, "BLOB", "", "", "", 0, 0, 0);
//MbElement outBlob2 = outData2.createElementAsLastChild("BLOB");
//outBlob2.setName("BLOB");
MbElement outBlob2 = outData2.createElementAsLastChild(MbElement.TYPE_NAME, "BLOB", null);
MbElement outBlob2a = outBlob2.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", myByteArray2);
// ----------------------------------------------------------
This snippet seems to successfully invoke the MIME parser, but when it should create the MIME part in domain BLOB, assigned parser BLOB, giving it the name BLOB, it encounters the error I originally posted (these result in the exception: 'The request for service /WBIMB failed.2230 Caught exception and rethrowing,ImbJniNode::evaluate,2310 Could not create parser,ImbMessageGroup::createParser,'). The lines in bold should be functionally equivalent to the eSQL statement:
DECLARE partData BLOB ASBITSTREAM(InputRoot.XML);
CREATE LASTCHILD OF M.Data DOMAIN('BLOB') NAME 'BLOB';
CREATE LASTCHILD OF M.Data.BLOB NAME 'BLOB' VALUE partData;
And yet, in JCN, it does not appear to work. Although the manual explicitly states to use the method CreateElementAsFirstChild(String) to assign a parser to an element.
Has anyone had the same experience? Am I missing something in my syntax, or is this functionally missing from the JCN?
[/i] |
|
Back to top |
|
 |
jefflowrey |
Posted: Thu Jul 27, 2006 7:26 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
http://publib.boulder.ibm.com/infocenter/wmbhelp/v6r0m0/index.jsp?topic=/com.ibm.etools.mft.doc/com/ibm/broker/plugin/MbElement.html wrote: |
createElementAfter
public MbElement createElementAfter(String parserName) throws MbException
Creates a new syntax element, inserts it after this element, and associates it with the specified parser class name. The new element becomes the next sibling of this element and shares the same parent.
The portion of the syntax element tree that is owned by the parser may only have its effective root at the first generation of elements (that is, as immediate children of root). The user-defined node interface does not restrict the ability to create a subtree that appears to be owned by a different parser. However, it is not possible to serialize these element trees into a bit stream when outputting a message.
Parameters
parserName - The name of the parser class. The supplied parser constants give values for some of the IBM supplied parsers. For example, PARSER_NAME.
Returns
The new element.
Throws
MbException |
_________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
msukup |
Posted: Thu Jul 27, 2006 7:51 am Post subject: |
|
|
Acolyte
Joined: 11 Feb 2002 Posts: 56
|
Thank you, Jeff -- the answer was in the fine print! So the answer: you can assign a different parser to a subtree in JCN, but it just won't reserialize it -- meaning there is nothing stopping you from doing it, it just won't work. great. lovely little gotcha. |
|
Back to top |
|
 |
jefflowrey |
Posted: Thu Jul 27, 2006 7:55 am Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
You shouldn't need to assign a different parser to this element, though.
What you want to do should work fine if you just put the data into the element when it's in the MIME parser. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
msukup |
Posted: Thu Jul 27, 2006 12:17 pm Post subject: |
|
|
Acolyte
Joined: 11 Feb 2002 Posts: 56
|
i wish that were the case, but when I tried this, creating BLOB elements with following:
MbElement outBlob1 = outData1.createElementAsLastChild(MbElement.TYPE_NAME, "BLOB", null);
MbElement outBlob1a = outBlob1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", bitstream);
, it didn't work. When I create the element BLOB but do not assign it parser BLOB, the tree looks fine (MIME/Parts/Part/Data/BLOB/BLOB followed by bitstream), but it raises the exception: 'Last child of Data not owned by BLOB parser'. As if!
In any case, I am abandoning doing it all within a single Java compute node. Instead, I will package multipart MIME message creation in eSQL (which I know works), and then call out to Java class to create pdf and return pdf, then serialize pdf and attach to MIME part. This should work, though it would have been nice to be able to do it all within one node. Oh well. |
|
Back to top |
|
 |
jefflowrey |
Posted: Thu Jul 27, 2006 12:29 pm Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
I don't quite understand why you want Part.Data.BLOB.BLOB...
I'd think you just want Part.Data.
Also, I think you want your outBlob1a to be a Name element with a Value element child that has the bitstream. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
msukup |
Posted: Thu Jul 27, 2006 1:55 pm Post subject: |
|
|
Acolyte
Joined: 11 Feb 2002 Posts: 56
|
first, let me say thank you, jeff, for taking the time to respond, as this has been perplexing me for a couple of days now . . .
Here is a summary of what I have tried:
1) Successful in creating multipart MIME msg in esql. Output tree looks like:
(0x01000000):MIME = (
(0x03000000):Content-Type = 'multipart/related; boundary=myBoundary'
(0x01000000):Parts = (
(0x01000000):Part = (
(0x03000000):Content-Type = 'text/plain'
(0x03000000):Content-Id = 'part one'
(0x01000000):Data = (
(0x01000000):BLOB = (
(0x03000000):BLOB = X'3c51313a436c61696d20786d6c6e733a51313d22687474
703a2f2f7777772e6962782e636f6d2f436c61696d223e3c436c61696d3e3132333c2f436c61696d
3e3c2f51313a436c61696d3e'
)
)
)
(0x01000000):Part = (
(0x03000000):Content-Type = 'text/plain'
(0x03000000):Content-Id = 'part two'
(0x01000000):Data = (
(0x01000000):BLOB = (
(0x03000000):BLOB = X'4f6e652074776f2074687265650d0a'
)
)
)
)
2) Unsuccessful trying to create same tree in JCN.
If I try this in JCN by creating MIME/Parts/Part/BLOB/BLOB, and setting value of lastchild BLOB to bitstream desired in MIME part, the tree looks the same, but when the message is reserialized, it is results in exception 'Last child of Data not owned by BLOB parser'
3) Also unsuccessful: if I try to create MIME/Parts/Part/BLOB/BLOB, assigning BLOB Parser to MIME/Parts/Part/BLOB element, this also gives me exception 'Could not create parser,ImbMessageGroup::createParser' (code from initial posting)
4) I have also tried as you suggested with no success, to set the bitstream directly to the Data element as a value of the element Data, but the following exception is then thrown when tree is serialized:
(0x01000000):faultdetail = (
(0x02000000): = 'The request for service /WBIMB failed.2230 Caught e
xception and rethrowing,ImbJniNode::evaluate,2230 Caught exception and rethrowin
g,ImbResetContentDescNode::evaluate,5661 Last child must be Parts or Data,MIMEWr
iter::write(),'
That resulting tree from this approach 4 does not resemble the successful MIME tree from esql, btw.
Conclusion? MIME multipart message construction not possible through JCN? Should I keep trying? (in other words -- have you successfully created SwA through JCN? If you have, i'll keep at it. if not, i'll let someone else open pmr and go with esql + java class for solution). |
|
Back to top |
|
 |
jefflowrey |
Posted: Thu Jul 27, 2006 2:39 pm Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
Can I see the successful ESQL?
I'm not as up on the details of the MIME parser as I should be - MIME itself is a slightly different story.
I continue to be surprised that it wants Data.BLOB.BLOB.
Your original Java code should be right to create the tree though. Unless 0x03000000 is actually a VALUE element and not a NAME-VALUE element... but I've forgotten.
I haven't successfully created a MIME document from a JCN - or a SwA at all - but that doesn't mean it doesn't work. I've never tried!
Make your own decisions about what you need to do, and if I get a chance I'll play with this. I'm in the midst of rebuilding my laptop, though, so it may be a bit.
Maybe someone else will pop their head in and see, too. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
mgk |
Posted: Fri Jul 28, 2006 5:09 am Post subject: |
|
|
 Padawan
Joined: 31 Jul 2003 Posts: 1642
|
Hi,
For most domains the root element name is the same as the parser name, so using a string literal for the parser name works. However, for the BLOB domain, althought the root element name is BLOB, the actual parser name for this domain is NONE. To avoid just this problem, you should not be using string literals for the parser name, instead you should use the constants defined in the class for the parser you are trying to create. In this case for the BLOB parser you should use the MbBLOB.PARSER_NAME constant as in:
Code: |
MbElement outBlob1 = outData1.createElementAsLastChild(MbBLOB.PARSER_NAME); |
If you look up the MbBLOB.PARSER_NAME constant in the API docs, you will see it resolves to the string NONE.
Regards, _________________ MGK
The postings I make on this site are my own and don't necessarily represent IBM's positions, strategies or opinions. |
|
Back to top |
|
 |
msukup |
Posted: Fri Jul 28, 2006 6:28 am Post subject: |
|
|
Acolyte
Joined: 11 Feb 2002 Posts: 56
|
Cool! Thanks, mgk! It works now from JCN.
For reference, here is code snippet:
final String multipart = "multipart/related; boundary=myBoundary";
byte[] myByteArray2 = {5, 6, 7, 8};
byte[] bitstream = inMessage.getBuffer();
// optionally copy message headers
copyMessageHeaders(inMessage, outMessage);
// ----------------------------------------------------------
// Add user code below
//Set Properties content type to multipart
MbElement outRoot = outMessage.getRootElement();
MbElement outProps = outRoot.getFirstElementByPath("/Properties");
MbElement outPropDomain = outProps.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Domain", "MIME");
outPropDomain.setValue("MIME");
MbElement outPropContentType = outRoot.getFirstElementByPath("/Properties/ContentType");
outPropContentType.setValue(multipart);
//Set HTTP Header content type to multipart
MbElement HTTPHdr = outRoot.getFirstElementByPath("/HTTPInputHeader");
MbElement outMimeHTTPCT = HTTPHdr.getFirstElementByPath("/Content-Type");
if (outMimeHTTPCT == null){
outMimeHTTPCT = HTTPHdr.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "Content-Type", multipart);
}else{
outMimeHTTPCT.setValue(multipart);
}
//Create MIME Header
MbElement outMime = outRoot.createElementAsLastChild("MIME");
MbElement outMimeVersion = outMime.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "MIME-version", "1.0");
MbElement outMimeHdrCT = outMime.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE, "Content-Type", multipart);
//Add first part -- copy of xmlns input
MbElement outParts = outMime.createElementAsLastChild(MbElement.TYPE_NAME, "Parts", null);
MbElement outPart1 = outParts.createElementAsLastChild(MbElement.TYPE_NAME, "Part", null);
MbElement outContent1 = outPart1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-Type", "text/xml");
MbElement outContentId1 = outPart1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-ID", "part1");
MbElement outData1 = outPart1.createElementAsLastChild(MbElement.TYPE_NAME, "Data", null);
MbElement outBlob1 = outData1.createElementAsLastChild(MbBLOB.PARSER_NAME);
outBlob1.setName("BLOB");
MbElement outBlob1a = outBlob1.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", bitstream);
//Add second part -- will be pdf attachment
MbElement outPart2 = outParts.createElementAsLastChild(MbElement.TYPE_NAME, "Part", null);
MbElement outContent2 = outPart2.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-Type", "text/plain");
MbElement outContentId2 = outPart2.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Content-ID", "part2");
MbElement outData2 = outPart2.createElementAsLastChild(MbElement.TYPE_NAME, "Data", null);
MbElement outBlob2 = outData2.createElementAsLastChild(MbBLOB.PARSER_NAME);
outBlob2.setName("BLOB");
MbElement outBlob2a = outBlob2.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", myByteArray2);
Thanks,
Meredyth |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
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
|
|
|
|