Wednesday, July 05, 2006

EJB 3 Interceptors: Aspect orientation in EJB spec

EJB 3 Interceptors: Aspect orientation in EJB spec

By now most people in the java community have heard about Spring, Dependency Injection, Aspect oriented programming and other such terms

For those who have not, if i were to put this in a single line it would say "An aspect is a common function that can be used across an application".

Examples of this would be things like Security, Auditing, Transactions, Logging, etc..

It is definitely useful to abstract out common aspects of an application in order that you do not have to write the same code in many places.

The Spring container is very popular in the java community as of now for this particular reason. Also the Spring container externalizes the configuration of the dependency injected aspect objects so that the behaviour, as well as implementations of the aspect objects, can be varied as needed without much code change.

EJB 2 also did some of this with regards to EJB Transactions, EJB Reference, Connection pools, etc.

However With EJB 3 and Annotations a new term has been added. It is called "EJB Interceptors". They apply only on session and message driven beans.

EJB3 Interceptors can act on a bean level like lifecycle callback interceptors or on a specific method level or on all methods or on certain number of methods. Also there could be multiple interceptors that also could have exclusion rules for certain methods.

We will try and see this in a bit more detail.

What are lifecycle callback interceptors?

EJB2 had an EJB Lifecycle for each of the EJB types i.e. Stateless Session bean, StateFull Session Bean, Entity Bean and MDBs. They are described in detail here: -

http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/EJBConcepts9.html

The particular lifecycle state can be "Does Not exist", "Pooled", "Ready". Between these states there are methods that the container calls on the EJB such as create,
setSessionContext, ejbCreate etc..

Now In EJB3 since we have EJB's we also have EJB lifecycles and related methods. However for us to be bale to do anything at the time of a lifecycle method invocation we have to define it as a lifecycle call-back interceptor method.

For example: -

Session beans have the following interceptor methods

• PostConstruct
• PreDestroy
• PostActivate
• PrePassivate

So we could have a session bean like this

@Stateless public class BusinessServiceBean implements BusinessService {

public void doService(){...};
...

@PostActivate
initializeDB() {...};

}


What is a method interceptor?

Business method Interceptor for all methods

(-- this is from the EJB spec
Business method interceptor methods are denoted by the AroundInvoke annotation. Only one AroundInvoke method may be present on the bean class or on any given interceptor class. An
AroundInvoke method must not be a business method.

The business method invocation is intercepted by the AroundInvoke methods of the bean class and interceptor classes. AroundInvoke methods must always call InvocationContext.proceed() or neither the business method will be invoked nor any subsequent interceptor AroundInvoke methods.

InvocationContext

The InvocationContext object provides the metadata that is required for interceptor methods:

public interface InvocationContext {

public Object getBean();
public Method getMethod();
public Object[] getParameters();
public void setParameters(Object[]);
public java.util.Map getContextData();
public Object proceed() throws Exception;

}

--)

Now how do we use this?

Here is a sample code that uses a Business method Interceptor

@Stateless public class BusinessServiceBean implements BusinessService {

public void doService(){...};
...

@PostActivate
initializeDB() {...};

@AroundInvoke
doChecks() {
checkDBAccess;
checkSecurity;
.....
};

}

This would mean that when a user calls doService the call is intercepted and doChecks method is called first instead.

Business method Interceptor for specific methods

A business method interceptor method may be defined to apply to a specific business method invocation, rather than to all of the business methods of the bean class.

This is done by using interceptor annotations.


@Stateless public class BusinessServiceBean implements BusinessService {

@Interceptors(test.TestInterceptor.class)
public void doService(){...};
...

@PostActivate
initializeDB() {...};

@AroundInvoke
doChecks() {
checkDBAccess;
checkSecurity;
.....
};

}

As i understand, there can be more than one method level interceptor. If that is the case the interceptors are invoked in the order they are specified. Also method level interceptors are invoked in addition to any other interceptors defined at the bean level.

I need to get to an EJB 3 implementation to test out a few permutations and combinations of the above code.

To conclude, EJB3 now looks more and more like other popular java frameworks, for aspect oriented programming, like Spring. Also EJB 3 persistence now looks like OR tools namely Toplink, Hibernate, etc.