Eduardo
Eduardo

Reputation: 2280

Interceptor not working at method level in a Servlet

I have a simple web-app maven project with the following structure:

enter image description here

SimpleServlet.java is a servlet with the following code:

@Logger
public class SimpleServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello");
    }

}

And the Logger class is an interceptor interface with the following code:

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

And the MyLogger class is an interceptor implementation with the following code:

@Interceptor
@Logger
public class MyLogger {

    @AroundInvoke
    public Object veQuePedo(InvocationContext ctx) throws Exception {
        System.out.println("Logged");
        return ctx.proceed();
    }

}

My web.xml:

<web-app 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/web-app_3_0.xsd"
          version="3.0">

  <display-name>Archetype Created Web Application</display-name>
  <servlet>
        <servlet-name>ThaServlet</servlet-name>
        <servlet-class>com.SimpleServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ThaServlet</servlet-name>
        <url-pattern>/hola</url-pattern>
    </servlet-mapping>
</web-app>

And my beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                           http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
    version="1.1"
    bean-discovery-mode="all">
    <interceptors>
        <class>com.MyLogger</class>
    </interceptors>
</beans>

The case is that I read an interceptor only works on CDI beans, which I tested and noticed is correct.

For this example we are talking about a servlet, so I come to you with the following questions:

1) If the my servlet (the one in my example) is not considered a CDI bean, why when I set the @Logger interceptor works?

2) Why the interceptor @Logger in my servlet does not work at method level and does work fine at class level?

Debugging with the annotation at method level I see the servlet is wrapped, but for some reason the @AroundInvoke method is ignored.

enter image description here

Upvotes: 0

Views: 1164

Answers (1)

covener
covener

Reputation: 17872

Services provided by CDI, like interception, generally only happen on business method invocations.

Essentially, these are invocations of a method through a contextual reference (an injected bean, or the containers invocation of methods on components that are treated as beans like Servlets).

In your case, the method called from "outside" the bean to "inside" the bean is not doGet() -- it's some other inherited method. The call to doGet() comes from within the bean itself and cannot be intercepted.

That's why your interception at the class level seems to be intercepted once, although it's not on the doGet() that you later try to annotate directly.

Upvotes: 2

Related Questions