2010/06/15
15 Jun, 2010

Working with RPCServiceClient

  • Deepal Jayasingha
  • - WSO2

Introduction

Apache Axis2 has a number of different ways to make a Web service call, one can use WSDL file and Axis2 tools to generate the client stub and then make the Web service call. One can use ServiceClient and then populate it with required data and make the call, or one can use OperationClient and gain more access and invoke the service. One can use RPCServiceClient and invoke the service as he invoke a local method call, without knowing anything about Apache Axiom.

When we use ServiceClient or OperationClient we always need to have better understanding on Axiom API and how to use them, because to invoke a Web service using ServiceClient we need to pass Axiom element as the payload. In addition, it will return Axiom element as the response, so we need to be able to populate and process Axiom, otherwise it is hard to invoke a service using one of the above client. However when we use code generation we do not need to think about any of the Axiom details, because generated code handles everything for us.

What is RPCServiceClient ?

RPCServiceClient is a convenient API built on ServiceClient, the whole idea is to provide an easy API to invoke a Web service without having any understanding on Axiom. As we will see soon, we pass Java objects and get the response as Java objects, so it is just a matter of working with Java objects to invoke a Web service.

Note: One of the restriction with RPCServiceClient is that we need to have exactly the same Java classes as in the service. In other worlds we need to have service related Java libraries in the client side to do the Web service call. The main reason is Axis2 has to do the correct serialization or the de-serialization . However if the Web service only uses simple types (such as int, string, boolean etc.. ), then we do not need to have the service code.

Having discussed that, now we are ready to discuss how to use RPCServiceClient to make the Web service call.

Creating RPCServiceClient

As same as in ServiceClient there are a number of ways we can create RPCServiceClient, in fact RPCServiceClient extends ServiceClient so it has all the constructors. In addition to that RPCServiceClient can be used to use any of the methods in the ServiceClient too.

RPCServiceClient client = new RPCServiceClient();

Here we create a client using its default constructor, it will use the default configuration context as it has access to all the modules in the classpath. If we want to use our own configuration context then we can use the following constructor.


ConfigurationContext  clientCtx = getConfigurationContext();
RPCServiceClient client = new RPCServiceClient(clientCtx, null);

Sample Service

To continue the article in more easy manner, let's create a Web service and deploy that. However I am not going to discuss how to deploy a Web service here, for that refer to Axis2 deployment. You can find the sample Web service class below;


public class SampleService {
    public MyBean echoBean(MyBean bean) {
        return bean;
    }
  
     public int add(int a, int b) {
        return a + b;
    }
}

public class MyBean {
    private String name;
    private int age;
    private boolean value;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isValue() {
        return value;
    }

    public void setValue(boolean value) {
        this.value = value;
    }
}

So, the service class has two methods, one is handling Java simple types and other one handling a Bean. You can use the above classes to create and deploy a service in Axis2. Once you do that, we are ready to do to next section.

Invoke the "add" method

First step of invoking the service is to create the RPCServiceClient and configure that with options object. Following code segment does that.


Options opts = new Options();
opts.setTo(new EndpointReference(“https://localhost:8080/axis2/services/SampleService”));
opts.setAction(“urn:add”);
RPCServiceClient client = new RPCServiceClient();
client.setOptions(opts);

Now we have the configured RPCServiceClient, next let's create the request parameter to call the service.


ArrayList args = new ArrayList();
args.add("100");
args.add("200");

This is just one way of creating the request parameters, what you need to do is to create an object array containing the parameters. As you can see the above “add” method takes two arguments, so we have two objects in the array to represent them.

Now let's call the service,

OMElement response = sender.invokeBlocking(new QName("https://ws.axis2.apache.org", "add", "req"), args.toArray());

As you can see the return type is OMElement, but what we need is to have an int as the return type. Now let's do that. Since we know the return type is int, we can populate the return object array with the corresponding return types.


Object[] res  = sender.invokeBlocking(new QName("https://ws.axis2.apache.org", "add", "req"), args.toArray(), new Class[]{Integer.class});
System.out.println(res[0]);

So, it is so easy to make a Web service call from RPCServiceClient, we just need to create the request parameters and response parameters. And the call the service, then Axis2 will do the correct serialization and de-serialization and invoke the service as well as give us the response. Important thing is we do not need to worry about any of the XML manipulation in Axis2.

Invoking “echoBean” method

Previously we invoked a simple method which only has simple Java types, now its time to see how we can use RPCServiceClient to make a service call which has complex type. As same as “add” method we can create an instance of RPCServiceClient as follows;


Options opts = new Options();
opts.setTo(new EndpointReference(“https://localhost:8080/axis2/services/SampleService”));
opts.setAction(“urn:echoBean”);
RPCServiceClient client = new RPCServiceClient();
client.setOptions(opts);

Now we can populate the request parameters as follows;


MyBean bean = new MyBean();
bean.setAge(30);
bean.setName("Deepal");
bean.setValue(false);

ArrayList args = new ArrayList();
args.add(bean);

Now we can call the service as follows,


OMElement response = sender.invokeBlocking(new QName("https://ws.axis2.apache.org", "echoBean", "req"), args.toArray());
MyBean resBean = (MyBean)BeanUtil.deserialize(MyBean.class, response.getFirstElement(),
                                                      new DefaultObjectSupplier(), null);

As you can see we use some what different approach to create the response, the other way is to get the correct response is to pass the return types array when we call the service, we can do that as follows;


Object[] res  = sender.invokeBlocking(new QName("https://ws.axis2.apache.org", "echoBean", "req"), args.toArray(), new Class[]{MyBean .class});

The first element of the array represents the response which is an instance of MyBean.

Summary

In the article we discussed how to use RPCServiceClient, we went though few samples to demonstrate how to use the client. We discussed a number of different ways to process the response as well, one way is to get the response as Omelement, other way is to get the response directly into corresponding Java type.

Author: Deepal Jayasinghe

Software Engineer

WSO2 Inc.

 

About Author

  • Deepal Jayasingha
  • WSO2 Inc.