2010-10-29 68 views
14

我的Java EE 6应用程序由打包在ear文件中的war和ejb模块组成。我使用CDI进行DI(即,我在两个模块中都有一个beans.xml文件)。我想使用war模块中ejb模块中定义的日志拦截器。我已经启用拦截器在EJB的beans.xml中:CDI:跨不同模块/ bean档案使用拦截器

<beans> 
    <interceptors> 
     <class>com.test.interceptor.LoggingInterceptor</class> 
    </interceptors> 
</beans> 

这对于被注释与EJB模块在拦截器类唯一的工作。战争模块中的类不会被拦截(虽然它们也使用拦截器进行注释)。我认为解决方案应该是在战争拦截器中启用拦截器(如上所述)。

严重:但是,应用程序不能与下面的消息被部署异常而加载的应用程序:WELD-001417启用拦截器类类com.test.interceptor.LoggingInterceptor既不是通过便携式扩展注释@Interceptor也不登记

我LoggingInterceptor看起来是这样的:

@Log 
@Interceptor 
public class LoggingInterceptor { 
    private static final Logger logger = Logger.getLogger(LoggingInterceptor.class.getName()); 

    static { 
     logger.setLevel(Level.ALL); 
    } 

    @AroundInvoke 
    public Object logMethod(InvocationContext ctx) throws Exception { 
     logger.log(Level.FINE, "ENTRY {0} {1}", 
       new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() }); 
     long startTime = System.nanoTime(); 
     try { 
      return ctx.proceed(); 
     } finally { 
      long diffTime = System.nanoTime() - startTime; 
      logger.log(Level.FINE, "RETURN {0} {1}", 
       new Object[]{ ctx.getTarget().getClass().getName(), ctx.getMethod().getName() }); 
      logger.log(Level.FINE, "{0} took {1} ms", new Object[]{ ctx.getMethod(), 
        TimeUnit.MILLISECONDS.convert(diffTime, TimeUnit.NANOSECONDS)}); 
     } 
    } 

} 

而且拦截器绑定:

@InterceptorBinding 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE}) 
public @interface Log {} 

如何为两个模块使用拦截器?

+0

您是否找到解决此问题的解决方案?看到它会很有趣。 – mik 2012-05-28 07:28:19

+1

@milk不,我没有。我将所有模块合并到一个war模块中,这是自Java EE 6. – Theo 2012-05-29 10:17:56

+0

哇,这是可能的,谢谢你清楚地阐明了这一点。我遇到了完全相同的问题,并将它整合到一个模块中解决了它。有时候J2EE只是试图让事情变得艰难...... – JoshC13 2015-11-06 02:59:17

回答

1

我想知道你的WAR是否缺乏classloader可视性到你的ejb-jar中?我认为理想情况下,299个拦截器将在他们自己的jar中,对EJB和web模块都可见,并在其beans.xml中启用。

5

为时已晚,但如果有人仍然有这个问题。 两个模块应该由相同的类加载器加载,以便在不同模块间使用拦截器,至少在WebSphere 8b2中是如此。 在WebSphere中,可以在管理控制台中切换此设置:应用程序>应用程序类型> WebSphere企业应用程序> [您的应用程序名称]>类加载和更新检测> WAR类加载器策略=用于应用程序的单个类加载器。
拦截器必须在beans.xml中仅启用一次。

+0

正确答案永远不会迟到,thx :-) – 2012-06-06 09:04:49

+2

即使在WebSphere中允许(并且常见),这也不建议用于JEE应用程序。类装载机是分开的,这是有原因的。 – 2015-07-27 02:49:12

0

我在JBoss AS 6.0/6.1(每晚构建)上遇到了同样的问题,并通过disabling separate classloaders(选项1)修复了它,但要非常小心。类加载器的分离并没有推出没有理由,那么显然有前进道路上的新问题......

This是JIRA报告,请投上一票:-)

8

J2EE 7规范说(reference):

您在beans.xml的文件中指定的拦截器只适用于 类在同一个档案。使用@priority批注指定 拦截全局对于由多个的 模块

这种解决方案具有的独立于供应商的优点的应用程序。

一个例子:

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

我可以证实这个工程在WildFly 10.1.0.Final上 – schnatterer 2017-08-08 09:56:31

0

我与我的logging interceptor在JBoss 7有完全相同的问题,并通过固定它覆盖完整的拦截器的水罐里的应用程序。

<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> 

您仍然必须在应用程序的breans.xml中激活拦截器。

不好,但它的工作原理。在Java EE 7中,它通过将拦截器注释为@Priority而无需激活。