ejb3

EJB Interceptors Example

1. Introduction

This is an example of how to use the javax.interceptor.* in an EJB.

Interceptors are used, as the name suggests, to intercept ejb methods calls using methods annotated with interceptor annotation (@AroundInvoke , @AroundTimeout , @PostConstruct etc ).

An interceptor method is called by Ejb Container before ejb method call it is intercepting.

The Interceptors specification defines two kinds of interception points:

  • business method interception, and
  • lifecycle callback interception.

Interceptor Types
Figure 1: Interceptor Types

In addition, the EJB specification defines timeout method interception.

2. Create a new EJB Module

Open NetBeans IDE, choose File > New Project.

In the New Project wizard, expand the Java EE category and select EJB Module as shown in the figure below. Then click Next.

Figure 2: Create new EJB Module
Figure 2: Create new EJB Module

You have to specify the Project Name, the Project Name and the Project Location in the appropriate text fields and then click Next.

Figure 3: Configure Project
Figure 3: Configure Project

In the next window , add the JEE Server and select the JEE version and click Finish.

Figure 4: Add Server
Figure 4: Add Server

3. Create a new Session Bean

Go to File -> New File -> Enterprises JavaBeans -> Session Bean or
Right-click the EJB module project and choose New > Session Bean .

Figure 5: Create new Session Bean
Figure 5: Create new Session Bean

4. EJB Interceptors

4.1 Introduction

The EJB 3.0 spec defines the ability to apply custom made interceptors to the business methods of your beans.

4.2 Implementing interceptors

An interceptor is defined as a simple class where there is a single method annotated with @AroundInvoke and life-cycle annotation . This method will be called on every business and life-cycle method call to the EJB .

SampleInterceptor.java

package org.netbeans.example;

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

/**
 *
 * @author jGauravGupta
 */
public class SampleInterceptor {

    @PostConstruct
    public void init(InvocationContext context) throws Exception {
        System.out.println("SampleInterceptor > PostConstruct > init");
        context.proceed();
    }

    @AroundConstruct
    public Object construct(InvocationContext context) throws Exception {
        System.out.println("SampleInterceptor > construct");
        return context.proceed();
    }

    @AroundInvoke
    public Object invoke(InvocationContext context) throws Exception {
        System.out.println("SampleInterceptor > invoke");
        return context.proceed();
    }

    @PreDestroy
    public void destroy(InvocationContext context) throws Exception {
        System.out.println("SampleInterceptor > PreDestroy > destroy");
        context.proceed();
    }
}

4.3 Binding an interceptor to a bean

Here is the EJB that will use the above Interceptor to intercept it’s methods using Interceptors annotation.

@javax.interceptor.Interceptors declares an ordered list of interceptors for a target class or method of a target class.

SampleBean.java

package org.netbeans.example;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.interceptor.Interceptors;

/**
 *
 * @author jGauravGupta
 */
@Stateless
@LocalBean
@Interceptors(SampleInterceptor.class)
public class SampleBean {

    @PostConstruct
    public void init() {
        System.out.println("SampleBean > PostConstruct > init");
    }

    public void test() {
        System.out.println("SampleBean > test");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("SampleBean > PreDestroy > destroy");
    }

}

4.4 Tester

Let’s create a simple auto startup Singleton Bean to test the desired functionality.

Create Tester
Create Tester

Tester.java

package org.netbeans.example;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.LocalBean;
import javax.ejb.Startup;

/**
 *
 * @author jGauravGupta
 */
@Singleton
@LocalBean
@Startup
public class Tester {

    @EJB
    SampleBean sampleBean;

    @PostConstruct
    public void init() {
        sampleBean.test();
    }
}

4.5 Output

Verify the following output in NetBeans console :

Info:   SampleInterceptor > construct
Info:   SampleInterceptor > PostConstruct > init
Info:   SampleBean > PostConstruct > init
Info:   SampleInterceptor > invoke
Info:   SampleBean > test
Info:   InterceptorExample was successfully deployed in 199 milliseconds.
Info:   SampleInterceptor > PreDestroy > destroy
Info:   SampleBean > PreDestroy > destroy
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   Portable JNDI names for EJB Tester:
Info:   Portable JNDI names for EJB SampleBean:
Info:   SampleInterceptor > construct
Info:   SampleInterceptor > PostConstruct > init
Info:   SampleBean > PostConstruct > init
Info:   SampleInterceptor > invoke
Info:   SampleBean > test
Info:   InterceptorExample was successfully deployed in 232 milliseconds.

4.6 Download the NetBeans Project

Download the NetBeans project of Interceptor tutorial:

Download
You can download the full source code of this example here: InterceptorExample.zip

5. CDI Interceptors

5.1 Introduction

CDI Interceptors are pretty much the same as EJB interceptors, however since they are applied using a qualifier, you will at first define your interceptor qualifier, for example, here is a SampleBinding qualifier (which can be triggered by adding the @SampleBinding annotation on your Beans):

5.2 Interceptor bindings

An interceptor binding type may be declared by specifying the @javax.interceptor.InterceptorBinding meta-annotation.

Go to File -> New File -> Contexts and Dependency Injection > Interceptor Binding Type :

Create InterceptorBinding
Create InterceptorBinding

Type SampleBinding for the class name and org.netbeans.example for the package :

Configure InterceptorBinding
Configure InterceptorBinding

SampleBinding.java

package org.netbeans.example;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding;

/**
 *
 * @author jGauravGupta
 */
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface SampleBinding {

    boolean transaction() default false;
}

Suppose we want to add some extra information to our @SampleBinding annotation . CDI will use the value of transaction to choose between two different interceptors TransactionalInterceptor and NonTransactionalInterceptor.

5.3 Implementing interceptors

Now will code the Interceptor definition, which is annotated with the qualifier annotation (@SampleBinding) as well as with the @Interceptor annotation at the top of it.

Right-click on SampleBinding.java editor -> Insert Code… -> Generate Interceptor :

Implementing interceptors
Implementing interceptors

TransactionalInterceptor.java

package org.netbeans.example;

import javax.interceptor.AroundConstruct;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

/**
 *
 * @author jGauravGupta
 */
@SampleBinding(transaction = true)
@Interceptor
public class TransactionalInterceptor {

    @AroundConstruct
    public Object construct(InvocationContext context) throws Exception {
        System.out.println("TransactionalInterceptor > construct");
        return context.proceed();
    }

    @AroundInvoke
    public Object invoke(InvocationContext context) throws Exception {
        System.out.println("TransactionalInterceptor > invoke");
        return context.proceed();
    }

}

NonTransactionalInterceptor.java

package org.netbeans.example;

import javax.interceptor.AroundConstruct;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

/**
 *
 * @author jGauravGupta
 */
@SampleBinding(transaction = false)
@Interceptor
public class NonTransactionalInterceptor {

    @AroundConstruct
    public Object construct(InvocationContext context) throws Exception {
        System.out.println("NonTransactionalInterceptor > construct");
        return context.proceed();
    }

    @AroundInvoke
    public Object invoke(InvocationContext context) throws Exception {
        System.out.println("NonTransactionalInterceptor > invoke");
        return context.proceed();
    }

}

5.4 Binding an interceptor to a bean

Now we can apply this annotation either at class level (and will intercept all method calls) or at method level, so it will intercept just that method call. Let’s apply it to the SampleBean :

SampleBean.java

package org.netbeans.example;

import javax.ejb.Stateless;
import javax.ejb.LocalBean;

/**
 *
 * @author jGauravGupta
 */
@Stateless
@LocalBean
@SampleBinding(transaction = true)
public class SampleBean {

    public void test() {
        System.out.println("SampleBean > test");
    }

}

The @SampleBinding(transaction = true) annotation applied at class level denotes that all the methods should be intercepted with TransactionalInterceptor.

5.5 Enabling interceptors

By default, all interceptors are disabled. To enable the cdi interceptors , you need to declare it into your beans.xml file:

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="annotated">
   <interceptors>
     <class>org.netbeans.example.TransactionalInterceptor</class>
     <class>org.netbeans.example.NonTransactionalInterceptor</class>
   </interceptors>
</beans> 

Those lines in beans.xml not only “enable” the interceptors, but also define the “order of execution” of the interceptors.

5.6 Output

Verify the following output in NetBeans console :

Info:   TransactionalInterceptor > construct
Info:   TransactionalInterceptor > invoke
Info:   SampleBean > test

5.7 Download the NetBeans Project

Download the NetBeans project of the CDI Interceptor tutorial:

Download
You can download the full source code of this example here: CDI_InterceptorExample.zip

jGauravGupta

Gaurav is a senior software engineer with a passion for learning. He is an evangelist of netbeans & new technologies and author of JPA Modeler , jBatch Suite etc . He loves to go beyond the same old day to day work and find new and innovative ways to do the same things more effectively.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button