getBody vs. getBodyEntries

Hi,

I am trying to get my head around some of the web services best practices and any limitations that the webMethods toolset inflicts. I have successfully created a web service using a Custom SOAP processor. I had an issue that I worked around, but I want to make sure that I am not limiting myself with this work around solution.

I had an issue using getBody vs. getBodyEntries. I was originally [SIZE=2]using the soap:utils:getbody function. I was taking the output node from that public function and mapping it into the pub:validate function to validate
the node against an XML schema. This resulted in always passing schema validation no matter whether the XML I passed was valid or not. The only way validation failed was if I validated agiang the wM document instead of the wM schema component. I had in the past been told by webMethods support that they recommend validating against the schema component over the wm document, so I logged a ticket telling them that using this getBody service I was unable to validate against the schema.

They evnetually told me that I should be using the getBodyEntries function instead of the getBody function. So I tried that and then was able to validate against the schema successfully (meaning the validate function finally failed if I passed invalid XML).

However the getBodyEntries function ended up creating another issue when mapping its output node into the XMLNodeToDocument function. The document that it created always removed the root element from the document structure that I was trying to convert to. So I opened another ticket and they eventually came back with the following resolution:

[INDENT]When using the output of the getBodyEntries function (bodyEntries) as input to the XMLNodeToDocument function you must map the XMLNodeToDocument output to the root element of the referenced document rather than to the referenced document name. This is a special case for getBodyEntries when using its output as input to the XMLNodeToDocument. If you are using XMLNodeToDocument anywhere else you can map the output document to the high level document name.
[/INDENT]The rep told me that he was going to put a chage request into their support to address this issue, but I am not sure what the outcome will be. What I ended up doing was using getBodyEntries and mapping the index[0] of the output node into XMLNode toDocument function as they suggested and then mapped the output document of that service to the root element of the referenced document that I was converting to. I also mapped the index[0] of the getBodyEntries output node into the validate input object and validated against the wM schema component.

So after all this… Here are my questions:
1. When would you use getBody vs. getBodyEntries in WebMethods?
2. When you use getBody does it return the body tags and everything in between?soapenv:Body</soapenv:Body>
3. When you use getBodyEntries does it return an array of all “xml” nodes which are present in soap:body and excludes the soapenv:body tags?

4. I don’t like assuming that we will always only have one body entry. I am not sure why there would be mulitple body entries, but if it is allowed I do not like that I haven’t accomidated for that scenario. Can you give me an example of why we would pass a SOAP message with multiple body entries?
5. Is it possible to have multiple bodies in a SOAP message? And if so, why would you?

Thanks in advance for your help!
Sara


[/SIZE]

Sara,

My preference is to use pub.soap.utils:getBody and then follow that with a pub.xml:queryXMLNode to extract a node that can be mapped into a document without the extra hoops you are referring to. I frequently use a meta-data repository (RDBMS table or XML) to lookup the name of the document type to which the body should be mapped and the name of the schema against which it should be validated. If you design your naming conventions correctly you could derive these things rather than look them up.

I created a utility service called getDocumentFromSoapBody that does these things and returns a node which can be validated against a schema and a document inside a consistently named wrapper (“inputDocument”) that can be mapped directly into a service invoked using a “doInvoke” utility service. (The handling service is also looked up or derived based on QName).

I believe the WS-Interoperability standards recommend that only a single body element is permitted. I have not seen any service providers return multiple body entries although it is certainly a technical possibility.

Update: I could not find this convention in the WS-I Basic Profile 1.0 or 1.1. I think the convention of having a single child of the soap:body element is part of the document / literal wrapped style which is not an official standard. This IBM Devworks article discusses the various styles of soap messaging.

HTH,

Mark

Mark,

Thank you for your response. Since my last post I have experienced another issue with getBodyEntries where the output node does not convert to a complete document when I use the XMLNodeToDocument right after it. If I have a document List in my document that I am converting to, it will only map the last record of the document list and lose the previous ones.

So I started looking into your last response where you mentioned that you prefer to use pub.soap.utils:getBody and then follow that with a pub.xml:queryXMLNode to extract a node that can be mapped into a document. I am having trouble followig this and it is probably because of my inexperience with the queryXMLnode function. I haven’t yet figured out how to pull an XML node from this function. It seems like I can only output a resultType of string, even though the documentation around this service states that you can have many different result types. Could you provide an example of how you are using this function to extract a XML node out of a soap message and convert it to a document?

Thanks,
Sara

Sara,

I whipped up two examples that show use of getBody and getBodyEntries services to handle soap requests containing multiple elements in the soap body.

In both tests, I was able to extract the nodes and convert them to documents.Note that “document / literal wrapped” style calls for use of a single element (named for the web service operation name).

Hope that helps,

Mark
SoapTest.zip (14.8 KB)

Thanks Mark,

Your sample service helped me understand what it was that you were explaining to me. I think that using getBody followed by the queryXMLNode service produces the same “node” output that you would recieve when using getBodyEntries. In your queryXMLNode you specify "/.[0]" for the XQL query which I believe results in the same logic when I map the “0” index of the getBodyEntries output parameter (bodies
[
]).

After playing with it some more today, I realize that my real problem is with “XMLNodeToDocument”. If I have a XML message that contains an array with multiple records populated in that array AND I specify the document structure that I want to convert to in the documentTYpeName parameter, it will not map all of the data in the array. It maps only the last record in the array. If I do not specify the documentTypeName then the conversion works properly. Plus there are some funny mapping things that I need to do in order to get the document to be converted correctly in the right format depending on what node I am mapping into the XMLNodeToDocument function.

This all seems very quarky to me. I have attached a package with some simple tests of different ways to extract the soap body and convert to a document. Hopefully the comments on each service will explain what each test is trying to display. I think there might be a webMethods bug in here somewhere so I logged a ticket with webMethods. I am surprised that the documentTypeName does not create the document correctly. I sent the same package to them so that they can see the way these services are working for me.

Let me know if you have any insight.

Thank you for all of your help!
Sara
ASoapTest_Sara.zip (41.2 KB)

I have seen this behavior before when the node contained an XML document that did not match the structure described in the document type.

To test this, don’t drop the “document” variable from the pipeline after the pub.xml:xmlNodeToDocument step. Compare its structure (especially its top-level nodes) to that of the document type. If the top level names don’t match the built-in service won’t be able to use the document referenced in the documentTypeName parameter.

My experience suggests that when the structure of the node matches the document type the repeated elements will be mapped to the document list as you would expect.

Mark

Sara,

In looking at your test services very, very briefly, it would appear that the document produced by pub.xml:xmlNodeToDocument has as its first child element the field named “SenderSystem” whereas the document type has as its first child the field named “ns:VehicleStatusUpdateRequest/SenderSystem”.

If you modify your document type to “outdent” the children of “ns:VehicleStatusUpdateRequest” and then delete the document named “ns:VehicleStatusUpdateRequest”, your GetBodyService:getBody_specifyDocumentTypeName service will create the document list for “EventHistory” as you expect.

Mark

Thanks Mark,

Our document is generated from an external schema and validated against the schema component. I am not sure that changing the document structure or schema is going to be an option for us at this time. But I will keep that in mind the next time we create a schema to be imported into webMethods. I am surprised that using the documentTypeName in XMLNodeToDocument is causing this type of problem.

Thanks again for your help.
Sara

The problem is not that you are using the documentTypeName parameter, it is that the document type that you are referencing does not match the structure of the node you are attempting to map. Change the node or change the document type to make them match and it works exactly as you would expect.

Mark