RESTEasy can intercept JAX-RS invocations and route them through listener-like objects called interceptors. There are four interception points on the server side:
- wrapping around MessageBodyWriter invocations
- wrapping around MessageBodyReader invocations
- through pre-processors, which intercept the incoming request before unmarshalling occurs
- through post-processors, which are invoked immediately after the JAX-RS method finishes
In this article I will describe how to use RESTEasy interceptors to log incoming requests into a REST API.
I am currently using RESTEasy to expose HealthCare web services for consumption by mobiles applications, and there is a need to log transactions for auditing purpose, including for HIPAA compliance.
The first step is to specify in your web.xml file, that you are going to use a new interceptor - (e.g. named LogInterceptor):
<web-app>
...
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.acme.api.rest.service.LogInterceptor</param-value>
</context-param>
...
</web-app>
Then you create the corresponding java class for LogInterceptor:
package com.acme.api.rest.service;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.WebApplicationException;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import org.jboss.resteasy.spi.Failure;
...
@Provider
@ServerInterceptor
public class LogInterceptor implements PreProcessInterceptor {
// An handler to the Transaction log
private static final Logger translog = Logger.getLogger(JNDIMessageLoggingHandler.class);
// Getting the request as a context
@Context HttpServletRequest request;
@Override
public ServerResponse preProcess(HttpRequest arg0, ResourceMethod method) throws Failure, WebApplicationException {
final TransactionLogEntry transactionLogEntry = new TransactionLogEntry(Long.toString(Thread.currentThread().getId()),
System.currentTimeMillis(),
getClientIP(request),
request.getRequestURL().toString());
translog.info(transactionLogEntry);
}
}
In this example, the TransactionLogEntry constructor takes :
- a transaction ID
- a timestamp
- the client that initiated the request (e.g. request.getRemoteAddr()+":"+request.getRemotePort())
- the request URL
2 comments:
Thank you for the example. How would you log the body of a POST request?
Thanks - how could you extend this interceptor to also log execution time? Something along the lines of wrapping around a proceed() to capture start/end times.
Post a Comment