Wildfly和Wildfly-swarm从战争部署和自定义模块注入CDI bean

时间:2017-09-14 17:09:55

标签: java wildfly cdi wildfly-swarm

在试验Wildfly-swarm的过程中,我遇到了一个关于豆类注射的奇怪情况。

我有一个非常简单的bean,或多或少是这样的:

@ApplicationScoped
public class FooServiceImpl implements FooService {
    Foo delegate;
    @PostConstruct public void init() {
        delegate = .....;
    }

    public Foo getFoo() {
        return delegate;
    }
}

如果我在战争部署中直接将它捆绑在一个罐子里,一切正常并且符合预期。但是,我需要将此实现的内部部分与应用程序完全隔离,为什么我将服务api及其实现打包到单独的jboss模块中。

这些模块被添加到swarm uberJar中,我的应用程序通过MANIFEST Dependencies条目依赖于它们。现在,一切似乎都运行正常,FooService bean被注入我的应用程序servlet / rest资源,但是没有调用init()方法。

我无法弄清楚这里发生了什么。这就像bean解析过程无法识别@ApplicationScope注释。它可以有两种不同的类加载器吗?

更新

我启用了跟踪,对我而言,看起来Weld将FooImpl类视为ApplicationScoped,即向正在创建的代理添加LifecycleMixin.lifecycle_mixin_$$_postConstruct()

2017-09-14 23:11:34,315 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001538: Created context instance for bean Managed Bean [class com.xxx.FooImpl] with qualifiers [@Any @Default] identified as WELD%ManagedBean%test.war|test.war.external.file:/tmp/nestedjarloader2449602760983533131.tmp/META-INF/beans.xml|com.xxx.FooImpl|null|false
2017-09-14 23:11:34,315 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001542: Retrieving/generating proxy class com.xxx.FooImpl$Proxy$_$$_WeldClientProxy
2017-09-14 23:11:34,315 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public void com.xxx.FooImpl.registerMessageHandler(com.xxx.MessageHandler)
2017-09-14 23:11:34,315 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public void com.xxx.FooImpl.registerListeners(java.util.EventListener[])
2017-09-14 23:11:34,316 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public void com.xxx.FooImpl.send(com.xxx.MessageHandler,com.xxx.Message) throws java.io.IOException
2017-09-14 23:11:34,316 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public void com.xxx.FooImpl.init()
2017-09-14 23:11:34,316 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public java.lang.String java.lang.Object.toString()
2017-09-14 23:11:34,316 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public abstract void org.jboss.weld.interceptor.proxy.LifecycleMixin.lifecycle_mixin_$$_postConstruct()
2017-09-14 23:11:34,316 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001541: Adding method to proxy: public abstract void org.jboss.weld.interceptor.proxy.LifecycleMixin.lifecycle_mixin_$$_preDestroy()
2017-09-14 23:11:34,317 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001543: Created Proxy class of type class com.xxx.FooImpl$Proxy$_$$_WeldClientProxy supporting interfaces [interface com.xxx.FooService, interface java.io.Serializable, interface org.jboss.weld.interceptor.proxy.LifecycleMixin, interface org.jboss.weld.interceptor.util.proxy.TargetInstanceProxy, interface org.jboss.weld.bean.proxy.ProxyObject]
2017-09-14 23:11:34,317 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001506: Created new client proxy of type class com.xxx.FooImpl$Proxy$_$$_WeldClientProxy for bean Managed Bean [class com.xxx.FooImpl] with qualifiers [@Any @Default] with ID WELD%ManagedBean%test.war|test.war.external.file:/tmp/nestedjarloader2449602760983533131.tmp/META-INF/beans.xml|com.xxx.FooImpl|null|false
2017-09-14 23:11:34,318 TRACE [org.jboss.weld.Bean] (ServerService Thread Pool -- 12) WELD-001507: Located client proxy of type class com.xxx.FooImpl$Proxy$_$$_WeldClientProxy for bean Managed Bean [class com.xxx.FooImpl] with qualifiers [@Any @Default]

没有调用postconstruct拦截器 - 为什么?神秘感加深了!

更新2

在vanilla wildfly上测试过,行为相同,如果bean位于模块中,则不调用@PostConstruct方法。

1 个答案:

答案 0 :(得分:0)

我认为这个问题与the one in JBoss forums有关联,但如果他们不是......

可能的原因是您的单独模块未声明对<module name="javax.annotation.api"/> 的依赖,@PostConstruct来自undefined。添加它,应该解决问题。 这似乎是预期的JVM行为(as explained in this SO question) - 如果你错过了运行时的依赖,程序仍然会执行但忽略注释。

作为解决此问题的方法(如果上述方法无效或您无法做到) - 您可以使用初始化方法。这是CDI创建对象后立即执行的方法。