Thought I’d give EJB3 interceptors a shot today. Only class level and method level interceptors are allowed. No rich AspectJ (or jboss-aop) style support. No rich pointcut language. Spring 2.0 is much better in this regards. But like I said before, for most applications what EJB3provides is more than enough. Even Spring prior to 2.0 had only limited AOP support (Method level).
First let me show you the stateless session bean with the interceptors configured.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.aver.service.timer; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.ejb.Stateless; import javax.interceptor.ExcludeClassInterceptors; import javax.interceptor.Interceptors; @Stateless @Interceptors(PerformanceInterceptor.class) public class TimeServiceBean implements TimeService { public String getTime() { SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); return "EJB3-SSB-" + formatter.format(Calendar.getInstance().getTime()); } @ExcludeClassInterceptors public String getTime2() { SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); return "EJB3-SSB-" + formatter.format(Calendar.getInstance().getTime()); } } |
- The @Interceptorsannotation at the class level tells the container to apply the specified interceptor (or a list of comma separated interceptors) to all the methods in the class…except in my case for the getTime2 method which explicitly requested that all class level interceptors must be excluded during its execution (using annotation @ExcludeClassInterceptors).
- The @Interceptorsannotation can be applied at either the class level or the method level.
I am yet to find a useful use of @ExcludeClassInterceptorsor its close brother @ExcludeDefaultInterceptors.@ExcludeDefaultInterceptors will as indicated exclude any default interceptors (which can only be applied via the XML configuration file).
I for one prefer the interceptors being configured outside of the bean itself. Typically the functionality in interceptors are cross cutting concerns and they should not be meddled with by individual beans. You don’t want one developer excluding all interceptors and thereby conveniently skipping some security related interceptor in your application. Anyway the feature is there so we will all find a good use for this .
Now here is the interceptor implementation in PerformanceInterceptor.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.aver.service.timer; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; public class PerformanceInterceptor { @AroundInvoke public Object measureTime(InvocationContext ctx) throws Exception { long startTime = 0; try { startTime = System.currentTimeMillis(); return ctx.proceed(); } finally { System.out.println(ctx.getTarget().getClass().getName() + "->" + ctx.getMethod() + " executed in " + (System.currentTimeMillis() - startTime) + "ms"); } } } |
This should be fairly obvious. You apply the @AroundInvoke to the interceptor method to indicate that the method is the interceptor itself. Not sure if that is clean English there. You need the method signature exactly as I indicated above. Of course the method name can be different.
This is it … now when the application executes this interceptor is applied for TimeService.getTime method only.
What I do not like about this is the use of @AroundInvoke annotaton. Iprefer that the interceptor class implement an interface similar to the AOP alliance org.aopalliance.intercept.MethodInterceptor. I personally think the annotation above is not clean. But thats me…others may love it.
Lastly there is another way to implement the interceptor. In the implementation above I had defined the interceptor externally in the class PerformanceInterceptor.java. You can if you want directly implement the @AroundInvoke method in the bean class itself. I just do not like that. I feel what you put in interceptors are cross cutting features and cross cutting features are best left in their own class.Again that’s me…others may love it. Anyone have an opinion either way do let me know.