http://www.developer.com/

Back to article

How to Write Axis2 Web Service Clients for the Cloud


May 13, 2009

Introduction

Cloud computing has become a buzz word in the IT field, and people are developing application for the Clouds. One of the cool features we can find with Cloud apps like Amazon is that they support the Web service API to configure, run and monitor the instances in the Cloud. Due to various reasons Amazon EC2 has become one of the most commonly use commercial Clouds, so today we are going to discuss how to write a Web service client for Cloud apps like Amazon, Writing a client for other Cloud apps would be much the same. Since most of them will have the same set of API as well as security requirements.

Axis2 can be used both as a server and a client to invoke services. In previous articles we have discussed a number of different accepts of Axis2 on the server side. One of the other most important sides of Axis2 is how to use Axis2 as a client to invoke other Web services. When writing to a client using Axis2 there are two main approaches, the first approach is to write the client by hand, the second is to use tools to generate the client stub to invoke the remote service.

Hand written client vs generated client

In the first approach, we have to write the code for all the processing, which includes, serialization and de-serialization message, invoking the services and etc.., put simply there are a number of steps we have to perform to invoke the service. However the most important thing is that we can write the most efficient code when we write the client by hand, since we can optimize the code for our particular use case.

On the other hand, in the second approach what we do is use the Axis2 tool to generate the client side stub to invoke the service. With that approach we do not need to worry about the message serialization and de-serialization, setting up the system or invoking the service. Generated code handles all that for us. So the code generation approach is more convenient and time saving, especially to minimize the number of errors.

In this article we are going to discuss how to use the Axis2 code generation tool to generate client side code and then how to set up that code to invoke a remote service. In particular we are going to write an Axis2 client to invoke Amazon EC2 cloud APIs.

Setting up Axis2

The first step of creating the Axis2 client stub for a remote service is setting up the Axis2 client side, for that we need to download Axis2 binary distribution. We can download Axis2 binary distribution from the Axis2 official web site. Download that and then extract the downloaded zip file. Now we are ready to generate the stub for the Amazon EC2 Web service API. We can find the EC2 WSDL from following URL, http://ec2.amazonaws.com/doc/2009-03-01/AmazonEC2.wsdl.

If you are new to WSDL then you will find it somewhat hard to understand the WSDL, the nice thing is that you do not need to understand the WSDL to generate the Axis2 client. That is one of the cool feature of code generation; it reduces the complexity. The tool can process the WSDL and generate the code for us. Now let's generate client stub for the EC2 WSDL.

First go to the "bin" directory of the extracted Axis2 distribution, there you can find a number of shell scripts and Windows batch files. So depending on the OS platform you have to use either shell scripts or batch files. When we generate the code we can pass a number of options to the code generation tool, however in this particular case we are not going to discuss all of them. Run the following command to generate the code,

In Linux:

  ./wsdl2java.sh -uri http://ec2.amazonaws.com/doc/2009-03-01/AmazonEC2.wsdl  -o out 

In Windows:

  wsdl2java.bat -uri http://ec2.amazonaws.com/doc/2009-03-01/AmazonEC2.wsdl  -o out 

Then it will create a directory called "out" inside the bin directory and create the code inside that. If you browse you will able to see a large file. DO NOT try to open that or read through it, it is so complex to read, and there is no reason to read or edit that file. That single class has all the serialization and de-serialization code as well as the service invocation code.

Next we are going to use some other code generation parameters and generate code in a different manner. The idea is to generate data binding (serialization and de-serialization) code into septate classes. Next run the following command. Notice the difference?

In Linux:

  ./wsdl2java.sh -uri http://ec2.amazonaws.com/doc/2009-03-01/AmazonEC2.wsdl  -o out_unpack -u

In Windows:

  wsdl2java.bat -uri http://ec2.amazonaws.com/doc/2009-03-01/AmazonEC2.wsdl  -o out_ unpack  -u

What are those options?

Now we are going to discuss some of the options we use when we generate the code,

  • -uri :- as the name implies the "uri" option is to specify the location of the WSDL document, it can either be a remote URL or path to a local file.
  • -o :- This parameter is used to specify the output location of the code, so that the Axis2 tools generates the code into it.
  • -u :- The idea of "u" option is to unpack the code, it will generate the data binding code and service invocation code into separate classes.

Now we have generated the client side stub for our Amazon EC2. Our next step is to write the code to use the stub. In fact there is not such a big difference from writing a client to the other Web service and EC2, so if you know how to use a stub then it will be easy for you to use the generated stub to do the work you want.

Invoking the stub

As we discussed before there is no difference using the previously generated stub for EC2 and a normal stub with one exception. The exception being, in the case of Amazon EC2 we have to use security so we need to setup security requirement for EC2. Basically we need to configure the public key and the certificate. In addition to that due to some of the missing features in Axis2 security implementation we need to write some additional code. But we are not going to discuss that here since it will complicate the article, you can find the required library in the resource section. Download that and add it into the classpath, then you can use those utilities for the client.

Writing the security handler

As we discussed before to use Amazon EC2 we need to use the WS- Security, to use WS-Security in Axis2 we need to write a special handler to provide and handle the user-name and password. And writing that is so simple, we just need use the following code as the security handler:
  import org.apache.ws.security.WSPasswordCallback;
  
  import javax.security.auth.callback.Callback;
  import javax.security.auth.callback.UnsupportedCallbackException;
  import javax.security.auth.callback.CallbackHandler;
  import java.io.IOException;
  
  public class SecurityHandler implements CallbackHandler {
      public static String password;
  
          public void handle(Callback[] callbacks) throws IOException,
                  UnsupportedCallbackException {
              for (Callback callback : callbacks) {
                  WSPasswordCallback pwcb = (WSPasswordCallback) callback;
                  pwcb.setPassword(password);
              }
          }
  
  }

Having written the security handler and other security related code we are now ready to write the code to invoke the stub.

Setting up the public key and certificate

The next step of writing the client is setting up the public key and the certificate, for that you first need to have an EC2 account. If you do not have one, create an account and then use the EC2 tools to generate the public key and the certificate. For more information about creating those two keys refer to the resource section.

Writing the client

As we have a number of times to use Amazon EC2 we need to use WS-Security so we need to setup the required security for the client. One of the key requirements of that is to add the required modules into the classpath. In this case we need to have Axis2 security module in the classpath, otherwise the code we are going to write will not work. So download the Axis2 security module (Apache Rampart) and put that into classpath.

There are a number of ways of creating the instance of Stub, and that does not have a direct impact on the invocation. So here we are going to create the instance of Stub inside the constructor of the client as follow:

  ConfigurationContext configCtx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
  
  Create an instance of the stub.
  
              stub = new AmazonEC2Stub(configCtx);

We first create a configuration context, for the most part we do not need that. However there are situations where we need to create ConfigurationContext using the custom Axis2 configuration file and our own repository, in those cases we need this step.

Next we need to initialize some of the required parameters, like populate key stores and configure security handler. You can find the required code for those below. As we discussed previously we are going to use the attached utils.jar for this because that particular library file has all the required methods and classes we are going to use.

ec2PrivateKey = EC2Utils.pem2der(ec2PrivateKey);
ec2Cert = EC2Utils.pem2der(ec2Cert);
File jks = new File(EC2_JKS);
if (jks.exists()) {
     jks.delete();
}
SecurityHandler.password = EC2_KS_PASSWORD;
EC2Utils.doImport(EC2_JKS, ec2PrivateKey, ec2Cert, EC2_USER, EC2_KS_PASSWORD);

Now we have done everything we need to setup the client, and we are ready to write the code to invoke the Amazon EC2. We are going to discuss only one of the methods (RunInstances) in the stub, we can use the same procedure for all the other methods once we understand how to use the one method.

Amazon has different kinds of instance types, so we have to write the code to cope with that. The following few lines does that.

if (instanceType == null) {
    instanceType = InstanceType.SMALL;
}

To start an instance in EC2, we need to pass the required request parameters. The following code segment handles that. The code is so simple and we do not need to discuss them one by one.

          RunInstances req = new RunInstances();
          RunInstancesType params = new RunInstancesType();
          params.setInstanceType(instanceType.getType());
          params.setImageId(amiID);
          params.setKeyName(keyName);
          params.setMaxCount(numberOfInstances);
          params.setMinCount(numberOfInstances);
  
          if (groupName == null) {
              groupName = "default";
          }
          GroupSetType gst = new GroupSetType();
          GroupItemType git = new GroupItemType();
          git.setGroupId(groupName);
          gst.setItem(new GroupItemType[]{git});
          params.setGroupSet(gst);
  
          req.setRunInstances(params);

We need to configure the security parameters for each invocation, so the following code will do that for us. This means setting up the correct security policy for the method.

          enableSecurity("RunInstances");
    

Now we have all we need, so let's call the Service. We'll use the following code to invoke the service.

          RunInstancesResponse respone = stub.RunInstances(req);

Now its time to process the response.

RunInstancesResponseType resType = respone.getRunInstancesResponse();
RunningInstancesSetType instances = resType.getInstancesSet();
RunningInstancesItemType[] items = instances.getItem();
ArrayList instanceIds = new ArrayList();
for (int i = 0; i < items.length; i++) {
    RunningInstancesItemType item = items[i];
    instanceIds.add(item.getInstanceId());
    System.out.println("InstanceID " + item.getInstanceId());
}

You can find the complete client for invoking RunInstances in the resource section. Once you run this code it will start an EC2 instance for you. As we discussed before, we need to create the Amazon EC2 account, then the key files as well as the Amazon Machine Image. If we do not have them then it would be hard to follow this document. However the concept will remain the same, so if you want to invoke some other service you can follow the same steps.

To run the client, you need to pass the location of the public key, location of the certificate and name of the AMI. You can find a sample client in the resource section, edit and run it.

Summary

In this article we discussed how to use Axis2 tools to generate client side code, and then we discussed how to use the generated client to invoke a service. Since the Amazon EC2 has become one of the most commonly used Cloud APIs, we use Amazon EC2 WSDL to generate and invoke the service. In addition to that we discussed some of the client side security of Axis2 and how to use it. Now, you can complete the client to use the rest of the methods in the stub.

Resources

  1. utils.jar
  2. AWSClient.java
  3. SecurityHandler.java
  4. Amazon Elastic Compute Cloud

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date