Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is interceptor really disabled by default?

I ran into this confusion today. Quote from Weld's documentation (right under Section 9.3),

By default, all interceptors are disabled. We need to enable our interceptor. We can do it using beans.xml descriptor of a bean archive. However, this activation only applies to the beans in that archive.

However, in the project that I am currently working on, I have an interceptor for profiling a method. My META-INF/beans.xml is basically empty:

<?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">
</beans>

Yet I still get expected logs from that profiling interceptor. So, as the title goes, is interceptor really disabled by default?

BTW, I use weld-se for CDI functionality in the project, since CDI is the only thing I need for the project from the Java EE stack.

update

After messing around interceptors today, I find that if the old @Interceptors is used to indicate the interception implementation class, you don't need to specify anything in the beans.xml. However, if you use interceptor binding, i.e., use the @Interceptor annotation to indicate an interceptor class, you must enable interception by adding the interceptor class to the beans.xml. According to my experience, this is still true for CDI 1.1, as indicated by the version in the beans.xml above. BTW, I use org.jboss.weld.se:weld-se:2.0.4.Final for CDI implementation in this case, which I believe implements CDI 1.1.

like image 295
JBT Avatar asked Oct 15 '13 06:10

JBT


People also ask

How interceptors are declared?

An interceptor is defined using one of the interceptor metadata annotations listed in Table 50-1 within the target class, or in a separate interceptor class. The following code declares an @AroundTimeout interceptor method within a target class. @Stateless public class TimerBean { ...

Why are interceptors used?

Interceptors are used in conjunction with Java EE managed classes to allow developers to invoke interceptor methods on an associated target class, in conjunction with method invocations or lifecycle events. Common uses of interceptors are logging, auditing, and profiling.

What is interceptor in common architecture in Java?

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.

What are interceptors for business methods?

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 Answers

To confirm JBT findings in his EDIT. As per CDI specifications 1.0 of JSR-299 implemented by Weld 1.0 for JEE6 specs. Please reference this pointer, which I quote:

By default, a bean archive has no enabled interceptors bound via interceptor bindings. An interceptor must be explicitly enabled by listing the fully qualified class name in a child <class> element of <interceptors>. as in Approach 2 below

Follows an example:

First mandatory step is the interceptor binding:

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

Second mandatory step is the Intercepting Class:

@Interceptor
@Loggable
public class LoggingInterceptor {

    @AroundInvoke
    public Object logMethodEntry(InvocationContext ctx) throws Exception{
        System.out.println("In LoggingInterceptor..................... before method call");
        Object returnMe = ctx.proceed();
        System.out.println("In LoggingInterceptor..................... after method call");
        return returnMe;
    }
}

Third step can be achieved using either one of the following approaches

Approach 1, an empty beans.xml will do the job

@Stateless
@Interceptors(LoggingInterceptor.class)     //class interception
public class Displayer implements DisplayerLocal {

    @Override
    //@Interceptors(LoggingInterceptor.class)  //method interception
    public void displayHi() {
        System.out.println(".....Hi there............");
    }
}

Approach 2, needs the beans.xml as follows

<?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">
    <interceptors>
        <class>com.companyname.LoggingInterceptor</class>
    </interceptors>
</beans>

Then the intercepted class:

@Stateless
@Loggable       //class interception
public class Displayer implements DisplayerLocal {

    @Override
    //@Loggable      //method interception
    public void displayHi() {
        System.out.println(".....Hi there............");
    }
}
like image 127
Sym-Sym Avatar answered Sep 21 '22 01:09

Sym-Sym