Skip to main content

Interceptors with EJB 3

Posted by meeraj on January 25, 2006 at 4:15 AM PST

I have been having a look at EJB 3.0 interceptors with Glassfish. EJB 3.0 allows you to define interceptor methods that are called around the business methods and lifecycle events on the bean instances. The interceptor methods can either be defined within the bean class or in separate interceptor classes. Interceptor definitions and binding interceptors to bean classes or specific methods within the beans can be done either using annotations or within the deployment descriptors. Here, I will try to provide a simple example of using interceptors on business methods using annotations.

Methods that intercept invocations to business methods or lifecycle events can be defined either in the bean class or in separator interceptor classes. Only one interceptor method is allowed per class. The interceptor methods should be annotated with the @AroundInvoke annotation and should have the signature,
Object <methodName>(javax.ejb.InvocationContext). If the bean class has a method with the above signature and annotation, the method will be used to interpose on all the business method invocations on that bean. Additionally, you can define interceptors for all the business methods on the bean or individual business methods using the @Interceptors annotation. The value of this annotation is the list of interceptor classes. The interceptor classes are required to have a single interceptor method with the same signature and annotation as explained earlier. Interceptor classes have the same lifecycle as the associated bean instance and can have dependency injection, which will be done using the same naming context as the bean.

InvocationContext

InvocationContext allows you to propagate state across a chain of interceptors. In addition it allows to get/set method parameters, get a reference to the bean, get the invoked method name etc. The methods provided by InvocationContext interface are,

  • Object getBean(): Returns a reference to the bean.
  • Method getMethod(): Returns a reference to the invoked method.
  • Object[] getParameters(): Returns the parameters passed to the method.
  • void¬† setParameters(Object[] parameters) : Sets the parameters.
  • Map getContextData(): Get contextual data that can be shared in a chain.
  • Object proceed(): Proceed to the next interceptor in the chain or the business method if it is the last interceptor.
  • Order of Interception

    The interceptors are invoked in the order in which they are declared in the annotation. Bean level interceptors using interceptor classes are invoked before method level interceptors using interceptor classes. Interceptor method defined in the bean class itself is invoked at the end. If the bean or the interceptor classes have super classes with interceptor methods, they are invoked before the interceptor methods on the sub-classes are called.

    Example

    Now we will have a look at a simple example for doing interception on an EJB's business method.

    Bean Class

    package com.acme.ejb;

    import javax.ejb.AroundInvoke;
    import javax.ejb.Interceptors;
    import javax.ejb.InvocationContext;
    import javax.ejb.Stateless;
    import javax.jws.WebMethod;
    import javax.jws.WebService;

    @Stateless
    @WebService
    @Interceptors( { Interceptor2.class })
    public class HelloWorldBean {

    @Interceptors( { Interceptor1.class })
    @WebMethod
    public String sayHello() {
    return "Hello";
    }

    @WebMethod
    public String sayHi() {
    return "Hi";
    }

    @AroundInvoke
    public Object log(InvocationContext invocationContext) throws Exception {
    System.err.println(invocationContext.getMethod().getName() + " called from interceptor 3");
    return invocationContext.proceed();
    }

    }

    The bean class has an AroundInvoke method, a bean level interceptor and a method level interceptor. A call to sayHello will invoke the interceptors in the order bean level interceptor, method level interceptor and the AroundInvoke method within the bean class. A call to sayHi will invoke the interceptors in the order bean level interceptor and the AroundInvoke method within the bean class.

    Interceptor Classes

    package com.acme.ejb;

    import javax.ejb.AroundInvoke;
    import javax.ejb.InvocationContext;

    public class Interceptor1 {

    @AroundInvoke
    public Object log(InvocationContext invocationContext) throws Exception {
    System.err.println(invocationContext.getMethod().getName() + " called from interceptor 1");
    return invocationContext.proceed();
    }

    }

    package com.acme.ejb;

    import javax.ejb.AroundInvoke;
    import javax.ejb.InvocationContext;

    public class Interceptor2 {

    @AroundInvoke
    public Object log(InvocationContext invocationContext) throws Exception {
    System.err.println(invocationContext.getMethod().getName() + " called from interceptor 2");
    return invocationContext.proceed();
    }

    }

    Testing the Example using Glassfish

    The classes shown above can be packaged as a jar file and copied to the auto deploy directory of your Glassfish domain. The EJB is annotated with the @WebService annotation and the methods are annotated with the @WebMethod annotation, you can easily test the method invocations using the Glassfish console.

    Related Topics >>