2008/12/06
6 Dec, 2008

How to Convert RPC/encoded WSDL into a Document/literal Wrapped WSDL

  • Nadun Herath
  • - WSO2

In the Web services world, a WSDL document describes a Web service. A WSDL document's binding style describes how the service is bound to a messaging protocol. Particularly, the SOAP messaging protocol. There are two types of binding styles, namely, RPC(remote procedure call) and document. SOAP binding can have encoded use or literal use. This gives you four style/use models. In addition to that there is a another type called the 'document literal wrapped' style, making total style/use models to 5.

(1.) RPC/encoded

Strengths

  • WSDL is straight forward
  • In the SOAP message, operation name appears hence so it's easy for  receiver to dispatching this message to the implementation of the operation.

Weaknesses

  • Type encoding info degrades performance.
  • Cannot easily validate a message due to certain SOAP definitions coming in from WSDL definition.
  • Not WS-I compliant.



(2.) RPC/literal

Strengths

  • WSDL is straight forward as in RPC/encoded and also in soap message operation name appears exactly.
  • Type encoding is eliminated.
  • WS-I compliant.



Weaknesses

  • Cannot easily validate, as in RPC/encoded style.



(3.) Document/literal

Strengths

  • Everything withing soap:body is defined in a schema hence can be validated using a validator.
  • No type encoding info
  • WS-I compliant.

Weaknesses

  • Operation name is lost. So dispatching is difficult.
  • WSDL is getting more complicated.

(4.)Document/encoded

Document/encoded is not WS-I compliant hence not used much.



(5.) Document/literal wrapped

Strengths

  • No type encoding info.
  • WS-I compliant
  • Can easily validate because everything in the soap:body is defined by the schema.

Weaknesses

  • WSDL gets complicated.
  • Can't use when you have overloaded operation.

Document/literal wrapped style yields the best results when it comes to interoperability. Almost all the SOAP implementation supports this convention and .NET uses it by default. All JAX-RPC compliant implementations also support this convention. The "wrapped" convention produces document/literal services, and yet it supports an RPC-style programming interface. As an example let's take this operation

RemoteComment[] logout(string token, RemoteComment remoteComment)



If we use a document/literal style we will get something similar to this



logoutResponse logout(logoutRequest request)

To get details about the data we have to look inside logoutRequest class. It would be nice if we can avoid this and use interfaces that use primitive types and simple objects. This is  where document literal wrapped style help us to use primitive types and simple objects. If the wsdl is a 'document literal wrapped' to unwrap in axis2 wsdl2java tool you have to give unwrapping option -uv during code generation. If wsdl is correct WSF's svcutil.exe do this automatically. As an example in the wsdl object-types should mark as nillable=”true” and schema should mark as elementFormDefault="qualified" otherwise .NET tool will go out of the unwrapping mode.



Now let's see how we can convert RPC/encoded wsdl to document/literal style.



(1.) Wrapped style is a subset of document literal  style hence rules applied to document literal applies to document literal wrapped style as well. Input and Output messages can only contain one body part. The method parameters are defined in the types section separately.



e.g :- # Input message

RPC/encoded:

<wsdl:message name="logoutRequest"> <wsdl:part name="token" type="xsd:string"/> <wsdl:part name="no" type="xsd:int"/> </wsdl:message>

change this into following: doc/literal:

<wsdl:message name="logoutRequest">

<wsdl:part name="parameters" element="impl:logout">

</wsdl:part>

</wsdl:message>

 

# Output message

RPC/encoded:

<wsdl:message name="logoutResponse">
<wsdl:part name="parameters" element="impl:logoutResponse">
</wsdl:message>

change this to the following

doc/literal:

<wsdl:message name="logoutResponse">
<wsdl:part name="logoutReturn" type="xsd:boolean"/>
</wsdl:message>

Note that in RPC/doc style message part refers to a type and all the parameters in logout operation is defined in the message itself. In the 'document literal wrapped style' message part refers to an element defined in types section and not to a type. In that element all the parameters are defined.

(2.) Part must refer to a element define in types section. You can refer part elements imported or define in the types section as well. These elements are defined as 'wrapper' elements. You  should define input and output parameters as  element structures withing this wrapper elements.



(3.) Wrapper element should be a complex type, that means a sequence of elements. Each parameter in the sequence will be mapped to parameters in the service.



(4.) Name of the input wrapper element should be same as the operation name. If operation name is 'logout' input wrapper element is also should be define as 'logout'.



(5.) Name of the output wrapper element should be operation name with Response word appended at the end. If operation is logout output wrapper element should be 'logoutResponse'.

<element name="logout" type="impl:logout"/>
<complexType name="logout">
<sequence>
<element name="token" type="xsd:string"/>
<element name="remoteComment" type="tns1:RemoteComment"/>
</sequence>
</complexType> 
<element name="logoutResponse" type="impl:logoutResponse"/>
<complexType name="logoutResponse">
<sequence>
<element name="logoutReturn" type="impl:ArrayOf_tns1_RemoteComment"/>
</sequence>
</complexType>

if logout is a void operation this is how it should define

<element name="logoutResponse" type="impl:logoutResponse"/>
<complexType name="logoutResponse">
<sequence/>
</complexType>

(6.) In binding definition soap:binding should specify style as 'document' and soap:body must be specify use as 'literal'. You should not include namespace or encoding style attributes in the soap:body definition.

<wsdl:binding name="jirasoapservice-v2SoapBinding"
type="impl:JiraSoapService">
<wsdlsoap:binding style="document" 
transport="https://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="logout">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="logoutRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="logoutResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>

(7.) When you define arrays in 'document literal wrapped' style, you can't refer to SOAP encoding namespaces.

Array define in RPC/encoded style:

<complexType name="ArrayOf_tns1_RemoteComment">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="tns1:RemoteComment[]"/>
</restriction>
</complexContent>
</complexType>

This is how above array should define in document literal wrapped style

<complexType name="ArrayOf_tns1_RemoteComment">
<sequence>
<element name="remoteComment" type="tns1:RemoteComment"
minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>

Here is a short WSDL code, which contains a single logout operation. Separate namespaces are used for the WSDL and schemas.

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="https://jira.atlassian.com/rpc/soap/jirasoapservice-v2"
xmlns:impl="https://jira.atlassian.com/rpc/soap/jirasoapservice-v2"
xmlns:intf="https://jira.atlassian.com/rpc/soap/jirasoapservice-v2"
xmlns:tns1="https://beans.soap.rpc.jira.atlassian.com"
xmlns:tns2="https://exception.rpc.jira.atlassian.com"
xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="https://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="https://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="https://beans.soap.rpc.jira.atlassian.com"
xmlns="https://www.w3.org/2001/XMLSchema">
<import namespace="https://exception.rpc.jira.atlassian.com"/>
<import namespace="https://jira.atlassian.com/rpc/soap/jirasoapservice-v2"/>
<complexType name="RemoteComment">
<sequence>
<element name="author" nillable="true" type="xsd:string"/>
<element name="body" nillable="true" type="xsd:string"/>
<element name="created" nillable="true" type="xsd:date"/>
<element name="groupLevel" nillable="true" type="xsd:string"/>
<element name="id" nillable="true" type="xsd:string"/>
<element name="roleLevel" nillable="true" type="xsd:string"/>
<element name="updateAuthor" nillable="true" type="xsd:string"/>
<element name="updated" nillable="true" type="xsd:date"/>
</sequence>
</complexType>
</schema>
<schema targetNamespace="https://exception.rpc.jira.atlassian.com" 
xmlns="https://www.w3.org/2001/XMLSchema">
<import namespace="https://beans.soap.rpc.jira.atlassian.com"/>
<import namespace="https://jira.atlassian.com/rpc/soap/jirasoapservice-v2"/>
<complexType name="RemoteException">
<sequence/>
</complexType>
<complexType name="RemotePermissionException">
<complexContent>
<extension base="tns2:RemoteException">
<sequence/>
</extension>
</complexContent>
</complexType>
<complexType name="RemoteAuthenticationException">
<complexContent>
<extension base="tns2:RemoteException">
<sequence/>
</extension>
</complexContent>
</complexType>
<complexType name="RemoteValidationException">
<complexContent>
<extension base="tns2:RemoteException">
<sequence/>
</extension>
</complexContent>
</complexType>
</schema>



<schema targetNamespace="https://jira.atlassian.com/rpc/soap/jirasoapservice-v2"
xmlns="https://www.w3.org/2001/XMLSchema">
<import namespace="https://beans.soap.rpc.jira.atlassian.com"/>
<import namespace="https://exception.rpc.jira.atlassian.com"/>
<element name="logout" type="impl:logout"/>
<complexType name="logout">
<sequence>
<element name="token" type="xsd:string"/>
<element name="remoteComment" type="tns1:RemoteComment"/>
</sequence>
</complexType> 
<element name="logoutResponse" type="impl:logoutResponse"/>
<complexType name="logoutResponse">
<sequence>
<element name="logoutReturn" type="impl:ArrayOf_tns1_RemoteComment"/>
</sequence>
</complexType>
<complexType name="ArrayOf_tns1_RemoteComment">
<sequence>
<element name="remoteComment" type="tns1:RemoteComment"
minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="logoutRequest">
<wsdl:part name="parameters" element="impl:logout">
</wsdl:part>
</wsdl:message>
<wsdl:message name="logoutRequest">
<wsdl:part name="parameters" element="impl:logout">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="JiraSoapService">
<wsdl:operation name="logout" >
<wsdl:input message="impl:logoutRequest" name="logoutRequest"/>
<wsdl:output message="impl:logoutResponse" name="logoutResponse"/>
<wsdl:fault message="impl:RemotePermissionException" name="RemotePermissionException"/>
<wsdl:fault message="impl:RemoteAuthenticationException" 
name="RemoteAuthenticationException"/>
<wsdl:fault message="impl:RemoteException" name="RemoteException"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="jirasoapservice-v2SoapBinding" type="impl:JiraSoapService">
<wsdlsoap:binding style="document" transport="https://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="logout">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="logoutRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="logoutResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="RemotePermissionException">
<wsdlsoap:fault name="RemotePermissionException" use="literal"/>
</wsdl:fault>
<wsdl:fault name="RemoteAuthenticationException">
<wsdlsoap:fault name="RemoteAuthenticationException" use="literal"/>
</wsdl:fault>
<wsdl:fault name="RemoteException">
<wsdlsoap:fault name="RemoteException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>

Author

Nadun Herath - (Final year Computer Engineering student)

 

About Author

  • Nadun Herath
  • WSO2 Inc.