Skip to main content

A Dive Into the Generated Client Code in Axis2

June 22, 2006

{cs.r.title}






When it comes to a SOAP stack, most of the users are keen on the code generator tool. It is probably the first tool they will use and often, the ease of use of the generated code governs the popularity of the particular SOAP stack. Axis2 makes a significant change in the code generator tool and the structure of the generated code as well. This article aims to drill down into the details of the generated code and guide the user into the particulars of the generated code and its usage.

Basics of Code Generation

Code generation for web services comes from the fact that the WSDL document associated with the web service describes the service fully in a machine-processable way. Hence, a tool can parse the WSDL and figure out how to call the service without human intervention.

The code generator has two uses as far as the generation of code from WSDL is concerned. It can generate code to access a service as a client, or it can generate the skeletal code to implement the service on the server side. The latter is referred to as the contract-first approach, where the WSDL is made prior to the service implementation.

Another important aspect of code generation is data binding. Data binding in code generation refers to the generation of relevant artifacts to represent schema types mentioned in the WSDL. In this case, the generated code should handle the conversion, into and out from, the relevant type artifact, too. For example, in the case of Java, a simple schema type (such as xs:string) would map to an already-present Java primitive type or class. A complex type would naturally map to a JavaBean. The generated code should generate the necessary logic to convert the XML representation into the Java representation, and vice versa.

The Axis2 code generator can handle both the client-side and server-side code generation. It also supports plugging in of different data binding frameworks and generating code through them rather than solely depending on Axis2's own framework.

The rest of this article uses a simple WSDL file, the currency converter found in the Resources section, to demonstrate the generated code. The focus of this article is limited to the client side.

Where Is the Code Generator?

In its simplest form, the code generator is a command-line tool. It also comes in other flavors, such as an Eclipse/IDEA plugin and a custom Ant task. However, all of these use the same tool core to generate code, and the options available are the same. All the examples in this article use the command-line tool, but the graphical equivalent is easy to figure out and can be used appropriately.

The batch/shell scripts for the code generator tool are available in the bin directory of the Axis2 standard binary distribution. Usually once the standard Axis2 distribution is downloaded and unzipped, the scripts are ready for action. If you are having problems in running the tools, the Axis2 site has a great deal of documentation on how to install Axis2 and on setting up the classpath, etc.

The First Round!

The Axis2 code generator requires only one mandatory option: the WSDL URI. It can be either a file reference or a URL. Hence, for the first round, run the code generator with the mandatory option only.

> WSDL2Java -uri currencyConvert.wsdl

Since there is no output location specified, the output will be directed to the current directory. The default data binding mechanism is ADB (Axis Data Binding).

There should be two artifacts visible immediately after the code generation:

  1. The build.xml file
  2. The src directory

Inside of the src directory, the source files will be available inside the org/apache/axis2 folder, since it uses a default package when not specified. The most interesting items here are the generated stub and the callback class, so let us analyze them closely.

The generated stub class, apart from the three constructors, has two public methods:

  • A convert method that takes a ConversionRequest object and returns a ConversionResponse object.
  • A startconvert method that takes a ConversionRequest object, and a CurrencyConverterServiceCallbackHandler that returns nothing.

The former is the synchronous invocation method and the latter is the asynchronous invocation method. Asynchronous invocation is one of the new features added to Axis2; the latter method utilizes the new client API to do the asynchronous invocation. As for the input and output, the ConversionRequest and ConversionResponse classes are generated as public inner classes of the stub.

Following is a code snippet that shows how the synchronous method can be used:

 //instantiate the stub
CurrencyConverterServiceStub stub
             = new CurrencyConverterServiceStub();
CurrencyConverterServiceStub.ConversionRequest
    request =  new CurrencyConverterServiceStub.
                              ConversionRequest();
//fill up the request object
  request.setAmount(100f);
  request.setFromCurrency("USD");
  request.setToCurrency("SLR");

//send and get the response
  CurrencyConverterServiceStub.ConversionResponse
     response=stub.convert(request);

Using the asynchronous method is not as straightforward as using the synchronous method. In order to use the asynchronous method, one has to first implement the callback class. The generated callback is an abstract class, so it can be conveniently overridden inline as an anonymous inner class. The following code snippet shows how the callback can be utilized to use the asynchronous method. Note that the asynchronous method returns immediately!

 //instantiate the stub
CurrencyConverterServiceStub stub =
               new CurrencyConverterServiceStub();
CurrencyConverterServiceStub.ConversionRequest
   request =
      new CurrencyConverterServiceStub.
                              ConversionRequest();

//fill up the request object
request.setAmount(100f);
request.setFromCurrency("USD");
request.setToCurrency("SLR");

//implement the callback
CurrencyConverterServiceCallbackHandler callback =
  new CurrencyConverterServiceCallbackHandler(null){

  public void receiveResultconvert(
  CurrencyConverterServiceStub.ConversionResponse
                                           param1){
   System.out.println("Converted amount is " +
                       param1.getAmount() +
                       " SLR");
   }
  };

//call the method
stub.startconvert(request,callback);

One important consideration when implementing the callback is selecting the methods to override. Each operation has two relevant methods in the generated callback: the receiveResult method and the receiveError method. The stub implementation is such that the receiveResult method is called when a successful result is received and the receiveError method is called when a SOAP fault is received. Hence, code for handling a successful response should go inside the receiveResult method and the code to handle an erroneous response should go into the receiveFault method.

For complete code samples, see the Resources section.

The Second Round: Use a Different Data Binding Framework

One of the most interesting features of Axis2 is its ability to handle multiple data binding frameworks easily and efficiently. The standard Axis2 distribution supports four data binding frameworks, namely ADB, XMLBeans, JaxMe, and JibX. One can also specify not to data bind, in which case the method signatures will have OMElements as inputs and outputs allowing the use of raw XML data.

For the second round, run the code generator with the -d xmlbeans option.

> WSDL2Java -uri currencyConvert.wsdl -d xmlbeans

One immediately noticeable deviation from the earlier artifacts is the generation of a new directory, resources, producing:

  1. The build.xml file
  2. The src directory
  3. The resources directory

The familiar stub can be found in the org.apache.axis2 package, but the method signatures are slightly different. As for the inputs and outputs, this time they will be XMLBeans classes. The newly created resources directory contains XMLBeans-specific resources that are in an XMLBeans-readable format.

The following code snippet uses the XMLBeans-generated classes.

CurrencyConverterServiceStub stub = 
                new CurrencyConverterServiceStub();
ConversionRequestDocument.ConversionRequest request =
     ConversionRequestDocument.ConversionRequest.
        Factory.newInstance();
       
        //fill up the request object
        request.setAmount(100f);
        request.setFromCurrency("USD");
        request.setToCurrency("SLR");

        ConversionRequestDocument requestDoc =
           ConversionRequestDocument.
                             Factory.newInstance();
        requestDoc.setConversionRequest(request);
        //call the method
        ConversionResponseDocument response =
                        stub.convert(requestDoc);

Notice that the XMLBeans classes need to be instantiated differently. However, the externally visible part of the stub has only changed slightly, and the rest of the semantics are virtually unchanged. This demonstrates the flexibility of Axis2 to use different data binding frameworks.

The Third Round: Tweak the Generated Code by using Options

The code generator provides a number of options for tweaking the generated code. While an exhaustive list of the options can be found in the Axis2 site, following are some interesting options that can be used in the client side.

One can try out the -u option, which causes the generated data binding classes to be expanded and moved to a separate package (this is only effective in the case of ADB). The method signatures of the stub will change slightly. One can also control which type of methods that are be generated (either synchronous or asynchronous) by using the -s and -a flags.

For example, the following command creates only the asynchronous methods in the stub:

> WSDL2Java -uri currencyConvert.wsdl -a

If there is a need for test classes, Axis2 can also generate a JUnit test case. This can be specified by the -t option. The generated test case, however, is not usable straight away. One needs to fill in the population part of data-bound classes in order to proceed. The methods that need filling are marked with a todo in the source file.

The following command generates a test class:

> WSDL2Java -uri currencyConvert.wsdl -t ...

An interesting tweak is the custom namespace-to-package mapping. The default for the data binding classes is to derive package names from their target namespaces. However, these automatic packages might be long and cumbersome, so users might need to swap the auto-generated package with a custom one. This can be done by using the -ns2p option, where a list of namespaces and packages can be specified.

Another convenience provided to the user is the auto-generated Ant build file. The generated build file has targets that allows the user to easily compile and make a .jar for the client. Often it is recommended to use the generated build file rather than doing it any other way, since the build file may alter the classpath to suit the relevant data binding framework. The best example for this is that when using XMLBeans, the compilation requires the newly generated resources directory to be in the classpath. The generated build file has targets that handle such classpath issues.

Conclusion

Axis2 is a lightweight SOAP framework that allows faster and efficient SOAP processing. The new code generator bundled with Axis2 supports the use of the new asynchronous API and allows the use of multiple data binding frameworks to be used underneath.

Resources

width="1" height="1" border="0" alt=" " />
Ajith Ranabahu is one of the principal architects of the Axis2 project and specializes in the ADB and codegen modules.
Related Topics >> Web Services and XML   |   

Comments

The link to the sample code

The link to the sample code is broken.