Code generation for JiBX data binding converts operations defined by a Web service to method calls. In the most general case of document/literal (doc/lit) Web services the generated methods each take a single parameter object and return a single result object. This type of interface can be painful for developers because it adds both a layer of indirection and potentially a large number of extra classes (one input and one output class for each generated method).
Fortunately, there's an alternative way of generating methods that gives a much more usable API for many Web services. This alternative is called unwrapping, and the service definitions that it applies to are called wrapped definitions. The key difference that qualifies a service definition as wrapped is the structure of the input and output elements used for operations.
Here's a sample wrapped WSDL (partial) by way of an example:
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
xmlns:tns="http://ws.sosnoski.com/library/types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<schema elementFormDefault="qualified"
targetNamespace="http://ws.sosnoski.com/library/types"
xmlns="http://www.w3.org/2001/XMLSchema">
<element name="getBook">
<complexType>
<sequence>
<element name="isbn" type="string"/>
</sequence>
</complexType>
</element>
<element name="getBookResponse">
<complexType>
<sequence>
<element name="book" minOccurs="0" type="tns:BookInformation"/>
</sequence>
</complexType>
</element>
<element name="addBook">
<complexType>
<sequence>
<element name="type" type="string"/>
<element name="isbn" type="string"/>
<element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
<element name="title" type="string"/>
</sequence>
</complexType>
</element>
<element name="addBookResponse">
<complexType>
<sequence>
<element name="success" type="boolean"/>
</sequence>
</complexType>
</element>
<complexType name="BookInformation">
<sequence>
<element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
<element name="title" type="string"/>
</sequence>
<attribute name="type" use="required" type="string"/>
<attribute name="isbn" use="required" type="string"/>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="getBookRequest">
<wsdl:part element="wns:getBook" name="parameters"/>
</wsdl:message>
<wsdl:message name="getBookResponse">
<wsdl:part element="wns:getBookResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="addBookRequest">
<wsdl:part element="wns:addBook" name="parameters"/>
</wsdl:message>
<wsdl:message name="addBookResponse">
<wsdl:part element="wns:addBookResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="Library">
<wsdl:operation name="getBook">
<wsdl:input message="wns:getBookRequest" name="getBookRequest"/>
<wsdl:output message="wns:getBookResponse" name="getBookResponse"/>
</wsdl:operation>
<wsdl:operation name="addBook">
<wsdl:input message="wns:addBookRequest" name="addBookRequest"/>
<wsdl:output message="wns:addBookResponse" name="addBookResponse"/>
</wsdl:operation>
</wsdl:portType>
...
</wsdl:definitions>
This WSDL defines a service with just two operations: getBook and addBook. The getBook operation takes a getBook element as input, and returns a getBookResponse element as output, while addBook takes an addBook element as input and returns an addBookResponse as output. Each of these input and output elements in turn consists of a sequence of child elements, with some of the child elements defined directly using standard schema types and others referencing user-defined schema types.
As I said up front, this WSDL qualifies for unwrapped handling using JiBX. Here's the body of the client interface generated when using unwrapping (the -uw option for WSDL2Java):
public interface LibraryJibxUnwrapped {
/**
* Auto generated method signatures
* @param type* @param isbn* @param author* @param title
*/
public boolean addBook(
java.lang.String type,java.lang.String isbn,java.lang.String[] author,java.lang.String title) throws java.rmi.RemoteException
;
/**
* Auto generated method signatures
* @param isbn
*/
public com.sosnoski.ws.library.jibx.beans.Book getBook(
java.lang.String isbn) throws java.rmi.RemoteException
;
//
}
You can see that the JiBX code generation converted the operations into simple method call interfaces without introducing any extraneous objects (see JiBX Document/Literal Example for the interface generated when unwrapping is not used). The server-side interface is the same.
The key points that allow unwrapped handling with JiBX are:
You also need to supply an appropriate JiBX binding definition (using the -Ebindingfile {file} parameter for WSDL2Java - see JiBX Codegen Integration - WSDL2Java usage for more details). This must define abstract mappings for the complexTypes referenced by child elements of the inputs and outputs, with a type-name attribute matching the schema complexType name. If the child elements reference schema simpleType definitions the binding must also define a formats for each simpleType, with a label attribute matching the schema simpleType name. The binding definition must also specify the force-classes='true' attribute on the binding element.
For example, here's a binding definition that matches the above WSDL:
<binding force-classes="true" xmlns:tns="http://ws.sosnoski.com/library/types">
<namespace uri="http://ws.sosnoski.com/library/types" default="elements"/>
<mapping abstract="true" class="com.sosnoski.ws.library.jibx.beans.Book"
type-name="tns:BookInformation">
<value name="type" style="attribute" field="m_type"/>
<value name="isbn" style="attribute" field="m_isbn"/>
<collection field="m_authors">
<value name="author"/>
</collection>
<value name="title" field="m_title"/>
</mapping>
</binding>
And here's the actual
com.sosnoski.ws.library.jibx.beans.Book class:
package com.sosnoski.ws.library.jibx.beans;
public class Book
{
private String m_type;
private String m_isbn;
private String m_title;
private String[] m_authors;
public Book() {}
public String getType() {
return m_type;
}
public String getIsbn() {
return m_isbn;
}
public String getTitle() {
return m_title;
}
public String[] getAuthors() {
return m_authors;
}
}
The JiBX code generation for Axis2 currently requires that
classes coresponding to unwrapped child elements (such as
com.sosnoski.ws.library.jibx.beans.Book, in this case)
provide public default (no-argument) constructors.
JiBX handling allows the child elements of both inputs and outputs to be optional (with nillable='true', minOccurs='0', or both), providing the binding converts these child elements to object types rather than primitive types. It also allows repeated child elements (with minOccurs='unbounded', or any value of minOccurs greater than one), representing the repeated elements as arrays of the corresponding object or primitive types.