Parsing soap message namespaces properly

<Problem1>

I can successfully invoke my validateAddress soap-msg based service from a command line test tool by posting the soap request message below (A). However, when I generate a WSDL file for this service (correctly pointing it to the appropriate input and output documents, it does refer to a prefix name anywhere (“xsq” in my case).

What do I need to do to my WSDL file to cause a client (.Net, webMethods, AXIS, whatever) to generate a soap message with a root node of “xsq:validateAddress” instead of just “validateAddress”.

</Problem1>

<Problem2>

If I post the soap message (B) shown below, the default processor locates and invokes my service OK, but when I try to use queryDocument against the body of the message, the “Document View” shows the structure of the document with every node prefixed by “prefix0:”. That would be OK, if I could query against it, but a query of “/prefix0:validateAddress” returns null. See the two attached bitmaps.

This is easy to recreate and a real pain in the rear.

</Problem2>

(A) soap request message that invokes “myNamespace:validateAddress” and can be processed by queryDocument with a query like “/xsq:validateAddress”:

<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="[url]http://schemas.xmlsoap.org/soap/envelope/"[/url] xmlns:SOAP-ENC="[url]http://schemas.xmlsoap.org/soap/encoding/"[/url] xmlns:xsd="[url]http://www.w3.org/1999/XMLSchema"[/url] xmlns:xsi="[url]http://www.w3.org/1999/XMLSchema-instance"[/url] SOAP-ENV:encodingStyle="[url]http://schemas.xmlsoap.org/soap/encoding/">[/url] <SOAP-ENV:Header xmlns:SOAP-ENV="[url]http://schemas.xmlsoap.org/soap/envelope/"><requestMessageHeader>[/url] <organization>B2BPartner1</organization> <department>Dept01</department> <application>AppID1</application> <timeStamp>2003-08-01T17:54:47.779Z</timeStamp> <messageID>000123456</messageID> </requestMessageHeader></SOAP-ENV:Header><SOAP-ENV:Body> <xsq:validateAddress xmlns:xsq="myNamespace"> <address> <streetAddress1>1700 Lincoln</streetAddress1> <streetAddress2></streetAddress2> <city>Denver</city> <state>CO</state> <country>US</country> <postalCode>80203</postalCode> </address> <address> <streetAddress1>1025 Eldorado Blvd</streetAddress1> <streetAddress2></streetAddress2> <city>Broomfield</city> <state>CO</state> <country>US</country> <postalCode>80021</postalCode> </address> </xsq:validateAddress></SOAP-ENV:Body> </SOAP-ENV:Envelope>

(B) soap request message that properly invokes myNamespace:validateAddress, but causes queryDocument to break (no way to query the contents of the “validateAddress” element)

<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="[url]http://schemas.xmlsoap.org/soap/envelope/"[/url] xmlns:SOAP-ENC="[url]http://schemas.xmlsoap.org/soap/encoding/"[/url] xmlns:xsd="[url]http://www.w3.org/1999/XMLSchema"[/url] xmlns:xsi="[url]http://www.w3.org/1999/XMLSchema-instance"[/url] SOAP-ENV:encodingStyle="[url]http://schemas.xmlsoap.org/soap/encodin[/url]

Fred Hartman addressed my questions in the following reply:

I can successfully invoke my validateAddress soap-msg based service from a command line test tool by posting the soap request message below (A). However, when I generate a WSDL file for this service (correctly pointing it to the appropriate input and output documents, it does refer to a prefix name anywhere (“xsq” in my case).

What do I need to do to my WSDL file to cause a client (.Net, webMethods, AXIS, whatever) to generate a soap message with a root node of “xsq:validateAddress” instead of just “validateAddress”.


There is no way to control the prefix naming of any node in soap messages. At least it is different in each SOAP implementation and any real XML implementation should work without caring about the prefix. As you know:

 <xsq:validateAddress xmlns:xsq="uri:myNamespace">

is equivalent to

 <validateAddress xmlns="uri:myNamespace"> 

So you ask, “How can I define a Flow Map if the fieldName changes from prefix0:validateAddress to xsq:validateAddress to validateAddress to p3:validateAddress? Just when I think it works, I get a source value is null warning.”

When calling documentToRecord you can pass a nsDecls parameter, which defines the namespace → prefix mapping. This means that the prefix of the incoming document is ignored when building the IData when the namespace of an element is found in the mapping list.

For instance,

 nsDecls 
xsq = uri:myNamespace 

would produce a boundNode with an entry

xsq:validateAddress 

for all the following incoming SOAP docs:

 <prefix0:validateAddress xmlns:prefix0="uri:myNamespace"> 
<xsq:validateAddress xmlns:xsq="uri:myNamespace"> 
<p3:validateAddress xmlns:p3="uri:myNamespace"> 
<validateAddress xmlns="uri:myNamespace"> 
  

I think there was a bug in IS 4.6 and the nsDecls parameter was not getting generated for you. This is fixed in 6.0.1, but you have to fixup the generated Flow with 4.6.

If I post the soap message (B) shown below, the default processor locates and invokes my service OK, but when I try to use queryDocument against the body of the message, the “Document View” shows the structure of the document with every node prefixed by “prefix0:”. That would be OK, if I could query against it, but a query of “/prefix0:validateAddress” returns null. See the two attached bitmaps.

This is easy to recreate and a real pain in the rear.


the webMethods XQL implementation was done right about the time that XML Namespaces Note was first released. So it is made to work in two modes:

  1. With no prefix/namespace mapping, so that the raw prefix:localName of the query are compared with the prefix:localName of each element. This makes thing simplier, but it means that if the prefix changes in the incoming document you have problems. With point-to-point integrations the prefix rarely changes, so people don’t have to ever really care about the namespace mapping. With SOAP every implementation picks prefixes differently, so it is an issue right away.

  2. With a prefix/namespace mapping. This is the nsDecls parameter to queryDocument. You can pass an IData with keys as the prefix and value as the namespace. These are the mappings for use in the query, so in your instance you can pass

nsDecls
xsq =

Any idea how to process responses coming with different namespaces prefixes each time? In webMethods xmlNodeToDocument we specify prefix mapping statically. How can we parse incoming SOAP response message coming with different prefixes dynamically each time?

Populate the nsdecls parameter with the namespace names and prefixes that you expect. The namespace names are part of the contract described in the WSDL and must match exactly. The prefixes can be anything that the sender’s soap client chooses to send as long as those prefixes are assigned to the namespaces.

You can also create XQL queries that specify an asterisk (*) in place of the prefix so that it will match any prefix.

HTH,

Mark

Thank you Mark for your response. I have implemented successfully within the web service connector. In this case webMethods(version 6.0.1) is the client and websphere was the server.
The question i have though why do we have to query for single element with the SOAP XML Response using XQL? Why does webMethods statically attach elements of the SOAP to the prefixes during design time? Why does’nt it resolve them dynamically?
Thanks in advance for your response once again.

Not sure I fully understand your question. At any rate, answers on why webMethods designed or implemented a feature in a particular way would be better directed to them.

Mark

Mark,

Let me clarify my question. When i create a web service connector in webMethods, it expects the namespace prefix that was originally specified in the WSDL. But the websphere responds with a different prefix name (prefix value resolves to the same URL) in the SOAP response every time webMethods makes a call to the web service.

Now in my connector service in webMethods, i have to make XQL queries with wild card character (*) for prefixes as you mentioned before to deal the prefix changes dynamically coming in from the websphere. But when the SOAP response contains multiple complex objects and arrays, this would mean that i would have to put in code to query each individual element in the response message. This sometimes can be cumbersome. So i was wondering if there was a way webMethods could parse and give the response message without the prefixes attached to the names of the elements so that i could avoid the cumbersome XQL queries.

The web service connector just generates a Flow service. As written here many times before, that generated code has a number of issues including hardcoded Soap endpoint addresses, lack of retries loop on the soapHTTP call and others.

I almost never use the web service connector-generated Flow except in early, early testing. Use it for a model if you wish, but write your own Flow.

If you populate the nsdecls parameter correctly, you should be able parse the soap response correctly regardless of what prefix is returned from the service provider.

Mark

Mark C. is right about the nsDecls parameter. It is key to making sure the prefixes are used correctly. Here is the excerpt from the manual-

This will override the inbound prefix that webSphere is sending to the web service and populate it with the prefix you choose as long as the namespaces match. I’ve tested with webSphere and it works correctly.

Your flow service can extract the entire body at once doing something like -
getBodyEntries
Loop over /bodyEntries
xmlNodeToDocument (this is where the nsDecls parameter gets set)

Your Schema and WSDL design can influence whether prefixes and namespace get sent on each element. It has to do with the xml schema and the design style, ie salami, venetian, russian doll etc. and whether elements are qualified or not. In practice however :frowning: the different tool vendors react differently to these designs. Here is an XML best practices site and there are many more - http://www.xfront.com/BestPracticesHomepage.html.

HTH

Thank you both very much for your responses. They make perfect sense.

Regards,
Srinivas

As a side note, WS-I basic profile restricts document/literal messages to only a single body entry, so technically it is not necessary to use a LOOP statement.

Doc/lit messages can have multiple header entries though. Any headers that have the mustUnderStand attribute set to “1” must be processed by the soap server or the message must be rejected with a “Could Not Understand” soap fault.

Mark

First of all you are spending way to much time with the Basic Profile. :wink: Second you know a loop makes it look way cooler. :smiley:

Thanks for pointing it out. I don’t really know why I had it in there to start with.:confused: Must have been one of those days.

Someone has to. From the lack of attention to WS-I in its products, webMethods sure isn’t. :confused:

Unfortunately for them, their customers and competitors are not quite as ignorant. :mad:

Actually, the ignorance is not on the part of the developers and architects responsible for building the product, it’s on the part of those responsible for prioritizing product development (PD) investment and the ones that have the job of getting that layer of management to listen.

I mean, how can your flagship product neglect innovation around the single most important IT trend and hype generator of our day, SOA and web services, for nearly four years. That’s broken.

Mark, I think you are correct in that the head folks in the development organization at webMethods wanted to get it in faster but other forces prevailed. Unfortunately I believe it is coming pretty late to the game. The 7.1 release which is not until April/May 2007 is the release that is going to have the Basic Profile and Basic Security support. It will be somewhat dated at the point as the other vendors are now into their support for extended WS-* standards.

In connection with your rant my rant :mad: is the Mainframe Adapter support that they are yanking effective March 2007. This is a pretty major impact to us and will cost us in both new license fees for some other non-webMethods product and extending webMethods support if we go that route. Not to mention the major effort in rewriting the interfaces that use the Mainframe adapter. Since it wasn’t really communicated to us, it’s not sitting well with us. Which Adapter is next on the hit list?