EJB 3.x interceptors

An interceptor is a method that is automatically called when the business methods of an Enterprise JavaBeans (EJB) are invoked or lifecycle events of an EJB occur.

There are three kinds of interceptor methods: business method interceptors, timeout method interceptors (which are new in EJB3.1), and lifecycle callback interceptors. Business method interceptors are invoked around the call to a business method. Timeout method interceptors are invoked around the call to an EJB timeout method. Lifecycle callback interceptors are called around one of the PostConstruct, PreDestroy, PrePassivate, or PostActivate lifecycle events. For each interceptor type, an individual class can only declare one interceptor method. However, each class in a class hierarchy can declare an interceptor method for each interceptor type. If an interceptor method in a subclass overrides the same method in a super-class, only the method in the subclass might be invoked.

Interceptor methods are permitted to access and call all resources and components that the associated method is allowed to call. Additionally, interceptor methods execute with the same transaction and security context as the associated method. Except for singleton session beans, lifecycle interceptor methods are executed with local transaction containment (LTC).

You can declare interceptor methods directly in the EJB class or in a separate interceptor class. To declare interceptor methods in a separate class, you must bind the interceptor class to the EJB using either an annotation or XML. Use the following example to declare interceptors using the annotation:

@Interceptors({ClassInterceptor1.class, ClassInterceptor2.class})
public class TestBean { /* ... */ }

@Interceptors({ClassInterceptor1.class})
public class TestBean2 {
	@Interceptors({MethodInterceptor1.class, MethodInterceptor2.class})
	public void businessMethod() { /* ... */ }
}

Use the following example to declare interceptors using the deployment descriptor:

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <interceptor-class>ClassInterceptor1</interceptor-class>
      <interceptor-class>ClassInterceptor2</interceptor-class>
    </interceptor-binding>

    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <interceptor-class>ClassInterceptor1</interceptor-class>
    </interceptor-binding>

    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <interceptor-class>MethodInterceptor1</interceptor-class>
      <interceptor-class>MethodInterceptor2</interceptor-class>
      <method>
        <method-name>businessMethod</method-name>
      </method>
    </interceptor-binding>
  </assembly-descriptor>

You can exclude class-level interceptors from a method by using either the ExcludeClassInterceptors annotation or the exclude-class-interceptors element in the deployment descriptor. Use the following example to exclude the interceptor, ClassInterceptor, from the method, businessMethod.

@Interceptors({ClassInterceptor1.class})
public class TestBean2 {
	@ExcludeClassInterceptors
	public void businessMethod() { /* ... */ }

	public void businessMethodWithClassInterceptor1() { /* ... */
}

Use the following example to exclude the interceptor from the method using the deployment descriptor:

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <exclude-class-interceptors>true</exclude-class-interceptors>
      <method>
        <method-name>businessMethod</method-name>
      </method>
    </interceptor-binding>
  </assembly-descriptor>

Interceptor methods can have public, protected, package private, or private visibility. Interceptor methods must not be final or static. Business method interceptors and timeout method interceptors must have a return type of java.lang.Object, a single parameter of javax.interceptor.InvocationContext, and a single throws clause type of java.lang.Exception. All lifecycle interceptors must have a return type of void and must not have a throws clause. Lifecycle interceptors declared directly on the EJB class must not have parameters; lifecycle interceptors declared on an EJB superclass or on an interceptor class must have a single parameter of javax.interceptor.InvocationContext. Timeout interceptor methods and lifecycle interceptor methods must not throw application exceptions.

You can use the InvocationContext parameter of an interceptor method to get information about the method being invoked. The getTarget method returns the bean instance being invoked. The getTimer method is applicable to timeout method interceptors only, and it returns the timer being executed. The getMethod method returns the business interface method that is being invoked. The getParameters method returns the parameters being passed to the business method, and the setParameters method allows the parameters to be modified. The getContextData method returns the data association with the method being invoked. Finally, the proceed method invokes either the next interceptor or the target method.

You can declare interceptor methods using either annotations or XML. To declare an interceptor method using an annotation, place the appropriate AroundInvoke, AroundTimeout, PostConstruct, PreDestroy, PrePassivate, or PostActivate annotation on the interceptor method. Use the following example to declare a business method interceptor, a timeout method interceptor, and a PostConstruct lifecycle interceptor method on an EJB class using annotations.

@Interceptors({ClassInterceptor.class})
public class TestBean {
	@PostConstruct
	private void beanPostConstruct() { /* ... */ }

	@AroundInvoke
	protected Object beanAroundInvoke(InvocationContext ic) throws Exception {
		return ic.proceed();
	}

        @AroundTimeout
        protected Object beanAroundTimeout(InvocationContext ic) throws Exception {
		return ic.proceed();
        }
}

Use the following example to declare the same interceptor methods on an interceptor class.

public class ClassInterceptor {
	@PostConstruct
	private void interceptorPostConstruct(InvocationContext ic) {
		try {
			ic.proceed();
		} catch (Exception ex) { /* ... */ }
	}

	@AroundInvoke
	protected Object interceptorAroundInvoke(InvocationContext ic) throws Exception {
		return ic.proceed();
	}

	@AroundTimeout
	protected Object interceptorAroundTimeout(InvocationContext ic) throws Exception {
		return ic.proceed();
	}
}

Alternatively, you can declare an interceptor method in the deployment descriptor with the around-invoke, around-timeout, post-construct, pre-destroy, pre-passivate, and post-activate elements. Use the following example to declare a business method interceptor, a timeout method interceptor, and a PostConstruct lifecycle interceptor method on an EJB class and an interceptor class using the deployment descriptor.

  <enterprise-beans>
    <session>
      <ejb-name>TestBean</ejb-name>
      <around-invoke>
        <method-name>beanAroundInvoke</method-name>
      </around-invoke>
      <around-timeout>
        <method-name>beanAroundTimeout</method-name>
      </around-timeout>
      <post-construct>
        <lifecycle-callback-method>beanPostConstruct</lifecycle-callback-method>
      </post-construct>
    </session>
  </enterprise-beans>

  <interceptors>
    <interceptor>
      <interceptor-class>ClassInterceptor</interceptor-class>
      <around-invoke>
        <method-name>interceptorAroundInvoke</method-name>
      </around-invoke>
      <around-timeout>
        <method-name>interceptorAroundTimeout</method-name>
      </around-timeout>
      <post-construct>
        <lifecycle-callback-method>interceptorPostConstruct</lifecycle-callback-method>
      </post-construct>
    </interceptor>
  </interceptors>

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <interceptor-class>ClassInterceptor</interceptor-class>
    </interceptor-binding>
  </assembly-descriptor>

You can also declare interceptor methods on super-classes. Use the following example to declare a PostActivate interceptor on a bean super-class using annotations:

public class TestBean extends BeanSuperClass { /* ... */ }

public class BeanSuperClass {
	@PostActivate
	private void beanSuperClassPostActivate(InterceptorContext ic) {
		try {
			ic.proceed();
		} catch (Exception ex) { /* ... */ }
	}
}

Use the following example to declare the same interceptor method on a superclass of an interceptor class using annotations:

public class ClassInterceptor extends InterceptorSuperClass { /* ... */ }

public class InterceptorSuperClass {
	@PostActivate
	private void interceptorSuperClassPostActivate(InterceptorContext ic) {
		try {
			ic.proceed();
		} catch (Exception ex) { /* ... */ }
	}
}

You can also declare the same interceptor methods using the deployment descriptor. Use the following example to declare an interceptor method on the superclasses of a bean and interceptor class:

<enterprise-beans>
  <session>
    <ejb-name>TestBean</ejb-name>
    <post-activate>
      <class>BeanSuperClass</class>
	 <lifecycle-callback-method>beanSuperClassPostActivate</lifecycle-callback-method>
    </post-activate>
  </session>
 </enterprise-beans>

 <interceptors>
   <interceptor>
    <interceptor-class>ClassInterceptor</interceptor-class>
    <post-activate>
      <class>InterceptorSuperClass</class>
	 <lifecycle-callback-method>interceptorSuperClassPostActivate</lifecycle-callback-method>
    </post-activate>
   </interceptor>
 </interceptors>

 <assembly-descriptor>
   <interceptor-binding>
     <ejb-name>TestBean</ejb-name>
     <interceptor-class>ClassInterceptor</interceptor-class>
   </interceptor-binding>
 </assembly-descriptor>

You can declare default interceptors that apply to all session and message-driven beans in a module. Default interceptors can only be declared in the deployment descriptor, and they are specified using an ejb-name of "*". Use the following example to declare a default interceptor.

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>DefaultInterceptor</interceptor-class>
    </interceptor-binding>
  </assembly-descriptor>

You can exclude default interceptors from a specific class or method by using either the ExcludeDefaultInterceptors annotation or the exclude-default-interceptors element in XML. Use the following examples to exclude default interceptors using the annotation:

@ExcludeDefaultInterceptors
public class TestBean { /* ... */ }

public class TestBean2 {
	@ExcludeDefaultInterceptors
	public void businessMethod() { /* ... */ }
}

Use the following example to excludes default interceptors using the deployment descriptor:

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <exclude-default-interceptors>true</exclude-default-interceptors>
    </interceptor-binding>

    <interceptor-binding>
      <ejb-name>TestBean2</ejb-name>
      <exclude-default-interceptors>true</exclude-default-interceptors>
      <method>
        <method-name>businessMethod</method-name>
      </method>
    </interceptor-binding>
  </assembly-descriptor>

When interceptors are invoked for a method, default interceptor classes are invoked first, class-level interceptors are invoked next, and interceptors methods from the EJB class are invoked last. For a single interceptor class hierarchy, interceptor methods are always invoked on the most general super-class first. The default and class-level interceptor classes are invoked in the order specified in the deployment descriptor or the Interceptors annotation. You can override this ordering by specifying the complete list of default and class-level interceptors in the interceptor-order element in the deployment descriptor.

  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>TestBean</ejb-name>
      <!--
        The default ordering would be:
	  1. DefaultInterceptor
	  2. ClassInterceptor1
	  3. ClassInterceptor2

	The following stanza overrides the default ordering.
      -->
      <interceptor-order>
        <interceptor-class>ClassInterceptor2</interceptor-class>
	<interceptor-class>DefaultInterceptor</interceptor-class>
	<interceptor-class>ClassInterceptor1</interceptor-class>
      </interceptor-order>
    </interceptor-binding>
  </assembly-descriptor>



Related concepts
Enterprise beans
Related tasks
Developing enterprise beans
Related reference
Enterprise bean development best practices
Reference topic Reference topic    

Terms of Use | Feedback

Last updatedLast updated: Sep 19, 2011 6:15:55 PM CDT
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=matt&product=was-express-dist&topic=rejb_3interceptors
File name: rejb_3interceptors.html