We need to monitor access (from where, who, etc.) to our web services, trace incoming and outgoing message contents for auditing purposes. It is better to separate this task from web services themselves and let the web service infrastructure, which is Axis in our case, handle this operation.
In Axis, it is possible to develop custom Handler objects and register them to service requests and responses so that
we can easily extract necessary information from message requests and get SOAP message body to collect necessary auditing
data. Axis provides org.apache.axis.Handler interface and a BasicHandler abstract class as a convenience class for
custom Handler classes.
public class LogHandler extends BasicHandler {
public void invoke(MessageContext messageContext) throws AxisFault {
}
}
The invoke method is called whenever a request comes in and a response goes out from the web service for which a custom
Handler is configured. In our case, we use HTTP transport mechanism to expose our web services using Servlets; therefore,
we expect to get HTTP requests. The question here is how to access HttpServletRequest within those Handler objects.
Axis puts the current request object into messageContext as a property (transport.http.servletRequest) and you can
access any available property by just calling messageContext.getProperty(name) method.
public class LogHandler extends BasicHandler {
public void invoke(MessageContext messageContext) throws AxisFault {
HttpServletRequest request = (HttpServletRequest) messageContext.getProperty("transport.http.servletRequest");
//...
}
}
We also want to log SOAP message requests and responses. As our LogHandler object is called for both requests and
responses, we need a way to understand whether it is called at request time or at response time. Axis has a “pivot point”
concept. Basically, it is the point at which a request is processed and a response is produced, or a new request is sent
and a response is received. Web service providers such as RPCProvider and MsgProvider types are pivot points for all
RPC services and messaging services respectively. MessageContext class provides an API to check if the current request
has passed a pivot point, that is, it is processed and a response is produced, or not.
public class LogHandler extends BasicHandler {
public void invoke(MessageContext messageContext) throws AxisFault {
if (!messageContext.getPastPivot()) {
//get message request from context and do related task...
} else {
//get message response from context and do related task...
}
}
}
Another point in our LogHandler is to log exceptions occurred during web service request handling. The invoke method
is not called for SOAP faults. There is an onFault() method which is for this purpose. It is already implemented in
BasicHandler; therefore, you need to override it in your Handler class and perform your specific task when a SOAP
fault occurs.
public void onFault(MessageContext messageContext) {
//get message response from context and do related task...
}
Axis architecture is all about processing messages, and during that processing, a series of Handler objects can be
invoked to intercept that message processing. You can easily create a chain of message Handlers as well.