Ejb interceptors in depth

User Rating: 4 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Inactive
 

EJB 3.0 interceptors provide the bean developer with fine grained control over the method invocation flow. In this tutorial we'll see from practical examples how it can we can take advantage of it.

 

 

An interceptor is a method that you can interpose in the invocation flow of an enterprise bean. You can define an interceptor to intercept an enterprise bean's business methods:  the interceptor method will be executed before any of the bean's business methods are invoked.


The great benefit of interceptors is that they give you a way to add functionality to your business methods without modifying the methods' code.
Let's see a practical example:
 

import javax.ejb.Stateless;

import javax.interceptor.Interceptors;

import org.jboss.ejb3.annotation.RemoteBinding;

@Stateless(name="SampleEJB")
@RemoteBinding(jndiBinding="SampleEJB")
@Interceptors(value=com.sample.MyInterceptor.class)

public class SampleBean implements Sample {

    public void doSomething(String param) {
        callWebService(param);
    }
}

In this class we've declared a custom interceptor named com-sample.MyInterceptor :

How does it work ? when a method of your SampleEJB is invoked, the Interceptor is invoked. The interceptors has full access to the method name invoked and its parameter.

 

package com.sample;

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

public class MyInterceptor {

    @AroundInvoke
    public Object log(InvocationContext ctx) throws Exception
    {
        System.out.println("*** TracingInterceptor intercepting " + ctx.getMethod().getName());
        long start = System.currentTimeMillis();
        String param = (String)ctx.getParameters()[0];

        if (param == null)
            ctx.setParameters(new String[]{"default"});

        try
        {
            return ctx.proceed();
        }
        catch(Exception e)
        {
            throw e;
        }
        finally
        {
            long time = System.currentTimeMillis() - start;
            String method = ctx.getClass().getName();
            System.out.println("*** TracingInterceptor invocation of " + method + " took " + time + "ms");
        }
    }
}

In this example the Interceptor validates the parameters and then invokes the method ctx.proceed() which in turns call the next Interceptor in the chain (if any) and finally the business method.

When the business method returns the Interceptor resumes its execution and calculates the time elapsed.


Scenarios where you can use Interceptors:

Interceptors are particularly when:

  • You need to validate parameters before they're passed to a business method
  • You need to perform security checks at the time the business method is called.
  • You need to perform other useful for actions such as logging and profiling without changing the code of your EJB.


On what kind of components you can apply Interceptors ?

They can be used on stateless session beans, stateful session beans, and message driven beans.

How many kind of Interceptors can you apply ?

You can apply Interceptors at three different level:
1) Default interceptors:

These interceptors needs to be declared in your ejb-jar.xml and are valid across all your EJB deployed :


 <assembly-descriptor>
 <interceptor-binding>
 <ejb-name>*</ejb-name>
 <interceptor-class>sample.interceptor.MyDefaultInterceptor</interceptor-class>
 </interceptor-binding>
 ...
 </assembly-descriptor>

2) Class level interceptors:

This is the kind of interceptor we've seen in our example: it is valid across all methods of an EJB.


@Stateless
    @Interceptors(value=com.sample.SampleInterceptor.class)
    public class StatelessBean
    {
       ...
    }

3) Method level interceptors:

The method level interceptor only intercepts the single method call :

    @Interceptors(value=com.sample.MethodInterceptor.class)
    public void doSomething()
    {
       ...
    }


Order of Interception

The default interceptor is invoked at first. Then Bean level interceptors are invoked and, at last, method level interceptors. If you declare a list of interceptors in your xml/annotations the interceptors are invoked in the order in which they are declared in the annotation.

Interceptors in the Bean class:

Interceptors do not need to be written in a separate file: you can code interceptors in the EJB class as well:

@Stateless(name="SampleEJB")
@RemoteBinding(jndiBinding="SampleEJB")
@Interceptors(value=com.sample.MyInterceptor.class)

public class SampleBean implements Sample {

    public void doSomething(String param) {
        callWebService(param);
    }
    @AroundInvoke
    public Object log(InvocationContext ctx) throws Exception
    {

        try
        {
            return ctx.proceed();
        }
        catch(Exception e)
        {
            throw e;
        }
    }
}

The only thing that differs if you declare your interceptors in the Bean class is the order: if you have on the same Class both External Interceptors and Internal Interceptors the (Internal) Interceptor method defined in the bean class itself is invoked at the end. (after the Interceptors in external files)

How do you exclude the DefaultInterceptor ?

If you have defined a default interceptor for all your EJB in a jar file, you can use the following annotation to exclude it and instead execute the Interceptor in the class:

@Stateless(name="SampleEJB")
@ExcludeDefaultInterceptors        
public class TestEJB implements Test
{

    @AroundInvoke
    public Object customInterceptor(InvocationContext ctx) throws Exception
    {
        System.out.println("*** CustomInterceptor intercepting");
        return ctx.proceed();
    }
 }

Related articles available on mastertheboss.com

EJB 3.0 tutorial : Session Beans

Enterprise JavaBeans (EJB) technology is a J2EE technology for de

JBoss MDB 3.0

Message-driven beans (MDBs) are stateless, server-side, transacti

JBoss EJB 3 BMT

In a Bean Managed Transaction, the code in the session or message

How do you keep your EJB callbacks separated from biz. methods?

JBoss daily recipe

How to set EJB timeout period ?

JBoss recipe of the day

How to add a Selector with MDB 3.0 ?

Message selectors allow an MDB to be more selective about the mes