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>

50 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

Anne Thomas said...

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

Anne Thomas 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.

Anne Thomas 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>

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 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

Unknown 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 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 Manzano 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 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 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.

Unknown said...
This comment has been removed by the author.
Unknown 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"

Unknown 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 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 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 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 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 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

Anonymous 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?

Driek 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

Unknown 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

Anonymous 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

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

Unknown said...

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

 Best Organic Vitamins 

Anonymous 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

Unknown 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

Unknown 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.

Reuben said...

Hi Anne

Is there a convention of how arrays should look in the XML, when using wrapped document/literal?

I have a question at stackoverflow about this, but no takers so far.

If there's no convention on whether to use:

<count>1</count>
<count>2</count>
<count>3</count>

vs

<count>
<item>1</item>
<item>2</item>
<item>3</item>
</count>

is there a form you prefer?