/java/

Using Interceptors in CDI Applications

2015-07-11 16:44:35

From docs: An interceptor is a class used to interpose in method invocations or lifecycle events that occur in an associated target class. The interceptor performs tasks, such as logging or auditing, that are separate from the business logic of the application and are repeated often within an application. Such tasks are often called cross-cutting tasks. Interceptors allow you to specify the code for these tasks in one place for easy maintenance.

Let's assume that we have some important service, for example payment service:

package pl.btbw;

public class PaymentService {

    public void pay(Integer pay) {
    }

    public void refund(Integer pay) {
    }
}

pay and refund method are very important as a things connecting with money. That is why we decided to add some log.

we can do that by simple interceptor

first we have to create custom annotation

package pl.btbw.logger;

import javax.interceptor.InterceptorBinding;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Logged {
}

and add this annotation to our service

package pl.btbw;

import pl.btbw.logger.Logged;

public class PaymentService {

    @Logged
    public void pay(Integer pay) {
    }

    @Logged
    public void refund(Integer pay) {
    }
}

now we have to create LoggedInterceptor class

package pl.btbw.logger;

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

@Logged
@Interceptor
public class LoggedInterceptor {

    public LoggedInterceptor() {
    }

    @AroundInvoke
    public Object logMethodEntry(InvocationContext invocationContext) throws Exception {

        Object[] parameters = invocationContext.getParameters();
        String params = "";
        for (Object parameter : parameters) {
            params += " " + parameter.toString();
        }

        System.out.println(
                String.format(
                        "User invoke method %s with parameters %s",
                        invocationContext.getMethod().getName(),
                        params
                )
        );

        return invocationContext.proceed();
    }
}

beans.xml

<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>

<beans beans_1_0.xsd&quot;="" http:="" java.sun.com="" javaee="" ns="" xml="" xmlns='"http://java.sun.com/xml/ns/javaee"' xmlns:xsi='"http://www.w3.org/2001/XMLSchema-instance"' xsi:schemalocation='"http://java.sun.com/xml/ns/javaee'>
<interceptors>
<class>pl.btbw.logger.LoggedInterceptor</class>
</interceptors>
</beans>

and that it's, now if you invoke methids

package pl.btbw;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/")
public class AppCtrl {

    @Inject
    private PaymentService paymentService;

    @GET
    public String test() {
        paymentService.pay(100);
        paymentService.refund(50);
        return "";
    }
}

you will get

17:29:18,910 INFO  [stdout] (default task-8) User invoke method pay with parameters  100
17:29:18,910 INFO  [stdout] (default task-8) User invoke method refund with parameters  50

GitHub