Saturday, 31 March 2012

JavaEE Revisits Design Patterns: Aspects (Interceptor)

I have written some blogs on aspects years ago. AspectJ and Spring Aspects have served well for long years. However they may not be the first choice when it comes to JavaEE world. I have written several posts on how JavaEE implements several design patterns (singleton, dependency injection, factory, observer, asyncronous) and aspects is not an exception.

Interceptors are very easy to implement in JavaEE without any xml configuration. Lets go back to our example given in the previous posts and start with adding a new plain class. Since we already used logging as an example for the observer post, lets assume now we need to implement a security mechanism on our existing service.


package com.devchronicles.observer;


import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;


/**
 *
 * @author murat
 */
public class SecurityInterceptor {
    
    @AroundInvoke
    public Object doSecurityCheck(InvocationContext context) throws Exception{
        System.out.println(context.getMethod().getName());
        
        return context.proceed();
    }
}


As mentioned before the class is a plain java class and does not implement or extend any other class. Here the @AroundInvoke annotation does the magic. The methods marked with this annotation need to return an Object and get a InvocationContext parameter. InvocationContext gives access to method and parameter info and values as well as ability to change them. In this example we simply get the method name. Another important point is to call context.proceed() to continue execution process.

To put our interceptor in action we need to add an annotation to our target classes which is the EventService bean from the previous posts.


package com.devchronicles.observer;


import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.interceptor.Interceptors;


/**
 *
 * @author murat
 */
@Interceptors(SecurityInterceptor.class)
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class EventService {
    @Inject
    private String message;
    
    @Inject 
    Event<String> event;
    
    public void startService(){
        System.out.println("start service call "+message);
        event.fire("this is my "+message);
        System.out.println("done...");
    }
}

Don't worry about the grey and specially the lighter grey parts which comes from the previous posts. The @Interceptor annotation is the only code we need to add to make our existing class a target for our interceptor and there is no other configuration need to be done!


No comments:

Post a Comment