WSO2 Tungsten as a Client

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
  • 30 May, 2006

Introduction

WSO2 Tungsten is a Web services platform which is built around Apache Axis2. As a result of Tungsten inherits all the Axis2 features. The advantage of Tungsten over Axis2 is that Tungsten has integrated all Axis2 related components in a manner in which that any user even with limited knowledge on Web services can easily deploy, invoke services and administer the system. Tungsten highlights all the key features in Axis2 and integrates modules, transports, databases etc in a seamless fashion. One of the key points in Tungsten is that the system administration is completely based on Web service invocations from an AJAX based Web UI.

Tungsten as a Server

As mentioned above WSO2 Tungsten is designed to run as a server. From Axis2 point of view Tungsten is just another transport receiver like SimpleHTTPServer or AxisServlet. So then what is the advantage of running Tungsten as a server? For one thing, SimpleHTTPServer cannot be used in a production environment, but Axis2 war or servlet distribution can be used in production environment. Tungsten is a standalone distribution is based on Jetty and have been tested on various platforms including different JDK versions. Hence Tungsten is a good candidate for deployment in a production environment.

Tungsten as a client

There are a number of instances where a service running inside an application server requires to send a request to some other service, or needs to invoke some other service hosted in the same application server (or any other location). The above scenario can be considered a client running inside Server. One of the most interesting Use Cases is WS-eventing and WS-notification, in which whenever an event occurrs, it is required to notify the clients or the subscribers. Why is this case so special? Is it not just simply invoking a service? Think about a scenario where you need addressing support for your invocation. In order to have addressing support you need either an addressing module in the repository or in the classpath. As a service author one cannot assume that that a repository has been configured since one has no control over it. To illustrate the problem much clearly let's look at the following service implementation class.

public class Trader { 
public String getQuote(String symbol) throws AxisFault {
// First it is required to call Stock service and get the Symbol and then
// get the quote from that.
OMElement symbolElement = creatOMElementforSymbol(symbol);
ConfigurationContext configCtx =
ConfigurationContextFactory.createConfigurationContextFromFileSystem("/path/to/my/repo",
"axis2.xml");
ServiceClient serviceClient = new ServiceClient(configCtx,null);
Options options = new Options(); //setting up the options for transports
serviceClient.setOptions(options); OMElement response =
serviceClient.sendReceive(symbolElement); // extract quote from response
return processResponse(response);
}
}

Above code looks simple, but the problem comes to play when you're creating configuration context based on the file system. How do you know the repository to create the configuration context? You may know that only if you assume that the service you are implementing is only for this particular application server. The problem can be easily solved if the service can get access to server's configuration context. One can create a service client using server's configuration context. If the server has an addressing module or rather any QoS (Quality of Service), then modules client will automatically get them as well. A Service can get access to server's configuration context by adding “setOperationContext” method to a service implementation class, in which case, first, you have to get a reference to configuration context and then inside the actual method invocation in which you have to use it in. This can be done, but involves a bit of work. Won't it be awsome if we can do this without having to do any of the above. Apache Axis2 gives a solution to above problem by using a so called Listener Manager. Setting up a listener manager does not take place automatically in Axis2. Listener Manager is a component which manages one or more transports in a given system and all the transports running inside, share the same configuration context (See References for more information on Apache Axis2 Transports). WSO2 Tungsten uses Listener Manager in both standalone and war distributions. In both cases, two transport listeners are used, one to handle http and another for https. Listener Manager has a static field to keep a reference to configuration context. It should be noted here that Axis2 automatically does not set the reference. It needs to be done manually. As mentioned above, WSO2 Tungsten sets up Listener Managers and sets the static field as the configuration context that it creates. So once Tungsten starts up Listener Manger does not have a null field for

ListenerManager.defaultConfigurationContext

Relationship between Listener Manager and Service Client

Service client has three constructors - defualt constructor, configurator which takes configurationContext as an argument and finally, the dynamic client. In any of the constructors if you pass null argument as a configuration context or if you simply use its default constructor, service client is implemented in a manner in which it first checks Listener Manager for its defaultConfigurationContext static variable. If it is not null, then sets Listener Manager's static variable as configuration context in the service client. Thus all the invocations carried out using that service, automatically gets access to server's run time and its configuration data. As mentioned above, if addressing is engaged globally then that is automatically applied to service client as well. Note: If the service running inside Tungsten creates a service client using its default constructor or passes configuration context as null, service client will get access to Tungsten server's configuration context.

Advantages

There are a number of advantages of sharing server's configuration context inside a service client. Getting access to server modules and parameters are a few of them. In addition to that one of the most important factors is the ability of using server specific transports as service client transports. To get a clear understanding of this let's consider the following use case:

  • Assume that someone wants to invoke a service using two channel in an asynchronous manner
  • And further assume that he creates a configuration context using axis2_default.xml

The code would look like below:

Options options = new Options(); 
options.setTo(targetEPR);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
options.setUseSeparateListener(true);
options.setAction(operationName.getLocalPart());
sender = new ServiceClient(configcontext, null);
sender.setOptions(options);
sender.sendReceiveNonBlocking(payload, callback);

Logic inside service client to handle the above code snippet can be listed as follows:

  • Once it sees the useSeparateListener flag as true,
  • Try to find the transport receiver specified by transportIn protocol, or by using target endpoint reference (targetEPR)
  • Check whether the transport receiver is running, if not it will start the listener (if you use default axis2.xml it will start up SimpleHTTPServer in port 6060)
  • And then ask replyTo address from that transport
  • Create message context
  • Add and set the content
  • Invoke the service

Disadvantages

There are few disadvantages in sharing the server's configuration context. One of the main concerns is adding unnecessary services into the server. This happen if you use default constructor of service client, whenever you call the default constructor it creates an anonymous service and adds that to configuration context. So if you keep on creating service clients with its default constructor there will be a considerable amount of anonymous services. There are few solutions to address above problem

  • Service client has the finalize method overridden to remove the service corresponding to it. Thus when service client goes out of the scope or when garbage collection happens, the service will be removed
  • You can call service clients cleanup method, and there it will remove corresponding service from the system
  • You can use only one service client instance rather than creating one per invocation

The second problem is that all the global level settings automatically applies to the service client, so if someone engages a particular module, then whether you want it or not it will be available in the execution chain.

Summary

A service hosted in Apache Axis2, and running inside an application server, cannot always create a configuration context as it wishes since it doesn't have enough data to do so. So the best solution is to use the currect Axis2 instance's configuration context. In WSO2 Tungsten any service can access server's runtime environment. Most common use case is to create a service client to invoke other services running outside the current container. To reduce the number of service instances running in the server, as a best practice, remember to call cleanup method in the service client instance that you have created.

References

The Axis2 Transport Framework

Author

Deepal Jayasinghe, Senior Software Engineer, WSO2 Inc. deepal at wso2 dot com

About Author

  • Deepal Jayasingha
  • WSO2 Inc.