CDI: Using Interceptors across different modules / bean archives

自古美人都是妖i 提交于 2019-12-03 02:56:38
gortiz

J2EE 7 specification says (reference):

The interceptors that you specify in the beans.xml file apply only to classes in the same archive. Use the @Priority annotation to specify interceptors globally for an application that consists of multiple modules

This solution has the advantage of being vendor independent.

An Example:

@Logged
@Interceptor
@Priority(Interceptor.Priority.APPLICATION)
public class LoggedInterceptor implements Serializable { ... }

It is too late, but if somebody still having this problem. Both modules should be loaded by the same classloader to make usage of interceptor across different modules possible, at least in WebSphere 8b2. In WebSphere this setting can be switched in administration console: Applications > Application Types > WebSphere enterprise applications > [your app name] > Class loading and update detection > WAR class loader policy = Single class loader for application.
Interceptor must be enabled only ONCE in beans.xml.

I wonder if your WAR lacks classloader visbility into your ejb-jar? I think ideally the 299 interceptors would be in their own jar, visible to both the EJB and web modules and enabled in both of their beans.xml.

I have the same issue on JBoss AS 6.0 / 6.1 (nightly build) and fixed it by disabling separate classloaders (option 1), but be extremely careful with this. The separation of classloaders hasn't been introduced for no reason, so apparently there are new problems on the road ahead...

This is the jira report, please vote it up :-)

I had exactly the same problem with my logging interceptor on JBoss 7 and fixed it by overlaying the complete interceptor's jar into the application.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <overlays>
                    <overlay>
                        <groupId>com.github.t1</groupId>
                        <artifactId>logging-interceptor</artifactId>
                        <type>jar</type>
                        <targetPath>WEB-INF/classes</targetPath>
                    </overlay>
                </overlays>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>com.github.t1</groupId>
        <artifactId>logging-interceptor</artifactId>
        <version>1.1</version>
        <optional>true</optional>
    </dependency>
</dependencies>

You'll still have to activate the interceptor in the application's breans.xml.

Not nice, but it works. In Java EE 7, it works without the activation by annotating the interceptor as @Priority.

If you have no control over the external dependency and you still want to enable interceptors without beans.xml you can write a CDI extension:

package my.package;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterTypeDiscovery;
import javax.enterprise.inject.spi.Extension;

public class MyCdiExtension implements Extension {

    public void observeAfterTypeDiscovery(@Observes AfterTypeDiscovery afterTypeDiscovery) {
        afterTypeDiscovery.getInterceptors().add(SomeExternalInterceptor.class);
    }
}

Add file resources/META-INF/services/javax.enterprise.inject.spi.Extension with content:

my.package.MyCdiExtension
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!