Getting Started with Axis2 - Plain Old Java Objects (POJO)

Archived Content
This article is provided for historical perspective only, and may not reflect current conditions. Please refer to relevant product page for more up-to-date product information and resources.
  • By Deepal Jayasingha
  • 2 Dec, 2007

Introduction

In the world of Web services, there are two ways in which you can set about developing your own Web service, namely, the 'code first' approach and the 'contract first' approach. Eventually it does not matter which approach you opt for, as long as you implement the logic correctly.

Applies To

Axis2 1.3 and above

Code first vs. Contract first?

In the contract first approach, we start with the Web services contract called the WSDL (Web Service Description Language) document and then write the server-side and the client-side code based on that contract. To begin development with the contract first approach, you need to have an understanding about WSDL. But even if you do not have enough knowledge about WSDL, there are many tools that you can use to create a skeleton of the server-side and a proxy of the client-side code. If we take Axis2 as an example, there are a number of ways in which you can create a service or a client for a given WSDL document, Command line tools and IDE plugins being a few.

Experience tells me that not everyone will start from a WSDL when writing Web services and clients. Developers often like to convert a bit of code they have into a Web service. This is what we call the code first approach, where we start with the code rather than the contract. This approach is the most commonly used approach in industry. With the code first approach, we can write a Web service without knowing anything about WSDL, SOAP or other related technologies. Most importantly, if you have an old software system and you want to expose that as a Web service, then the code first approach will be a good candidate. The code first approach can also be used in prototype development. But remember, even though you start with code, you can get the WSDL document for your service in the end, because most of the Web service frameworks do support WSDL auto generation.

 Which is better?

Picking a clear winner from between the two approaches can be a hard task since each has its own advantages and disadvantages. So the best approach would be to choose one which fulfills your requirements.

In this article, we are going to discuss how to write a POJO Web service, its problems, limitations etc.

Writing a POJO Web Service

POJO stands for Plain Old Java Objects. So when it comes to Web services, a POJO Web service would entail writing a Java class and exposing that as a Web service. There are some limitations in Axis2 when writing such an application though. (These limitations whcih will be fixed in the coming release, are discussed later in this article.)

Once we have written the application, there are a number of ways by which we can expose that as a Web service.

  • POJO deployment (drop the .class file or .jar file into the POJO directory in the repository ).
  • As a service archive, where we bundle compiled classes along with the configuration file.
  • Using a programmatic method to deploy services.

It should be noted that all of the above supports JSR 181 annotations. Therefore, we can write our application using annotations and expect Axis2 to do the right thing.

In Axis2 POJO, we have the following features.



  • Supports primitive types (int , boolean , long , String etc ..)
  • Supports method excludes
  • Supports any kind of Java Beans
  • Supports Object Arrays
  • Binary support using byte and DataHandlers
  • Supports AXIOM
  • Serialization support for List
  • Namespaces handling
  • Inheritances support
  • Support for Bean property excludes
  • Method overloading support using annotations

Primitive Types

We can write a simple application or a complex application using primitive types. When writing a complex application, it is much cleaner to use Java beans, but it's not compulsory. A very simple POJO with primitive types is shown below;

package sample;

public class SampleService {

public String echo(String value) {
return value;
}

public int add(int a, int b) {
return a + b;
}

public void update(int c) {

}
}

You can easily make this into a Web service using one of the methods discussed above. Once that is done, all the public methods will be exposed as Web service operations.

If we are using archived based deployment, then the corresponding services.xml would look as follows.

<service name="SampleService">
<description>This is my Sample Service</description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass">sample.SampleService</parameter>
</service>

For a POJO service it is recommended to use a RPCMessageReceiver. It has been tested to handle any kind of complex scenario.

As you can see, I have not listed any of the operations that I want to expose. Axis2 takes care of that automatically and publishes all the public operations. To understand what happens, create a service archive file and deploy it. (How to create and deploy a service is out of the scope of this article. Please refer to the References section for more information on this.) And when you issue the ?wsdl url for that service (http://host:port/axis2/services/serviceName?wsdl), you will see the auto generated file with three methods. Once  the service is deployed, you can invoke the service as you wish. You can either generate a client or invoke the service in a REST manner.

For easy deployment, use the one line deployment mechanism, which will run the Axis2 server and deploy the service in one go.

public static void main(String[] args) throws Exception{
new AxisServer().deployService(SampleService.class.getName());
}

Now go to http://localhost:6060/

You will clearly see the three methods when you click on the SampleService link.

Exclude Methods

By default, Axis2 exposes all the public methods. However there are instances where you may to exclude some of them or there's simply no need to expose all of them. So let's look at how to control this behavior. Let's say we need to expose the 'echo' and 'add' methods but not the 'update' method. You can do that by adding the following entry to services.xml. It should be noted here that you cannot exclude operations in this way when using the one-line deployment mechanism. The procedure for excluding operations when deploying a service programmatically is out of the scope of this article.

<excludeOperations>
<operation>update</operation>
</excludeOperations>

Add the above entry to the services.xml and redeploy the service. Then, when you click on ?wsdl link, you will see only two methods and you will not see the 'update' operation in the WSDL document.

Support for JavaBeans

As we discussed above, Axis2 POJO deployment supports any kind of JavaBeans, but you need to make sure you  adhere to the JavaBeans standard when using JavaBeans.

  • Need to have getter and setter methods
  • Need to have a default constructor
  • Cannot have properties which start with upper case letters. For example, you cannot have a property like 'private String Age' in a bean but you can have 'private String age'
  • Bean properties can be of another bean, primitive types, any kind of object arrays, DataHandlers, etc.

Now let's write a simple JavaBean and try to use that inside the service class. Our bean will looks like the following.

public class Address {
private String street;
private String number;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}
}

Now we can change our service implementation class to use the Address bean as follows.

package sample;

public class SampleService {

public String echo(String value) {
return value;
}

public int add(int a, int b) {
return a + b;
}

public void update(int c) {

}
public Address get(String name) {
Address address = new Address();
address.setNumber("Number");
address.setStreet("Streat");
return address;
}
}

Compile the code again, create a service archive file and redeploy the service. Then look at the WSDL file carefully. You will see new operations, and in the types section, you will see a new schema element for Address.

Support for Object Arrays

You can also write POJO Web service applications with object arrays. You can have an object array as a field of a bean or as a method in the Service class as shown below. It should be noted here that an object array can be of any kind.

public Address[] getAddress(String [] names){

}

Otherwise, it can be as follows.

public Address[] getAddress(String [] names ,
Address[] address ,
int [] values){

}

Binary Support

You can write your POJO to accept or return Binary data. You can use either byte[] or DataHandler. Irrespective of what you use, depending on the Axis2 configuration, Axis2 will serialize and de-serialize the data into Base64 or MTOM. To have binary support, you can write your Service class as shown below.

Sending binary data

public DataHandler getImage(String fileName) {
File file = new File(fileName);
DataHandler dh = new DataHandler(new FileDataSource(file));
return dh;
}

public byte[] getImage(String fileName) {
//Logic of creating byte array
return byteArray;
}

Receiving binary data

public void  upload(DataHandler dh) {
//Logic of saving the file
}
or
public void upload(byte [] byteArray) {
//Logic of saving the file
}

It is also valid to have binary fields in JavaBeans as well and, Axis2 handle them correctly.

AXIOM Support

As we know, AXIOM is the native XML support provider in Axis2, therefore even in POJO deployment there is support for AXIOM. Hence, you can write a POJO with AXIOM either to send or receive. I.e. you can write your service class to either take an AXIOM OM element as the input parameter or the return type, as well as write AXIOM OM element object arrays. The following code sample illustrates how to write a service class using AXIOM classes.

public OMElement  echo(OMElement element) {
return element;
}

Or

public OMElement  echo(OMElement [] element) {
return element;
}

Serialization Support for List

In Axis2 POJO you can write a service class to return a java.util.List as the return type. However, you cannot have a List as a method parameter. The following is possible in Axis2 POJO deployment.

 public List getList(String list) {
return new ArrayList();
}

Inheritance Support

Axis2 has inheritance support for Beans. For example, our Address bean can extend from another bean. Then Axis2 will automatically generate the WSDL for that as well. Say we have a bean as follows.

package sample;

public class AddressParent {
private String city;
private int zipCode;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getZipCode() {
return zipCode;
}

public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
}

You can create the Address bean as follows.

package sample;

public class Address extends AddressParent {
private String street;
private String number;

[Rest of the code goes here]
}

So if we write a Service class like below then the generated WSDL will have what we discussed above.

public class MyService {
public Address getAddress(String name){
Address address = new Address();
// creating and other processing
return address;
}
}

 

How to exclude Bean properties?

 

There are instances where you may need to exclude some of the properties of a Bean. One solution is to use Java annotations to exclude them, and the second and easier approach is to use Bean configurations. If you have an old existing system, then it is very difficult to use annotations since the work load involved may be high. So the best option would be to use configuration parameters.

 

With the bean configuration parameter, you can exclude properties of the parent or child node. Let's say we need to exclude the property 'street' from the Address and 'zipcode' from the AddressParent. Then the configuration parameter will look as follows.

 

<parameter name="beanPropertyRules">
<bean class="sample.Address" excludeProperties="street" />
<bean class="sample.AddressParent" excludeProperties="zipcode" />
</parameter>

 

 So if we apply this change to our previous sample:

 

public class MyService {

public Address getAddress(String name){
Address address = new Address();
// creating and other processing
return address;
}
}

Then the generated WSDL will not have the street and zipcode properties.

So if you add this to services.xml and redeploy the service, you will not see any of those properties in the WSDL. Also, if you invoke the service, you will not get those properties in the serialize message.

 

If you want to exclude more than one property, then you can use a comma  ( , ) to separate them. For example, say we need to exclude both 'street' and 'number' properties from the Address. Then it can be done as follows.

 

<parameter name="beanPropertyRules">
<bean class="sample.Address" excludeProperties="street,number" />
<bean class="sample.AddressParent" excludeProperties="zipcode" />
</parameter>

 
Then the generated WSDL will not have the street,number and zipcode properties.

Support for Annotations

 

Axis2 POJO supports annotations. Therefor, you can use any kind of available options in JSR 181. Following is a simple example of a service written using annotations.

 

package sample;

import javax.jws.WebService;
import javax.jws.WebMethod;

@WebService (name = "MyService" ,serviceName="MyService")
public class SampleService extends ParentService {
@WebMethod (action = "action:add")
public int add(int a, int b) {
return a + b;
}
}

 

Summary

 

We discussed how to write POJO Web service for Axis2 in various ways. Now you can open up your favorite IDE or editor and start writing  Web services for Axis2 using what we discussed.

 

 

 

References/Resources

 

 

Author

 

Deepal Jayasinghe, Tech Lead, WSO2 Inc. deepal [-AT-] wso2.com

About Author

  • Deepal Jayasingha
  • WSO2 Inc.