Skip to content

2. Interceptors

JOHNYBASHA SHAIK edited this page Aug 30, 2018 · 4 revisions

Interceptors

Interceptors bring cross-cutting functionality to the bean.


Interceptors fall in four categories

  • Lifecycle callback interceptor (@PostConstruct, @PreDestroy, @AroundConstruct)
  • Business Method interceptor (@AroundInvoke)
  • Time-out method interceptor (@AroundTimeout)

Eg:

@AroundInvoke
<access modifier> Object <method name>(InvocationContext ic) throws Exception;

The method(s) marked with any of the above annotations should obey the below conditions:

  • It can have any access level modifier but should not be static and/or final.
  • Must have InvocationContext parameter
  • Can throw a checked exception.
  • The lifecycle interceoptor methods must have void return type but other types(@AroundInvoke, @AroundTimeout) Must return Object, which is the result of invoked target method.
Few useful interceptor annotations

Interceptors – For chaining one or more interceptors to the target class.

ExcludeClassInterceptors – Excludes method(s) from the interceptors declared at the class level.

InterceptorBinding – Binds the interceptor class(es) with intercepted class.

Interceptor - This annotation attaches the InterceptorBinding to the interceptor

Priority – Prioritizes the order of interceptor methods order.


Ways of adding interceptor
  • 1.Target class interceptor:
    This is the simplest way of adding interceptor to the bean. A bean can annotate its methods with any of the 4 categories listed at the beginning. The scope of this interceptor is limited to the bean itself. Notice that this class doesn't need any additional annotation at the class level.

    Eg:

public class BookOrderService {
  public void createOrder(Order order) {
  //logic
  }
				
  @AroundInvoke
  private Object logMethod(InvocationContext ic) throws Exception {
    logger.info("Entering");
    try {
      ic.proceed();
    } finally {
      logger.info("Existing");
    }
  }
}

In the above example, the logMethod() will be triggered when container makes call to any of the methods(ie. createOrder() method) in BookOrderService.java.

  • 2.Class Interceptor:
    In this approach, the cross cutting functionality will be isolated into a class and instruct the container to intercept the calls on several beans using @Interceptors annotation.

    Eg:

  @Interceptors(MyInterceptor1.class, MyInterceptor2.class)
  public class BookOrderService {
    @Interceptors(MyInterceptor3.class, MyInterceptor4.class)
    public void createOrder(Order order) {
        //logic
    }
					
    public void updateOrder(Order order) {
        //logic
     }
   }

Notice that the order the listed interceptors get executed, is the order they are listed. In this example, MyInterceptor1 will be executed before MyInterceptor2 for updateOrder() and the sequence is MyInterceptor1, MyInterceptor2, MyInterceptor3 and MyInterceptor4 for createOrder()

  • 3.InterceptorBinding

InterceptorBinding introduces a level of indirection and loose coupling for interceptors. Notice that the @InterceptorBinding is applicable only for CDI enabled beans.

To make use of interceptor binding, one should

  • a. define a InterceptorBinding annotation.

    Eg:

	@InterceptorBinding
	@Target({METHOD, TYPE})
	@Retention(RUNTIME)
	public @interface Monitord{}
  • b. Attach the InterceptorBinding annotation to the interceoptor itself. This can be done by annotating the interceoptor with both @Interceptor and interceptorbinding.

    Eg:

	@Interceptor
	@Monitord
	public class MyInterceptor {
	 @AroundInvoke
	 public Object method(InvocationContext ic) throws Exception {
	   //logic
	 }
	}
  • c. Annotate the desired bean or bean method with the interceoptorbinding.

    Eg:

	@Monitord
	public class BookOrderService {
	    method()
	}
							
	public class BookSupplyService {
	 @Monitord							
	 method()
	}