Skip to main content

Transform Java classes into Web services using Axis2 and JiBX, Part 1: Use XML to define a Web service from your Java classes

Leverage XML to reuse existing Java code for Web services deployment

Tyler Anderson graduated with a degree in computer science in 2004 and a master of science degree in computer engineering in December, 2005, both from Brigham Young University.

Summary:  XML is powerful in that it can be used to define just about anything. What's more, it is the basis for an externally readable format for a majority of applications, most notably for the purposes of this series, Axis2 and JiBX. On top of that, as Web services become more and more ubiquitous, turning your legacy Java® projects into full-fledged Web services is increasingly becoming a priority. Unlike in the past, when the automatic generation of Web services was limited to a service and a single class, developers now have the option to generate a service or multiple services from the various Java classes in their existing projects. This article, Part 1 of a two-part series, uses XML to define a Web service from existing Java classes.

View more content in this series

Date:  20 Mar 2007
Level:  Intermediate
Activity:  1260 views
Comments:  

Introduction

Web services are increasingly more important in day-to-day development, and one of the more popular open source platform choices for developing Web services is Axis2. Written in the Java language, Axis2 can leverage a great deal of freedom from JiBX, a framework for binding XML to Java. Meaning, you already have a Java project, full of your Java classes and data structures, and you don't want to mess with, or change them whatsoever. JiBX allows this by binding XML data used by Axis2 to your Java classes. Advantages of this include easier code maintenance because the Web service will just use your already developed, tried and true Java classes.

This article introduces the Java classes that will be used in this two-part article series, and explains how to generate a Web Services Description Language (WSDL) and JiBX definition that accurately describes these Java classes. In Part 2 of this series, you'll use the WSDL and JiBX XML documents to create a Java implementation of a Web service that uses your Java classes as the data binding.


System requirements

For this two-part series, you'll need:

  • Axis2, binary and WAR distributions, which you can download from the Axis2 home page (see Resources).
  • JiBX 1.1, which you can download from the JiBX SourceForge page (see Resources).
  • Geronimo 1.1.1, downloadable at the Geronimo home page (see Resources).

Once you've done all of that, unzip Geronimo and type: java -jar <geronimo-home>/bin/server.jar.

Then, to deploy the axis2.war file, copy axis2 to the <geronimo-home>/deploy directory.

Unzip the Axis2 binary, and set the AXIS2_HOME environment variable to the directory where you unzipped the Axis2 binary (in my case, c:\apps\axis2-1.1). Next unzip JiBX, and copy all the JARs in <jibx-home>/lib (except stax-api.jar because Axis2 already has the stax-api.jar) to the <axis2-home>/lib directory.

Your environment should be all set!


The Java classes

Here are a few Java classes that make up a simple Web service Java project. The actual Java classes don't matter all that much, and you could use any Java classes that you might have created. There are three classes in this project: OneWayRequest, TwoWayRequest and TwoWayResponse. Take a look at each of them in order, beginning with OneWayRequest (see Listing 1).


Listing 1. OneWayRequest Java class

package com.ibm.devWorks.xml.simpleService;

public class OneWayRequest {
  protected String requestData;

  public String getRequestData() {
    return this.requestData;
  }

  public void setRequestData(String requestData) {
    this.requestData = requestData;
  }

}

Here you see a single field, requestData, that contains the data of the request. The class has two methods: One to set the field, and one to retrieve the field's value.

Next take a look at the TwoWayRequest class in Listing 2.


Listing 2. TwoWayRequest Java class


package com.ibm.devWorks.xml.simpleService;

public class TwoWayRequest {
  protected String echoString;
  protected boolean booolean;

  public boolean getBooolean() {
    return this.booolean;
  }

  public void setBooolean(boolean booolean) {
    this.booolean = booolean;
  }

  public String getEchoString() {
    return this.echoString;
  }

  public void setEchoString(String echoString) {
    this.echoString = echoString;
  }

}

This class is a little larger and it contains two fields: one called echoString and the other booolean. As in the previous class, the class has getter and setter methods for each field.

Look at the last class, TwoWayResponse, in Listing 3.


Listing 3. TwoWayResponse Java class

package com.ibm.devWorks.xml.simpleService;

public class TwoWayResponse {
  protected String echoString;
  protected boolean invertedBoolean;

  public boolean getInvertedBoolean() {
    return this.invertedBoolean;
  }

  public void setInvertedBoolean(boolean invertedBoolean) {
    this.invertedBoolean = invertedBoolean;
  }

  public String getEchoString() {
    return this.echoString;
  }

  public void setEchoString(String echoString) {
    this.echoString = echoString;
  }

}

This class is fairly similar to the previous class, TwoWayRequest, but it doesn't have to be. Your response class might contain several data items from a record in a database. That completes the Java classes! Next, you'll look at the WSDL that exposes these classes as a Web service.


Exposing the Java classes as a service through WSDL

In Part 2 of this series, you'll use Axis2 to read the WSDL you create in this section to create a Java implementation of your Web service.

Before going any further, you need to know a little about the intended Web service. The OneWayRequest class signifies a Web service operation that is one-way with only a request that sends request data in its field, requestData. The TwoWayRequest and TwoWayResponse classes signify a Web service operation that is two-way with both a request and a response, where the echoString field in the response has the same value of the echoString field in the request. The invertedBoolean field in the response is then the inverted value of the booolean field in the request (if booolean in the request is false, true gets sent as the value in the invertedBoolean field in the response).

Moving on to the WSDL, you first set up the namespaces, as shown in Listing 4.


Listing 4. Defining the namespaces of the WSDL

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
   xmlns:apachesoap="http://xml.apache.org/xml-soap"
   xmlns:impl="http://ibm.com/developerWorks/xml/SimpleService"
   xmlns:intf="http://ibm.com/developerWorks/xml/SimpleService"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   targetNamespace="http://ibm.com/developerWorks/xml/SimpleService">
...

These essentially prepare the WSDL, and you'll reference the namespaces later in the WSDL. When Axis2 reads this WSDL file, it'll need to know the namespace value that you refer to.

Next, define the schema in Listing 5.


Listing 5. Defining a schema

   targetNamespace="http://ibm.com/developerWorks/xml/SimpleService">
  <wsdl:types>
    <schema
       elementFormDefault="qualified"
       targetNamespace="http://ibm.com/developerWorks/xml/SimpleService"
       xmlns="http://www.w3.org/2001/XMLSchema">
      
      <!-- ELEMENTS -->
      
      <element name="OneWayRequest">
        <complexType>
          <sequence>
            <element name="requestData" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
      
      <element name="TwoWayRequest">
        <complexType>
          <sequence>
            <element name="echoString" type="xsd:string"/>
            <element name="booolean" type="xsd:boolean"/>
          </sequence>
        </complexType>
      </element>
      <element name="TwoWayResponse">
        <complexType>
          <sequence>
            <element name="echoString" type="xsd:string"/>
            <element name="invertedBoolean" type="xsd:boolean"/>
          </sequence>
        </complexType>
      </element>

    </schema>
  </wsdl:types>
...

This should be familiar to you. They are essentially your Java classes defined with a schema. Note that the fields in the Java classes match the sub-elements of the elements in the above schema. Also note the namespace, http://ibm.com/developerWorks/xml/SimpleService, which will be important later when you create the JiBX definition description.

Now define the messages, port types, bindings and the service of the WSDL (see Listing 6).


Listing 6. Completing the WSDL definition

...
  </wsdl:types>

  <!-- MESSAGES -->

  <wsdl:message name="OneWayRequestMessage">
    <wsdl:part name="input" element="impl:OneWayRequest"/>
  </wsdl:message>

  <wsdl:message name="TwoWayRequestMessage">
    <wsdl:part name="input" element="impl:TwoWayRequest"/>
  </wsdl:message>
  <wsdl:message name="TwoWayResponseMessage">
    <wsdl:part name="output" element="impl:TwoWayResponse"/>
  </wsdl:message>

  <!-- Port type (operations) -->

  <wsdl:portType name="SimpleServicePortType">

    <wsdl:operation name="OneWay" parameterOrder="input">
      <wsdl:input name="OneWayRequestMessage"
                  message="impl:OneWayRequestMessage"/>
    </wsdl:operation>

    <wsdl:operation name="TwoWay" parameterOrder="input">
      <wsdl:input name="TwoWayRequestMessage"
                  message="impl:TwoWayRequestMessage"/>
      <wsdl:output name="TwoWayResponseMessage"
                   message="impl:TwoWayResponseMessage"/>
    </wsdl:operation>

  </wsdl:portType>

  <!-- BINDING (bind operations) -->

  <wsdl:binding
     name="SimpleServiceSoapBinding"
     type="impl:SimpleServicePortType">
    <wsdlsoap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>

    <wsdl:operation name="OneWay">
      <wsdlsoap:operation soapAction="OneWay"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
    </wsdl:operation>

    <wsdl:operation name="TwoWay">
      <wsdlsoap:operation soapAction="TwoWay"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>

  <!-- SERVICE -->

  <wsdl:service name="SimpleService">
    <wsdl:port binding="impl:SimpleServiceSoapBinding"
               name="SimpleService">
      <wsdlsoap:address location="http://localhost:8080/axis2/services/SimpleService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

The messages defined are mapped to the request and response elements in the schema, and are used by the port type definition where the input or output of each operation is mapped to a message. The bindings section essentially maps an operation to a SOAP action, defining exactly the protocol and transport methods of the bound service and its accompanying operations. Lastly, the service section specifies available services, showing the service endpoint (the URL at which the service can be accessed) of each.

That completes the definition of the Web service. Next you'll map XML to the Java classes, enabling you to use JiBX as a data binding option in the next part of this series.


Creating a JiBX definition description

The main purpose of the JiBX definition description is to map a Java class to a namespace, including any desired fields. You'll know more of what is meant as you see the file created in this section. First, look at how the OneWayRequest class is mapped in Listing 7.


Listing 7. Mapping the OneWayRequest Java class


<?xml version="1.0" encoding="UTF-8"?>
<binding>
  <mapping name="OneWayRequest"
           class="com.ibm.devWorks.xml.simpleService.OneWayRequest">
    <namespace uri="http://ibm.com/developerWorks/xml/SimpleService"
               default="elements"/>
    <value name="requestData" field="requestData" usage="required"/>
  </mapping>
...

The name attribute of the mapping tag specifies the name of the element that directly relates to the OneWayRequest element on the WSDL schema you created in Listing 5. The class attribute maps the element to its Java class, the Java class shown in Listing 1. The uri attribute of the namespace tag places this mapping in the http://ibm.com/developerWorks/xml/SimpleService namespace, the same namespace as the OneWayRequest element shown in Listing 5. Lastly, you can see how the requestData sub-element shown in the WSDL in Listing 5 is mapped to the requestData field of the Java class shown in Listing 1 in the value tag. The name attribute specifies the sub-element in the WSDL, and the field attribute specifies the field name in the Java class.

Next, see how the other two Java classes are mapped in Listing 8.


Listing 8. Mapping the TwoWayRequest and TwoWayResponse Java classes

...
  <mapping name="TwoWayRequest" 
           class="com.ibm.devWorks.xml.simpleService.TwoWayRequest">
    <namespace uri="http://ibm.com/developerWorks/xml/SimpleService" 
               default="elements"/>
    <value name="echoString" field="echoString" usage="required"/>
    <value name="booolean" field="booolean" usage="required"/>
  </mapping>
  <mapping name="TwoWayResponse" 
           class="com.ibm.devWorks.xml.simpleService.TwoWayResponse">
    <namespace uri="http://ibm.com/developerWorks/xml/SimpleService" 
               default="elements"/>
    <value name="echoString" field="echoString" usage="required"/>
    <value name="invertedBoolean" field="invertedBoolean" 
           usage="required"/>
  </mapping>
</binding>

In Listing 8 you can see the similarities in how the OneWayRequest, and the TwoWayRequest and TwoWayResponse classes are mapped. This time, however, the names, classes and fields point to the appropriate data for the TwoWayRequest and TwoWayResponse elements. The one difference, however, is that these two elements have two sub-elements or fields. If a mapping tag has no sub-elements then it will have no children with value tags, and if a mapping tag has multiple sub-elements then the value tags are listed one after another, as shown in Listing 8.


Summary

Excellent! You're halfway there. You took existing Java classes, defined an XML schema for them, and exposed them through operations in a Web service through WSDL. You created a JiBX definition description that maps the Java classes to elements in the schema, enabling the Axis2 JiBX data bindings to properly bind the Web service SOAP data to your Java classes.

Come back for Part 2 where Axis2 will use the JiBX definition description to generate a service skeleton and client stub. You'll deploy the final Apache Axis2 Web service on Apache Geronimo, and test it by generating and creating a client that will communicate with the deployed Web service.



Download

DescriptionNameSizeDownload method
Part 1 sample codex-jibx1-source.zip3KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

  • Apache Axis2: Download this core engine for Web services.

  • JiBX 1.1: Download the JiBX framework for XML data binding to Java.

  • Geronimo 1.1.1: Get this easy-to-use, open source server.

  • JiBXSoap: Take a look at a SOAP Web services implementation of JiBX from the JiBX home page.

Discuss

About the author

Tyler Anderson graduated with a degree in computer science in 2004 and a master of science degree in computer engineering in December, 2005, both from Brigham Young University.

Comments



Trademarks

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology, SOA and Web services, Open source
ArticleID=202393
ArticleTitle=Transform Java classes into Web services using Axis2 and JiBX, Part 1: Use XML to define a Web service from your Java classes
publish-date=03202007
author1-email=tyleranderson5@yahoo.com
author1-email-cc=dwxed@us.ibm.com