Sunday, March 20, 2005

The "wrapped" document/literal convention

In my First Stop: WS-I posting, I recommended that web service developers always use document/literal, even though the WS-I Basic Profile allows rpc/literal. Some people might resist this notion, thinking the document style is harder to work with than rpc style, but that just isn't true. For developers that want an RPC-like programming experience using document/literal, all you have to do is use the "wrapped" convention.

Most SOAP implementations now support the "wrapped" convention. .NET uses it by default (and it doesn't support rpc/literal). All JAX-RPC compliant implementations also must support "wrapped". The "wrapped" convention yields the best results for interoperability.

The "wrapped" convention produces document/literal services, and yet it supports an RPC-style programming interface (i.e., it performs automatic marshalling of input parameters and return values).

The rules for the "wrapped" convention are fairly simple:
  1. "Wrapped" is a form of document/literal, therefore it must follow all the rules defined for document/literal. When defining a document/literal service, there can be at most one body part in your input message and at most one body part in your output message. You do *not* define each method parameter as a separate part in the message definition. (The parameters are defined in the types section, instead.)
  2. Each part definition must reference an element (not a type) defined, imported, or included in the types section of the WSDL document. These element definitions are "wrapper" elements (hence the name of this convention). You define your input and output parameters as element structures within these wrapper elements.
  3. A wrapper element must be defined as a complex type that is a sequence of elements. Each child element in that sequence will be generated as a parameter in the service interface.
  4. The name of the input wrapper element must be the same as the operation name.
  5. The name of the output wrapper element should be (but doesn't have to be) the operation name appended with "Response" (e.g., if the operation name is "add", the output wrapper element should be called "addResponse").
  6. In the binding definition, the soap:binding should specify style="document" (although this is the default value, so the attribute may be omitted), and the soap:body definitions must specify use="literal" and nothing else. You must not specify the namespace or encodingStyle attributes in the soap:body definition.

The following WSDL shows an example of the "wrapped" convention. It defines a simple add operation that takes two ints in and returns an int . This WSDL permits you to invoke the service like this:

int sum = addProxy.add(arg1, arg2);

Notice that the portType defines an operation called "add". It takes the "addRequest" message in and returns the "addResponse" message out. The "addRequest" message has one body part called "parameters" (.NET always uses this name for "wrapped" style). It references an element called "add". (The name of this input element must be the same as the operation name.) The "add" element is defined as a complex type that is a sequence of two elements (the input parameters), "arg1" and "arg2", which are both defined as ints. The "addResponse" message has one body part, also called "parameters", and it references an element called "addResponse". The "addResponse" element is defined as a complex type that is a sequence of one element (the return value), "sum", which is defined as an int.



<wsdl:definitions name=’addWrappedLiteral’

targetNamespace='urn:example/wrapped/add'

xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'

xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'

xmlns:types='urn:add/types'

xmlns:intf='urn:example/wrapped/add'>

<wsdl:types>

<xsd:schema elementFormDefault="qualified"

targetNamespace='urn:add/types'

xmlns:xsd='http://www.w3.org/2001/XMLSchema'>

<xsd:element name="add" type="types:add_t"/>

<xsd:element name="addResponse" type="types:addResponse_t"/>

<xsd:complexType name="add_t">

<xsd:sequence>

<xsd:element name="arg1" type="xsd:int"/>

<xsd:element name="arg2" type="xsd:int"/>

</xsd:sequence>

</xsd:complexType>

<xsd:complexType name="addResponse_t">

<xsd:sequence>

<xsd:element name="sum" type="xsd:int"/>

</xsd:sequence>

</xsd:complexType>

</xsd:schema>

</wsdl:types>

<wsdl:message name='addRequest'>

<wsdl:part name='parameters' element='types:add'/>

</wsdl:message>

<wsdl:message name='addResponse'>

<wsdl:part name='parameters' element='types:addResponse'/>

</wsdl:message>

<wsdl:portType name='addPT'>

<wsdl:operation name='add'>

<wsdl:input message='intf:addRequest'/>

<wsdl:output message='intf:addResponse'/>

</wsdl:operation>

</wsdl:portType>

<wsdl:binding name='addSoapBinding' type='intf:addPT'>

<soap:binding

transport='http://schemas.xmlsoap.org/soap/http'

style='document'/>

<wsdl:operation name='add'>

<soap:operation soapAction='urn:example/wrapped/add'/>

<wsdl:input>

<soap:body use='literal'/>

</wsdl:input>

<wsdl:output>

<soap:body use='literal'/>

</wsdl:output>

</wsdl:operation>

</wsdl:binding>

<wsdl:service name='addService'>

<wsdl:port name='addSoapPort' binding='intf:addSoapBinding'>

<soap:address location='...'/>

</wsdl:port>

</wsdl:service>

</wsdl:definitions>

56 comments:

MrTidy OTR said...

The link at the beginning of this post currently points to http://atmanes.blogspot.com/2005/03/first-stop-ws-i.htm, but it needs an 'l' on the end. http://atmanes.blogspot.com/2005/03/first-stop-ws-i.html is the correct URL.

Excellent post - thank you for the information.

Harri Kaukovuo said...

Great post.

Two minor corrections to the WSDL:

The WSDL starts with <wsdl:definition> and ends with <wsdl:definitions>. You might want to correct this to use <wsdl:definitions>.

The targetNamespace in types -section be targetNamespace="urn:example/wrapped/add/types" instead of targetNamespace="urn:add/types".

Corrections are just if someone wants to try out your sample WSDL with their development tool.

BR, Harri

James Waldrop said...

Any reason why you have two namespaces, one for the types and one for the rest of the WSDL (intf and types)?

My WSDL uses one namespace for both purposes and I'm wondering if that's incorrect.

Anne Thomas Manes said...

I prefer to keep the namespaces for the WSDL and the schema separate, but it certainly isn't a requirement to do so.

lcurry said...

Rule #4 that the name of the input wrapper element be the same as the operation name has a big impact on the shape of generated code. JAX-RPC generally maps such an element to a wrapper class or JavaBean, however Section 6.4.1 of spec states that when the operation has the same name as the element, the java mapping will be unwrapped, i.e. the resulting java operation will not have one JavaBean as an input param rather the composite elements that comprise the input element will individually be mapped to the operation parameter list, which can result in a mapping that is difficult and tedious to program. Would this justify removal of rule #4?

Anne Thomas Manes said...

The whole idea behind the "wrapped" convention is to simulate an RPC-like experience using document style interfaces. Rather than using a bean, the "wrapped" convention allows you to use unwrapped parameters. If you would prefer to use a bean, then name your input element something other than the name of the operation.

ChristianSonneJensen said...

Thanx for the explanation.

I have successfully set up Wrapped style wsdl, largely thanks to this blog, but I think it is cumbersome. I had a lot of trouble figuring out how to handle the namespaces. Does anyone know some good resources for getting to know how everything is tied together with namespaces? I get confused all the time.

I have one little challenge left: I have a no-arg operation on my webservice. How to I make a Wrapper for that???

Anne Thomas Manes said...

See this post for a short explanation of namespaces.

Here's how you would define a wrapper element for a void argument:

<element name="myMethod" type="tns:VoidType"/>
<complexType name="VoidType">
<sequence/>
</complexType>

Shmuel Koller said...

Learned a lot.
I am missing how a document/literal SOAP request is handled by a SOAP server - what is the signature of the Java method being invoked, and what is the marshalling/unmarshalling being done by Axis. This should even more manifest what is meant by wrapped. Here I pick Java+Axis as an example for SOAP language+server.
I thing these kind of end-point descriptions, in addition to wire-descriptions - do complement the overall semantics of wrapped, or unwrapped doc/lit.

Sudheer said...

Great Post. Excellent and I really appreciate it.

By the way, you mentioned wrapped produces document/literal services, but yet supports RPC like programming interface. That is it does the automatic marshalling of input parameters and return values.

I truly didnt understand what you meant by marshalling of input parameters. Also I am so confused about the marshalling in this context and difference between marshalling and serialization.

Rgds,

Sudheer

Anne Thomas Manes said...

In answer to these questions:
- How is a SOAP request handled by a SOAP server?
- What is the signature of the Java method?
- What marshalling/unmarshalling is being done by the server?

According to the WS-I Basic Profile v1.1, the signature of a SOAP message is defined by the QName of the child element of the SOAP Body. (When using wrapped style or RPC style, this QName is the same as the operation name. When using unwrapped document style, the Qname can be any name.) A number of SOAP implementations (e.g., Axis2) support alternative means to define the signature, such as the access point URL, SOAPAction, or wsa:Action.

When a SOAP server receives a request, it determines the message signature, and then looks it up in its internal configuration registry. (The registry is populated from the configuration files for all deployed services.) The configuration maps the incoming message signature to a specific class and method, and it specifies how to process the request: what handlers must be invoked in what sequence, and how to convert the incoming XML message into language objects. Likewise, the configuration also defines how to process the response: how to convert the return value into an outgoing XML message, and what handlers must be invoked in what sequence.

Serialization refers to converting an object or object graph into a format that can be stored or sent over a wire. Marshalling refer to the process of gathering the appropriate bits of information from multiple sources (e.g., multiple parameters) into a single object that can be serialized. Many people use the terms interchangeably.

Robert said...

Great post.

Will this work with nested complex types? If it should, then I'm stumped.

In Axis 1.4 I used java2wsdl to create the wsdl from my domain classes. I have not altered the generated WSDL, I overwrote my domain classes with the generated classes, and used the deploy.wsdd unaltered. Axis dies with SimpleDeserializer on the first instance of a nested class that it tries to parse (on the server, the client stub generates a correct SOAP query). Similar to your February discussion with Lindsey Hess. (Ironically, we are both dealing with search problems!) I'm starting to think that there is a subtle flaw the Axis generators.

I would greatly apreciate any pointers.

TIA

Roy said...

Hi Anne, I've just discovered your blogs and it is a pleasure reading them as they are clear and concise.

You presented a doc/lit wrapped WSDL with elementForDefault="qualified". Do you mind posting a sample SOAP response message for that?

I am interested in comparing any valid standards/WS-I compliant sample against the response from my own web service. My web service returns an object that contains a mixture of elements from the different schemas (with different namespaces) defined within the WSDL document. The body of the SOAP response looks like this.

<soapenv:Body>
<myOperationResponse xmlns="myNamespace">
<myOperationReturn>
<returnFieldA>2840054</returnFieldA>
<returnFieldC>
<returnFieldC1>2007-08-04T02:00:00.000Z</returnFieldC1>
<returnFieldC3 xsi:nil="true"/>
<returnFieldC4>MC2</returnFieldC4>
</returnFieldC>
</myOperationReturn>
</myOperationResponse>
</soapenv:Body>

Thanks,
Roy

Anne Thomas Manes said...

Roy -- See my post on namespaces.

The elementFormDefault="qualified" attribute specifies that local elements (elements defined within the context of a type rather than as direct children of the <schema> element) must be qualified by the targetNamespace. If you don't specify this attribute, then local elements are assigned to the "no namespace" namespace, and they must not be qualified.

If your WSDL uses elements from multiple namespaces, then each element in the message must be qualified in compliance with the schema definition.

The WSDL from my original post uses one schema to define both the response element and the types/children of the response element. Therefore a response message for my schema would look something like this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ns1:addResponse xmlns:ns1="urn:add/types">
<ns1:sum>41</ns1:sum>
</ns1:addResponse>
</s:Body>
</s:Envelope>

If I had defined the "addResponse" element in the "urn:add/elements" namespace and the "addResponse_t" type in a different namespace, "urn:add/types", then the response message would look like this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ns1:addResponse xmlns:ns1="urn:add/elements">
<ns2:sum xmlns:ns2="urn:add/types">41</ns2:sum>
</ns1:addResponse>
</s:Body>
</s:Envelope>

Ignacio said...

Hi Anne,

I have a two question about wsdl doc/lit wrapped.

1) The output and input message always must be have the part's name "parameters" ?

for example

<wsdl:message name="Operation_1">
<wsdl:part name="parameters" element="tns:Operation_1Response"/>
</wsdl:message>

<wsdl:message name="Operation_1Response">
<wsdl:part name="parameters" element="tns:Operation_1Response"/>
</wsdl:message>

2) The message's name must be the same that the operation name?

for example:

<wsdl:message name="Operation_1SoapIn" >
<wsdl:part name="parameters" element="tns:Operation_1"/>
</wsdl:message>

<wsdl:message name="Operation_1SoapOut">
<wsdl:part name="parameters" element="tns:Operation_1Response"/>
</wsdl:message>

<wsdl:portType name="WsWrappedWithRefSoap">
<wsdl:operation name="Operation_1">
<wsdl:input message="tns:Operation_1SoapIn"/>
<wsdl:output message="tns:Operation_1SoapOut"/>
</wsdl:operation>
</wsdl:portType>

is It a valid Doc/Lit wrapped ?

Thanks!
Ignacio

Anne Thomas Manes said...

Ignacio,

Your examples are correct as far as they go, but you must follow all six wrapped convention rules for the service to qualify as wrapped doc/lit. See the original post for the six rules.

Note that in your first code sample, you said:

<wsdl:message name="Operation_1">
<wsdl:part name="parameters" element="tns:Operation_1Response"/>
<:/wsdl:message>

But I think you meant:

<wsdl:message name="Operation_1">
<wsdl:part name="parameters" element="tns:Operation_1"/>
<:/wsdl:message>

Anne

Santosh Kumar Sharma said...

Dear All,

1. How to create Document / Literal WSDL from java interface ?? or how to create Java 2 WSDL using Document/ Literal.
2. from document/literal WSDL to java classes(stub, skelton, serivces).

I am using Axis 1.3 , tomcat-5.5.20 and eclipse.

Please provide the command and arguments for java2wsdl and wsdl2java for doc/lit.

is there any tool that help to generate java2wsdl and wsdl2java for doc/lit.

faith said...
This comment has been removed by the author.
faith said...

Thanks for the great article Anne.

I'm using JAX-WS. Once you have generated the java classes, you need to add annotations to the service class (@WebService).

I'm experiencing some problems in client stub generation and I'm wondering what is the right value for targetNamespacein the annotation:
@WebService(targetNamespace="...")

"urn:example/wrapped/add"
OR
"urn:add/types"

An Phu said...

The doc-lit wrap works fine if the response consists of a single object. However, if you are returning multiple objects, the method signature for the proxy can look ugly.

For example, if the addResponse_t complex type include an additional <element name="x" type="xs:int" />,

In Wcf, the generated method signature for the proxy would look like this:

class addProxy
int add(out int x, int arg1, int arg2);

The first element in the response becomes the return value, and subsequent elements in the response because part of the parameter list marked with the out keyword.

IMO, this is awkard. Maybe I am missing something. The general consensus seems to be doc-literal wrap is good, or at least in .Net. Why else make this the default style for wcf?

Hope this makes sense.

Puzzled,
An

Nadun Herath said...

<pre>
<message name="RemotePermissionException">
<wsdl:part name="fault" type="tns2:RemotePermissionException"/>
</message>
</pre>

Anne, if we have a exception message like above hw can we declare the wrapper element. please help. I thank you in advance.

Anne Thomas Manes said...

Nadun -- If you are using document/literal, then your message part must reference an element rather than a type. (In fact, according to the SOAP specification, all fault messages must use document/literal.) Describe the message this way:
<message name="RemotePermissionException">
<wsdl:part name="fault" element="tns2:RemotePermissionException"/>
</message>

where tns2:RemotePermissionException is declared as an element.

Nadun Herath said...

Hi Anne, Thanks for the reply. Is it <wsdl:part name="parameters" like in request and response messages or <wsdl:part name="fault".

Dean said...

Why do you recommend using document/literal?

What are the pros and cons of the different approaches (rpc/literal, rpc/encoded and document/literal)?

What if you are building web services for use inside the enterprise only, as a way to integrate legacy technologies? In other words, what if you are only building services where you control the client and the server, and are not concerned about third-party interoperability?

Anne Thomas Manes said...

Using most modern WS-* frameworks (i.e., less than 5 years old), document/literal is as easy to use as rpc/literal or rpc/encoded (it's simply a configuration issue). A document is fully described by a schema, which makes the message more manageable than one constructed using the RPC convention. An RPC structure is dymanically generated by the SOAP runtime framework; it does not have a complete schema definition. A document with a schema is more easily validated, transformed, versioned, encrypted, signed, etc. The only reason I would recommend using rpc style is if you are using a dynamic language for which no modern WS-* frameworks exist (i.e., less than 5 years old). The open source dynamic language communities gave up on WS-* a long time ago, so they haven't kept pace with the shift from rpc to document style. But if you're using a dynamic language, why are you using WS-* in the first place? REST is the way to go.

Eco-nemesis said...

Is there a way to avoid having the Response wrapped?

I tried to change the name of the ouput part and message to something completely different and also changing the name of the element from 'parameters' but for some reason the corresponding (Java) language stubs are still putting the response objects within the list of parameters uglily 'boxed' in Holder containers.

@WebParam(mode = WebParam.Mode.OUT, name = "responseCode", targetNamespace = "")
javax.xml.ws.Holder<java.math.BigInteger> responseCode,
@WebParam(mode = WebParam.Mode.OUT, name = "responseMessage", targetNamespace = "")
javax.xml.ws.Holder<java.lang.String> responseMessage,

I wish the response complex type element to be in one object, the return type of the signature of the method.

Santosh Kumar Sharma said...

Dear Anne sir,

Can you please provide some link from where i can know about - How to
consume Axis 1.3 RPC/encoded web services from C# client program.

Any specific attributes / value need to put while consuming from C# client
program in client program.

Regards,
Santosh

Anne Thomas Manes said...

Santosh: WCF does not support RPC/encoded, so you have to use the older ASMX tool in ASP.NET. Just include a WebReference in your client and link it to the WSDL document. Interoperability with Axis 1.3 is reasonably good, although you may encounter challenges if the interface uses arrays or nulls.

IlPuccio said...

Thaks a lot this post drove me out of the mess.

rahul said...

Sry i posted it before bt at wrong place , so reposting it:

Hi Annie

Please let me know what are the required changes that need to be done in order to convert a service from RPC\Encoded to Document\Literal. I am using AXIS (Latest Version).

What i did:
In my service that is RPC\Encoded style , i have done changes in its deploy.wsdd.
style="Document",use="literal". and re deployed it.When i accessed its wsdl(axis generates itself) It was according to document\literal. Using this wsdl i generated client code using gsoap. When i made use of that client code it say in its log "SOAP_TAG_MISMATCH" error. i analyed logs and find that may be some namespace issue is thr.

I want to verify my changes and want if u can comment on my issues.

Anne Thomas Manes said...

Rahul: In your deploy.wsdd, set style="wrapped" use="literal".

rahul said...

Thank you Anne!

rahul said...

Hi All

i have created a service using doc\literal. i am using AXIS on serverside. i have used gsoap utility to generate soap code for client. The issue i am facing is that if we look the logs of soap , i find the correct response , but my client is not able to read the correct response from it.
for example
if the result returned is "true" then too client doesn't read it as true and take default "false" as result.


This ruins the entire code logic. i am not able to debug the code. it say "Access Voilation at some point.

Can any one suggest me where can be the issue.
What should be done to avoid such thing.

May be i am posting it in wrong section. But do consider it.

rahul said...

Further adding to my previous post the test logs that are generated by soap say :

Tags 'result' and 'ns2:result' match but namespaces differ

Does it give any idea to resolve my issue. please give response.

rahul said...

Hi All

I want to know is thr any patch available for axis that solve the issue here as link:

http://www.theserverside.com/discussions/thread.tss?thread_id=38000

i too facing exactly the same issue as described by link.

Please let me know if any patch available for axis or is thr any other way to solve this issue.

mikelm said...

First of all thank you for this great information.
I'm currently on the way to implement a webservice with axis 1.4. I created a wsdl using the document/literal wrapped style.
Then I'm creating the java code with "WSDL2Java -s ...".
What I'm wondering about is, that the deployed webservice always shows the output parameters as part of the input parameters. Is there any way to avoid this thing?
Thanks in advance

The Iguana said...

Excellent clarification - I've been fighting with two different web service tools that generate different WSDL from the same service - apache/axis and wsdl.exe - this results in one service with doc-literal and another with doc-literal-wrapped, though they are supposed to be matching services called by the same client. Are you aware of any tools that can generate C++/Java (for embedding into Domino) for the wrapped WSDL style?

Pleuntje said...

You know what .When a SOAP server receives a request, it determines the message signature, and then looks it up in its internal configuration registry, true.. (The registry is populated from the configuration files for all deployed services.) The configuration maps the incoming message signature to a specific class and method, and it specifies how to process the request: what handlers must be invoked in what sequence, and how to convert the incoming XML message into language objects..,
Likewise, the configuration also defines how to process the response: how to convert the return value into an outgoing XML message, and what handlers must be invoked in what sequence.
Gr,Pleun

blogger de azi said...

Anne is right, this should be the right code:



<:/wsdl:message>

john said...

Amazing!I also wish him good luck to defend his gold medal. I like to share it with all my friends and hope they will also encourage him.

buy percocet online

Ewa said...

Nice to share my love is wonderful to tell you that a healthy green gives you the best Organic vitamins, herbal remedies and organic supplements. They use all natural ingredients to create organic products.
Service computer melbourne

kenge said...

Thanks for sharing the information!
I found this article very interesting and informative!
Keep sharing!

buy medicine

pioneer said...

I am happy when reading your blog with updated information! thanks alot and hope that you will post more site that are related to this site.

Buy Valium Online

Noel said...

This is like my fourth time stopping over your Blog. Normally, I do not make comments on website, but I have to mention that this post really pushed me to do so. Really great post .
buy xanax online

Bapu said...

I'm still learning from you, but I try to reach my goals. Since then enjoy reading all the information that appears on your blog.Keep come. Loved it!

buy adderall online

Ewa said...

I really enjoy simply reading all of your weblogs. Simply wanted to inform you that you have people like me who appreciate your work. Definitely a great post. Hats off to you! The information that you have provided is very helpful.
home it support melbourne

ashishmaihu said...

Such interesting read and information, thanks for sharing this post Cotton shirts for men

john said...

But, as I said earlier, we must accept that there are two sides of every aspect or a thing, one is good, and one is bad. Human being has not even spared Xanax, and used it as an intoxicating drug, rather abused it.

it support melbourne

John kim said...

There are some very great sources here and thank you for being so kind to post them here.

 Best Organic Vitamins 

abby brock said...

But, as I said earlier, we must accept that there are two sides of every aspect or a thing, one is good, and one is bad. Human being has not even spared Xanax, and used it as an intoxicating drug, rather abused it.

movers in marryland 

john said...

This is such a great post, and was thinking much the same myself. Another great update.
locksmith in new york

john said...

Hi! This is exactly what I was looking for. Thanks for sharing this great article! That is very interesting smile I love reading and I am always searching for informative information like this! You are bookmarked!
locksmith queens

john said...

This was a really outstanding post. In theory I'd like to compose like this too - taking time and real effort to make a solid article...
replace ignition

Andrew Jorge said...

Seem to be forward to considerate outstanding. Good luck for the following! Great blog post. Really looking forward to read more. Really enormous.
get MBA Thesis

Lara baxter said...

Nice post i really glad to read this informative post, thanks to share :)

business line rental

Ruwan Weerapura said...

I’m working on a web service implementation using WSDL first approach. I have few operations (methods) defined in the web service and need to find out which operation is being invoked.

I need to access this information ( method name) inside my Logical Handler implementation class.
My implementation is as follows:

String operation = (String) context.get(MessageContext.WSDL_OPERATION);

But this always returns NULL.

My environment is as follows:
IBM® WebSphere Application Server V7 (32-bit) Version 7.0.0.25 (2.0.14.WTE7070025-I20121016_1855)
Rational Software Architect for Websphere Software V8.0

Note: I have set the Jax-WS code generation version as 2.2 but my generated JAXB class has following comment.
Generated By:JAX-WS RI IBM 2.1.6 in JDK 6 (JAXB RI IBM JAXB 2.1.10 in JDK 6)

Please let me know if you see/know any issue around this and share any information/hint for accessing the web service method name inside the Logical Handler implementation.