SOAP DocumentLiteral

I’m having some issues with getting this to work correctly. My basic problem is that I don’t understand the Input Signature Requirements. prefix:localname, I not sure what this should be. Is the localname the actual service that will be invoke by the default soap processor? What would the prefix be? I’ve defined the Namespace name and localname on the service that will be processing the incoming soap messages. But this document that is suppose to contain a field with prefix:localname has got me a bit stumped. I read through the documentation on SOAP Development and Web Services but I found the part on SOAP Messaging to be bit confusing. I’ve gotten the RPC stuff to work without any issues.
Thanks for any suggestions.

markg

Mark,

webMethods Integration Server uses something called the default soap processor to handle document/literal soap requests. By default the URL for this processor is http:\<host>:<port>\soap\default.

It determines which IS service to invoke using the qualified name (QName) and the namespace definition in the soap request. (The element that is the first child of the SOAP-ENV:Body element is known as the QName.)

This means that the QName must be namespace qualified, that is, must specify a namespace prefix and a namespace definition. The default soap processor looks up the service to invoke in a registry using a key formed by concatenating the namespace prefix with the QName. You can list the contents of this directory using the pub.universalName:list built-in service.

The localname will be the name of the wrapper service to be invoked. The prefix can be any valid namespace prefix such as “xs”, “dx”, “myPrefix” etc.

The namespace definition (defined by xmlns:<prefix>="<namespace>") must match exactly the namespaceName specified in the Universal Name section of the service’s properties.

For example, if you defined a wrapper service called demo.flows:fooWrapper and specified it’s universal name properties to have a localName of “foo” and a namespaceName of "http://demo", then your soap request would need to have the following structure:

Note that the following would also work

Your wrapper service (“fooWrapper” in my example) extracts the soap body from the soap request using pub.soap.utils:getBody and then uses pub.xml.queryXMLNode to create a document from the resulting “body” node.

You can enter any value for the prefix on the “nsdecls” parameter, but you must specify a namespace value that matches exactly the namespace definition contained in your soap request and contained in your services UniversalName’s namespaceName property.

Clear as mud?

Mark

Thanks Mark. I’m making progress but still not all the way there yet. I got the wsdl generated and the .Net client is now sending the SOAP doc/literal to webMethods. The default processor is shipping it over to the service I created to process it. But then it falls apart. The problem I’m having, I think, is the document I’m sending doesn’t appear to be well formatted. Even though what is going into the pipeline appears to be okay. If I look into the WmMonitor and view the xml it looks good.

Looking at the webMethods examples I can see what they have done with the document structure. I don’t understand the purpose of the @xmlns put into the document. This seems to setup the namespace for the body entry in the xml but it doesn’t work outside of webMethods. If you try to generate wsdl with that in it, it will error out on import to anything else. It is not a legal character except that it seems to put the correct entry in webMethods. So I guess what I’m really struggling with is the document structure for the inputs and outputs.

This is much much harder than it should be. I’m struggling with how I’m going to roll this out to my developers. I don’t believe they are going to take to this very well. I did this with RPC and it was a piece of cake to get working.

Markg

Mark,

As you said with soapRPC processor it is piece of cake,i agree with you and one of our integration uses this RPC and it is well behaving and regarding using SOAP doc/literal it is a bit complicated process and some how we may have to get deep knowledge share from Mark carlson.

Cheers,

Okay after being distracted by projects , I’ve finally gotten the doc literal to work and boy it was fun. But I have a couple of questions.

Basically as a proof of concept, I took a webMethods service and exposed it as a web service using doc literal. I consumed the web service using .Net. The document I used for input was very simple flat structure.

Has anyone done anything more complex? If so how did you do it?

I also created a generic publish service with one input and output. A simple string on each. I exposed that service using the RPC style. The service expects the string to contain an xml document which it then converts and publishes to the broker. I used .Net to construct an xml document and pass it to this web service as a string. This was much easy to implement than the doc literal service but it also requires the .Net developer to know the structure of the xml it needs to pass to webMethods.

I guess I am struggling a bit with what is the best way to do this but that is also going to be reasonable to develop with our existing developers.

Hi

You might want to check the list of issues we had with connecting WebSphere to wM through webservices…

http://www.wmusers.com/wmusers/messages/117/42559.shtml

Chris

Mark,

See my latest blog post on an alternative that greatly simplifies exposing Java and Flow services as document/literal web services. It takes more effort to create the custom soap processor, but once that is in place, exposing new doc/lit web services is a snap.

As for your question on something more complex, the input and output signature can be any document structure with the one caveat that the contents of the document structure need to be easily serializable (convertible into XML). For example, if you have a custom java object embedded as an object data type in your input or output, don’t expect that to work without a lot of effort.

Mark

Thanks for the feedback. A few more questions if you don’t mind…

I’m still a bit confused on the proper document structure that is used as input into the doc literal web service.

As a test I have the following document defined withing webMethods:
The following five fields are all of type sting. A simple flat structure. testpublish represents the local namespace of the service. I have added namespace qualification into each field. This works but is it the correct way? The documentation says the first top level field should be prefix:localnamespace . But when the wsdl is generated this comes across as a string type call testpublish. I can invoke it from .Net and my testpublish service gets and I can parse it, but I’m thinking somehow this not the correct structure. What am I missing here?

xsd:testpublish
xsd:name
xsd:address
xsd:city
xsd:state

I finally figured out some of the issues with this. One thing that helped is a little tool called tcptrace http://www.pocketsoap.com/tcpTrace/ . It lets you look at the soap messages going between the two systems which is nice. In my case, what I was sending back as the soapResponse did not match the structure that had been generated via the WSDL that .Net was expecting.

I can successfully generate a doc/literal(SOAP-MSG in webMethods terms) wsdl file and consume it in .Net. However when constructing a soapResponse to an invocation of this webservice, the xml in the soapResponse does not match the output document used to in the generation of the WSDL. If I place a field called @xmlns (with the value set to the namespace) into the output document, it then works correctly. However this then breaks the ability to generate valid WSDL, the @xmlns field causes an error in the wsdl generation.

The structure of the flow and documents:
I have two documents, one for input and one for output. The document structure consist of one document object and five fields all of which are namespace qualified including the document. The output document is pretty much the same.

The flow service looks like this -

Input is set to - soapRequestData, soapResponseData
Output is set to - soapResponseData

Flow logic
soapDataToString
xmlStringToXMLNode
queryXMLNode
some mapping stuff
documentToXMLString - this where i construct the reply document using the output document mention above. But it only works if I include the @xmlns field with the namespace set as a value.
xmlStringtoXMLNode
addBodyEntry
map

Is this the way it is suppose to work? Because I have to go back and modify the output document after I generate the valid WSDL to contain this @xmlns field. It’s a minor issue but I was wondering if that is what they intended.

Mark,

I’m not quite sure why you can’t get a soap response that follows the schema in your WSDL. Since you have complete control over how you construct the soapResponse, you should be able to accomplish what you need.

I think you can add the prefix and namespace qualification to the soapReponse by configuring the documentToXMLString service such that the document input parameter contains a single (indented) child document named prefix:documentName and where the nsDecls input parameter contains a namespace entry for that prefix.

The custom soap processor design we created for my current project is working well. It eliminates the need to build wrapper services for each Flow or java service you want to expose.

Mark

Thanks Mark. The prefix was the missing link. It is working correctly now. I wasn’t using a prefix just namespace. After re-reading the documentation it pretty clearly says use prefixes in order to avoid just the problem I was having. Your note cleared it up. Thanks again.

markg

I am in the process of creating a Doc/Literal WSDL for a service that takes in a string variable (request) as an input. However, the string variable will contain XML data as input. I have tried defining the input and output documents as follows. I have created a wrapper service that takes soapRequestData and gives out soapResponseData. When I try to consume the WSDL using a web service connector. It seems to translate the string variable request into a document. This causes a failure since the target service is expecting request variable to be a string and not a document. I have tried everything I can to fix this but have not had much luck. I would greatly appreciate if anybody could shed light into this.

Please see attachments.

WSDL Error when XML string is an input
WSDLError.doc (30.7 k)

Rashmi,

I really, really, don’t like the practice of stuffing an XML document inside of a single string variable and then calling that a soap request. A couple of reasons for this are that you can never validate the content of your string against an XML schema or use the contents to make routing or transformation decisions.

I’m not clear on what your question is? What soap client will consume the service you are exposing as document/literal and describing in the WSDL?

What do you mean by “that request is now treated as a document and is causing the target service to fail”? You control how you extract data from a soap request. If you want to pass only a string, just convert the node returned by the getBody statement to pub.xml:queryXMLNode and use XQL to get the contents of the request variable.

Mark