Sunday, July 25, 2010

JBoss: Trace interceptor

Now and then I enhance methods by some log-output like the following:
public void foo() {
logger.trace("--> foo");
try {
/* ... */
} finally {
logger.trace("<-- foo");
}
}
If you have multiple code-locations where you want to add trace-output like above you can do this a little bit easier by making use of interceptors (JBoss documentation).

First of all you may centralize both - the log-statements and the try-finally block - in one single class, let's call it the TraceInterceptor:
public class TraceInterceptor {
private static final Logger logger = Logger.getLogger(TraceInterceptor.class);

@AroundInvoke
public Object intercept(final InvocationContext ctx) throws Exception {
String logMsg = null;
if (logger.isTraceEnabled()) {
logMsg = ctx.getMethod().getDeclaringClass().getSimpleName()
+ "." + ctx.getMethod().getName();
logger.trace("--> " + logMsg);
}
try {
return ctx.proceed();
} finally {
if (logger.isTraceEnabled()) {
logger.trace("<-- " + logMsg);
}
}
}
}
Two things are important: The signature of the intercept-method must be exactly like this and it must be annotated with the @AroundInvoke annotation. When using this interceptor for a method foo of class Bar, the order is as follows:
  1. execute TraceInterceptor.intercept() and log "--> Bar.foo"
  2. ctx.proceed() passes on to the next interceptor or (if no other interceptor is registered) to the actual method being called
  3. after foo-method returns the finally block is executed and the interceptor logs "<-- Bar.foo"
So if we want the TraceInterceptor to intercept the method foo() of class Bar, we may annotate this at the foo() method:
public class Bar {
@Interceptors({ TraceInterceptor.class })
public void foo() {
/* ... */
}
}
Instead of annotating the method you may also place the annotation at class-level so every method would be intercepted. As you can see from the curly braces it is also possible to annotate more than only one interceptor.

No comments:

Post a Comment