WSDL service definitions are widely used to specify web services based on SOAP message exchange. They're especially useful for client code generation, allowing potential service consumers to easily generate code to access the service using their preferred web services stack (such as .Net, Axis2, etc.). But WSDL is not really designed to be edited "by hand", and even if you use one of the many available GUI tools to work with WSDL the process is error-prone and tedious.

JiBX offers you an alternative approach to easily create WSDL service definitions. You can use a data model generated by the JiBX CodeGen tool to define a service interface in terms of Java methods, passing and returning instances of classes corresponding to OTA messages. The Jibx2Wsdl tool, included in the JiBX distribution, can then generate a WSDL service definition from the service interface. The resulting WSDL is not JiBX-specific, and can be used for any implementation of the service.

The webservice directory of the JiBX/OTA distribution includes an Ant build.xml and sample service code. The sample service code defines methods matching all the OTA request-response message pairs relating to air travel. It uses the generated OTA data model (either full, or modular) for the representation of the messages.

Sample service

The source code for the provided sample service is the org.ota.ws.AirService interface, in the webservice/base/src directory. This interface defines 13 methods, each taking one of the OTA air request messages as input and returning the appropriate OTA air response message. Here's a partial listing:

/**
 * OTA Air web service definition. This defines a method for each request/response pair
 * in the Air group.
 */
public interface AirService
{
    /**
     * Request flight availability for a city pair on a specific date for a specific
     * number and type of passengers.
     */
    AvailRS avail(AvailRQ req);
    
    /**
     * Book a specific itinerary for one or more identified passengers.
     */
    BookRS book(BookRQ req);
    
    /**
     * Modify a previously-booked itinerary for one or more identified passengers.
     */
    BookRS bookModify(BookModifyRQ req);
    ...

The service definition includes a JavaDoc describing the overall purpose of the service, and each method definition includes a JavaDoc describing that particular method.

The actual class names used for the request and response message match those in the "standard" data model examples. If you change the data model generation you may need to change these classes.

Generating the WSDL

Generating a WSDL service definition from the service interface uses this target from the Ant build.xml script in the webservice directory:

  <!-- Generate bindings, schemas, and WSDL -->
  <target name="generate-wsdl" depends="compile-base">
    <delete quiet="true" dir="${basedir}/gen"/>
    <echo message="Running Jibx2Wsdl tool"/>
    <java classname="org.jibx.ws.wsdl.tools.Jibx2Wsdl" fork="true" failonerror="true">
      <classpath>
        <path refid="jibx-classpath"/>
        <path refid="model-classpath"/>
      </classpath>
      <arg value="-p"/>
      <arg value="${basedir}/base/bin"/>
      <arg value="-s"/>
      <arg value="${basedir}/base/src"/>
      <arg value="-t"/>
      <arg value="${wsdlgen-dir}"/>
      <arg value="-d"/>
      <arg value="-u"/>
      <arg value="classpath:/META-INF/binding.xml;${ota-schemas}/*.xsd"/>
      <arg value="org.ota.ws.AirService"/>
    </java>
  </target>

This target invokes the JiBX Jibx2Wsdl tool, with the jar file(s) created from the generated OTA data model on the classpath. The first arguments give the paths to the binary class files directory and the source files directory for the service definition code, along with the target directory for WSDL generation. Then the -d flag indicates this is a pure doc/lit service (rather than the default "wrapped" style), meaning the methods in the service definition each take a single parameter representing the input message and directly return the output message. The -u flag and following value give existing binding and schema definitions to be used for the service, in this case the binding for the generated OTA data model and the corresponding OTA schemas. The last argument is the actual service definition class.

To generate the WSDL service definition, just open a console to the webservice directory and type ant. The output will be generated to the webservice/gen directory.

Generated WSDL

The generated WSDL is named AirService.wsdl, with the name taken from the service class (by default - this can easily be changed by using Jibx2Wsdl customizations). Since the OTA messages used as input and output to the service need to be described in the WSDL, it needs to incorporate the appropriate OTA schema definitions. This is done using <xs:import> schema references. All the necessary schemas (including those referenced indirectly) are copied into the output directory with the generated WSDL so that the <xs:import>s can use local references. This makes it easy to package the contents of the directory for distribution as a complete service definition.

Here's an edited version of the output WSDL:

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://ota.org/ws/AirService"
    xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
    targetNamespace="http://ota.org/ws/AirService">
  <wsdl:types>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:tns="http://ota.org/ws/AirService"
        xmlns:ns1="http://www.opentravel.org/OTA/2003/05" elementFormDefault="qualified"
        targetNamespace="http://ota.org/ws/AirService">
      <xs:import namespace="http://www.opentravel.org/OTA/2003/05"
          schemaLocation="OTA_AirBookRQ.xsd"/>
      <xs:import namespace="http://www.opentravel.org/OTA/2003/05"
          schemaLocation="OTA_AirDemandTicketRQ.xsd"/>
      ...
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="availMessage">
    <wsdl:part name="part" element="ns1:OTA_AirAvailRQ"/>
  </wsdl:message>
  ...
  <wsdl:portType name="AirServicePortType">
    <wsdl:documentation>OTA Air web service definition. This defines a method for
        each request/response pair in the Air group.</wsdl:documentation>
    <wsdl:operation name="avail">
      <wsdl:documentation>Request flight availability for a city pair on a specific
          date for a specific number and type of passengers.</wsdl:documentation>
      <wsdl:input message="tns:availMessage"/>
      <wsdl:output message="tns:availResponseMessage"/>
    </wsdl:operation>
    <wsdl:operation name="book">
      <wsdl:documentation>Book a specific itinerary for one or more identified
          passengers.</wsdl:documentation>
      <wsdl:input message="tns:bookMessage"/>
      <wsdl:output message="tns:bookResponseMessage"/>
    </wsdl:operation>
    <wsdl:operation name="bookModify">
      <wsdl:documentation>Modify a previously-booked itinerary for one or more
          identified passengers.</wsdl:documentation>
      <wsdl:input message="tns:bookModifyMessage"/>
      <wsdl:output message="tns:bookModifyResponseMessage"/>
    </wsdl:operation>
    ...
  </wsdl:portType>
  <wsdl:binding name="AirServiceBinding" type="tns:AirServicePortType">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <wsdl:operation name="avail">
      <soap:operation soapAction="urn:avail"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    ...
  <wsdl:service name="AirService">
    <wsdl:port name="AirServicePort" binding="tns:AirServiceBinding">
      <soap:address location="http://localhost:8080/axis2/services/AirService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

As you can see from the listing, Jibx2Wsdl copies the JavaDoc documentation from the service class and service methods into the appropriate points in the WSDL. This is not a requirement for WSDL, but it makes it much easier for users of the service to understand the functionality being provided.

The <wsdl:service> element (near the bottom of the listing) includes the location where the service can be accessed. By default this is just generated as for a service deployed to the Axis2 web services stack running on the local system. You can change the location value by using Jibx2Wsdl customizations, or just edit the generated WSDL and change the value as appropriate.