December 21, 2014

Java EE 6 Interceptors 1.0 (JSR318)

Introduction

Interceptor was in EE 5 introduced in EJB 3.0, see EJB3 Interceptors javax.ejb.AroundInvoke. In EE 6 that was taken out and made generic into Interceptors (JSR318), package javax.interceptor.*.

You can call Interceptor in EE 6 in two way:

  • By annotating method or class with @javax.interceptor.Interceptors(MyInterceptor.class)
  • Create custom Annotation with Annotation @javax.interceptor.InterceptorBinding and annotate with that you method or class.

Example

Your custom Interceptor.

package se.magnuskkarlsson.example.interceptor;

import java.io.Serializable;

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

import org.apache.log4j.Logger;

@Audit
@Interceptor
public class AuditInterceptor implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final Logger log = Logger.getLogger(AuditInterceptor.class);

    @AroundInvoke
    public Object intercept(InvocationContext ctx) throws Exception {
        log.info("### Entering method: " + ctx.getMethod().getName()
                + " in class " + ctx.getMethod().getDeclaringClass().getName());

        return ctx.proceed();
    }
}

Interception in a POJO.

package se.magnuskkarlsson.example.interceptor;

import javax.interceptor.Interceptors;

public class DemoPOJO {

    @Interceptors(AuditInterceptor.class)
    public String sayHello() {
        return "Hello POJO";
    }
}

Interception in a Stateless Session Bean.

package se.magnuskkarlsson.example.interceptor;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

@Stateless
public class DemoSLSB {

    @Interceptors(AuditInterceptor.class)
    public String sayHello() {
        return "Hello SLSB";
    }
}

beans.xml located for war in WEB-INF/.

<?xml version="1.0" encoding="UTF-8"?>
<beans 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 http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

</beans>

To use the Interceptor you must let weld create the intercepted class, otherwise will weld never knew about the interceptor and hence will the interceptor never work.

Example usage from a Servlet.

package se.magnuskkarlsson.example.interceptor;

import java.io.IOException;
import java.io.PrintWriter;

import javax.ejb.EJB;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/audit")
public class DemoServlet extends javax.servlet.http.HttpServlet {

    private static final long serialVersionUID = 1L;

    @Inject
    private DemoPOJO pojo;

    @EJB
    private DemoSLSB slsb;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");
        PrintWriter out = null;
        try {
            out = resp.getWriter();
            out.println("<html><body>");
            out.println("<h1>" + pojo.sayHello() + "</h1>");
            out.println("<h1>" + slsb.sayHello() + "</h1>");
            out.println("</html></html>");
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}

Limitation

You cannot use Interceptor directly in servlets, see https://java.net/projects/servlet-spec/lists/jsr340-experts/archive/2012-02/message/0.

No comments: