How to code EJB interceptors like a pro

EJB 3 interceptors provide the bean developer with fine grained control over the method invocation flow. In this tutorial we’ll see how to code server side EJB Interceptors and how to define Global EJB server side interceptors (WildFly 18 or newer).

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.

There are two types of EJB Interceptors you can plug in your code:

  • aroundInvoke Interceptors: These Interceptors will be called before a target EJB is invoked
  • aroundTimeout Interceptors: These Interceptors are called upon timeout of EJB timer service

aroundInvoke EJB Interceptors

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.

aroundTimeout EJB Interceptors

You can define interceptors for EJB timer service timeout methods by using the @AroundTimeout annotation on methods in the target class or in an interceptor class. Only one @AroundTimeout method per class is allowed.

The following code declares an @AroundTimeout interceptor method within a target class.

@Stateless
public class TimerBean {
...
    @Schedule(minute="*/1", hour="*")
    public void automaticTimerMethod() { ... }

    @AroundTimeout
    public void interceptorMethod(InvocationContext ctx) { ... }
...
}

Where can I apply EJB interceptors?

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()
    {
       ...
    }

4) 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).

Global EJB Interceptors

Since WildFly 18, it is possible to define one or more global EJB Interceptors which are invoked for all EJB running in the Container. The Interceptor is defined in a module therefore the application deployments are not changed.

Each interceptor is configured in <interceptor> tag which contains the following fields:

  • module – the module in which the interceptor is defined
  • class – the class which implements the interceptor

In order to use server interceptors you have to create a module that implements them and place it into ${WILDFLY_HOME}/modules directory.

Global Interceptor implementations are also POJO classes which use javax.interceptor.AroundInvoke and javax.interceptor.AroundTimeout to mark interceptor methods.

Sample configuration in the ejb3 subsystem:

<server-interceptors>
    <interceptor module="com.sample:MyInterceptor:1.0" class="com.sample.MyInterceptor"/>
</server-interceptors>

An this is a sample implementation:

package com.sample;

import javax.annotation.PostConstruct;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class MyInterceptor {

    @AroundInvoke
    public Object bar(final InvocationContext invocationContext) throws Exception {
        return invocationContext.proceed();
    }
}

Order of EJB 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:

<interceptor-binding>
    <target-name>myapp.OrderBean</target-name>
    <interceptor-class>demo.FirstInterceptor.class</interceptor-class>
    <interceptor-class>demo.SecondInterceptor.class</interceptor-class>
    <interceptor-class>demo.ThirdInterceptor.class</interceptor-class>
    <method-name>updateInfo</method-name>
</interceptor-binding>

Excluding the default Interceptor

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();
    }
 }

Scenarios where you can use Interceptors:

Interceptors are particularly when:

  • It is required 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.
Found the article helpful? if so please follow us on Socials