Interceptors enable you to control method invocation flow. Thus, you can inject functionality before or after the invocation of a business method. This helps you to set apart common logic which is not part of the business logic of the beans, such as logging and security.
You can define interceptor methods in a separate class (external interceptor), or in the bean class itself. You can define interceptors to apply to all methods in the bean class, or to a specific method in the class (method-level interceptor). The invocation of interceptor methods occurs within the same transaction and security context as the business method being invoked. Interceptors can throw runtime exceptions or application exceptions defined in the signature of the business method.
To use interceptors you have to annotate your class with @Interceptor or @Interceptors annotation. This indicates that in this particular class you use interceptors. If you want to use an interceptor that wraps a business method, specify an AroundInvoke() method with the @AroundInvoke annotation.
You can use the @AroundInvoke annotation only once in a class, regardless of whether you are using it in a dedicated interceptor class or in the bean class.
You have an EJB 3.0 Project.
More information: Creating EJB 3.0 Projects.
You have created an enterprise bean to use the interceptor.
More information: Creating Session Beans and Creating Message-Driven Beans.
...
1. To define interceptors for a bean in a dedicated class, you create a plain Java class and add the necessary imports.
import javax.ejb.PostActivate; import javax.ejb.PrePassivate; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext;
public class TestInterceptor {
|
2. You create an empty constructor for the class.
public TestInterceptor() { }
|
3. You add the methods for the class and annotate them with @AroundInvoke, @PostActivate, and @PrePassivate.
@AroundInvoke public Object audit(InvocationContext ic) throws Exception { System.out.println("Invoking method: " + ic.getMethod()); return ic.proceed(); }
@PostActivate public void postActivate(InvocationContext ic) throws Exception { System.out.println("Invoking method: " + ic.getMethod());
}
@PrePassivate public void prePassivate(InvocationContext ic) throws Exception { System.out.println("Invoking method: " + ic.getMethod()); } |
The @PrePassivate and @PostActivate life cycle callback interceptor methods do not apply to stateless session beans and message-driven beans.
4. To define the class as an external interceptor class that applies to all methods in your bean, you add the annotation with the interceptor class before the bean class declaration.
@Stateful @Interceptors(com.sap.demo.interceptors.Test.class) public class TestBean implements TestLocal
|
5. To use a method from the external interceptor class as a method-level interceptor, you add the @Interceptors annotation before the method declaration.
@Interceptors (com.sap.demo.interceptors.Test.class) public void myBusinessMethod(String myString) {
|
...
To define interceptor methods in the bean class, you add the source code of the method to the bean class and annotate it.
@AroundInvoke public Object audit(InvocationContext ic) throws Exception { System.out.println("Invoking method: " + ic.getMethod()); return ic.proceed(); }
|
Methods annotated with the @AroundInvoke annotation must have one InvocationContext parameter only and must have a return type Object.
To intercept an EJB callback, define a method within your interceptor class that is annotated with the callback in which you are interested.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import javax.ejb.EJBException; import javax.ejb.PostActivate; import javax.ejb.PrePassivate; import javax.ejb.Stateful;
@Stateful public class StatefulExample {
// Non serializable member of bean instance private Connection connection;
@PostActivate public void initializeNonSerializableMembers() { try { connection = DriverManager.getConnection("<database url>"); } catch (SQLException e) { throw new EJBException("Cannot create database connection."); } }
// ...
public void businessMethod() throws SQLException { /** * Work with initialized connection. * * example: PreparedStatement ps = (PreparedStatement) * connection.createStatement(); ResultSet rs = ps.execute("<SQL * statement>"); */ }
// ...
@PrePassivate public void releaseNonSerializableMembers() { try { connection.close(); } catch (SQLException e) { throw new EJBException("Cannot destroy database connection."); } } } |
Use void for the return value of the method because EJB callbacks have no return value.
Annotation Reference Table
Name |
Use |
Target |
Annotation Attribute |
@Interceptors |
Use it to designate one or more interceptor classes associated with a bean. You can apply @Interceptors to the bean class or to a business method of the bean. |
TYPE |
value – lists all interceptor classes that are to be associated with the bean. |
@AroundInvoke |
Use it to designate an interceptor method. |
METHOD |
|
@ExcludeDefault Interceptors |
Apply this annotation to a bean class to exclude the invocation of default interceptors for all business methods of the bean. |
TYPE METHOD |
|
@ExcludeClass Interceptors |
Apply this annotation to a business method to exclude the invocation of class-level interceptors (but not default interceptors) for that method. |
METHOD |
|
@PostConstruct |
Use it to designate a life cycle callback method. |
METHOD |
|
@PreDestroy |
Use it to designate a life cycle callback method. |
METHOD |
|
@PostActivate |
Use it to designate a life cycle callback method. You can apply this annotation only to stateful session beans. |
METHOD |
|
@PrePassivate |
Use it to designate a life cycle callback method. You can apply this annotation only to stateful session beans. |
METHOD |
|