Skip to main content

Web services programming tips and tricks: How to create a simple JAX-RPC handler

Measure the time it takes to execute a request

Andre Tost, Senior Certified IT Specialist, IBM Software Group
Andre Tost works as a Solution Architect in the WebSphere Business Development group, where he helps IBM's Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible.
Russell Butek, Software Engineer, IBM Software Group
Russell Butek is one of the developers of IBM's WebSphere Web services engine. He is also IBM's representative on the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache's AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC 1.0. Previously, he was a developer of IBM's CORBA ORB and an IBM representative on a number of OMG task forces: the portable interceptor task force (of which he was chair), the core task force, and the interoperability task force. You can contact Russell at butek at us.ibm.com.

Summary:  When developing a Web service, typically you would not want to put Web service-specific code in the implementation. In many cases, you would take existing code and simply add another access layer to it, namely a way to invoke it via SOAP over HTTP. This means that the service implementation knows nothing about SOAP, it knows nothing even about XML, and it certainly doesn't matter that it is invoked from a client that sits in another process, on another machine, possibly on the other side of the world! While this is a well known advantage of Web services technology (that is, the possibility to invoke it across a network or the Internet), it also creates challenges. You may want to measure the response time of the server; you may have to encrypt a message before you can send it across the network; or you may want to charge a client for using your Web service each time it is invoked. Luckily, the JAX-RPC specification provides us with a feature that can help us do these things: handlers. Below, we will describe how you can build a simple handler that measures the time it takes to execute a particular request and log the result in a file.

Date:  04 Nov 2003
Level:  Introductory
Activity:  4322 views

JAX-RPC handler basics

JAX-RPC handlers allow you to intercept a SOAP message at various times during a service invocation. Handlers can exist on both the client and the server side. If you use JAX-RPC on the client side, you can have a handler process a SOAP request message right before it goes on the network, and you can process the response message before it is returned to the client. Similarly, you can intercept an incoming SOAP request message on the server before invoking the service implementation, as well as the outgoing response.

Several handlers can be combined into what is called a "handler chain". Each handler processes the SOAP message, which is then passed on to the next handler in the chain. The exact sequence in which this happens is configurable. We'll get back to this later.

To develop a JAX-RPC handler, you simply create a class that implements the javax.xml.rpc.handler.Handler interface. It has three methods to handle SOAP requests, responses and faults, respectively.

Handler lifecycle

Handlers are defined in the JAX-RPC specification. However, the "Enterprise Web Services" (JSR109) specification describes how they are used in a J2EE environment and adds some clarification to the way handlers are managed by the application server (see Resources for more information on this specification). In this article, we will assume that your Web service runs on a J2EE application server and hence we will follow the definitions of JSR109 as well as JAX-RPC.

Handlers are shared across multiple service invocations. In other words, they can store information that is only valid for a particular client or server instance. You can compare this to the way servlets are handled. When a new instance of a handler is created, its init() method is called. That allows you to set up things that you can use for multiple invocations. Before the handler is removed, the destroy() method is called, so that you can do cleanup in there. As a rule of thumb, however, you should avoid storing any state in a handler altogether.

Handler configuration

Handlers can be configured either programmatically or, in case you are running a J2EE application server, they are configured in the Web service deployment descriptor. Handlers and handler chains are defined on a per service basis. They can be defined in both the server and client side deployment descriptors. Listing 1 shows the deployment descriptor for our sample service, showing how a handler class called handler. PerformanceHandler is registered for the HelloWorld service:


Listing 1. Web service deployment descriptor with handler
   <webservices id="WebServices_1066491732483">
      <webservice-description id="WebServiceDescription_1066491732483">
         <webservice-description-name>HelloWorldService</webservice-description-name>
         <wsdl-file>WEB-INF/wsdl/HelloWorld.wsdl</wsdl-file>
         <jaxrpc-mapping-file>WEB-INF/HelloWorld_mapping.xml</jaxrpc-mapping-file>
         <port-component id="PortComponent_1066491732483">
            <port-component-name>HelloWorld</port-component-name>
            <wsdl-port id="WSDLPort_1066491732483">
               <namespaceURI>http://pack</namespaceURI>
               <localpart>HelloWorld</localpart>
            </wsdl-port>
            <service-endpoint-interface>pack.HelloWorld</service-endpoint-interface>
            <service-impl-bean id="ServiceImplBean_1066491732483">
               <servlet-link>pack_HelloWorld</servlet-link>
            </service-impl-bean>
            <handler id="Handler_1066493401322">
               <handler-name>handler.PerformanceHandler</handler-name>
               <handler-class>handler.PerformanceHandler</handler-class>
            </handler>
         </port-component>
      </webservice-description>
   </webservices>

Multiple handlers would be defined here to form a chain as mentioned above.

Storing state

If multiple handlers that are involved in one service invocation need to share information, they can do so by adding properties to the message context as it is passed from handler to handler. This message context will be available from the request to the response. In other words, we can use it to store information on an incoming request that we can reuse when the response comes back. We will get to this in our example later.


Example: A service performance handler

Now let's look at how you can create a handler that measures the response time of your service implementation. We will assume that you have created a HelloWorld web service, which simply returns a String message. Listing 2 shows the code for the service implementation bean (you can find an EAR file with all the sources, including a test client in the Resources section):


Listing 2. Web service implementation class
public class HelloWorld {
	
	public String helloWorld(String message) {
		return "Hello "+message;
	}
}

The handler will be configured for the server that hosts the Web service. It will be invoked on both the request and the response message, so that we can measure the elapsed time.

Initializing the handler

As mentioned earlier, each handler must implement the javax.xml.rpc.handler.Handler interface. Or, you can make your life a bit easier by simply inheriting the javac.xml.rpc.handler.GenericHandler class, which provides default implementations for all the methods. For storing performance results, we use a class called Logger, which we set up in the init() method. You can find the source for the Logger class in the Resources section. Moreover, the application server passes a javax.xml.rpc.handler.HandlerInfo object into this method, which we need to cache as well (see Listing 3):


Listing 3. Handler implementation -- init and destroy
public class PerformanceHandler extends GenericHandler {

	protected HandlerInfo info = null;
	protected Logger logger = null;

	public void init(HandlerInfo arg) {
		info = arg;
		logger = Logger.getLogger("c://temp//HelloWorldServiceLog");
	}
	
	public void destroy() {
		try {
			logger.close();
		} catch (Exception x) {}	
	}		

Note that we close the Logger object when the handler instance is destroyed.

Handling requests and responses

Each handler implements the handleRequest method, which is invoked when a request message arrives, as shown in Listing 4.


Listing 4. Handler implementation -- the handleRequest method
	public boolean handleRequest(MessageContext context) {
		try {
			Date startTime = new Date();
			context.setProperty("startTime", startTime);
		} catch (Exception x) {
			// insert error handling here
			x.printStackTrace();
		}
		return true;
	}

Here you can see that we store the current time in the message context as a property called "startTime". The application server will guarantee that the same message context object is passed into the handleResponse method, so that we can measure the elapsed time there, as shown in Listing 5.


Listing 5. Handler implementation -- the handleResponse method
	public boolean handleResponse(MessageContext context) {
		try {
			Date startTime = (Date)context.getProperty("startTime");
			Date endTime = new Date();
			long elapsedTime = endTime.getTime()-startTime.getTime();
			logger.write("Elapsed time is "+elapsedTime+"\n");
		} catch (Exception x) {
			// insert error handling here
			x.printStackTrace();
		}
		return true;
	}

Now you can deploy your service. Make sure you have configured the handler as shown in the deployment descriptor above, and you can measure how long it takes to execute a service request.


Summary

JAX-RPC defines a mechanism with which you can manage service invocations by intercepting request and response messages without having to change the actual service consumer or provider. In J2EE, you can configure handlers in a deployment descriptor, without writing any code, providing you with a powerful way of controlling SOAP messages as they pass through your system.



Download

NameSizeDownload method
ws-tipjax2SOAPHandler.ear HTTP

Information about download methods


Resources

About the authors

Andre Tost works as a Solution Architect in the WebSphere Business Development group, where he helps IBM's Strategic Alliance partners integrate their applications with WebSphere. His special focus is on Web services technology throughout the WebSphere product family. Before his current assignment, he spent ten years in various development and architecture roles in IBM software development, most recently for the WebSphere Business Components product. Originally from Germany, he now lives and works in Rochester, Minnesota. In his spare time, he likes to spend time with his family and play and watch soccer whenever possible.

Russell Butek is one of the developers of IBM's WebSphere Web services engine. He is also IBM's representative on the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache's AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC 1.0. Previously, he was a developer of IBM's CORBA ORB and an IBM representative on a number of OMG task forces: the portable interceptor task force (of which he was chair), the core task force, and the interoperability task force. You can contact Russell at butek at us.ibm.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=11857
ArticleTitle=Web services programming tips and tricks: How to create a simple JAX-RPC handler
publish-date=11042003
author1-email=
author1-email-cc=
author2-email=
author2-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers