omn​​ifaces 在 openwebbeans 1.5.0 之前开始?

omnifaces starting before openwebbeans 1.5.0?

我正在使用 Java 8 / Tomcat 8 / OpenWebBeans 1.5.0 / MyFaces 2.2.8 / DeltaSpike 1.3.0。

因为我想使用 openwebbeans-tomcat7 模块,所以我将以下 jar 放在 tomcat/lib 中:

我也喜欢使用很棒的 omnifaces 库。因此,我的 webapp 在 WEB-INF/lib

中具有 omnifaces 作为依赖项

我使用的两个版本 1.8.1 和 2.0 的 CDI 存在问题。 在我看来,omnifaces 在 openwebbeans 之前启动,因此找不到 CDI。

在 1.8.1 中,这个问题引发了一个异常,但它是非阻塞的,因为 CDI 在这个版本中不是强制性的。在 2.0 中,它会阻止 webapp 启动,因为 omnifaces 2.0 有 CDI 作为要求。

对于 1.8.1,日志是:

21-May-2015 23:07:17.678 INFO [main] org.apache.catalina.core.StandardService.startInternal Démarrage du service Catalina
21-May-2015 23:07:17.678 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.0.20
21-May-2015 23:07:17.690 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDescriptor Déploiement du descripteur de configuration /opt/apache-tomcat-8.0.20/conf/Catalina/localhost/apps#presences#edit.xml
21-May-2015 23:07:18.914 INFO [localhost-startStop-1] org.apache.catalina.core.StandardContext.addApplicationListener The listener "org.apache.webbeans.servlet.WebBeansConfigurationListener" is already configured for this context. The duplicate definition has been ignored.
21-May-2015 23:07:19.199 SEVERE [localhost-startStop-1] org.apache.webbeans.web.tomcat7.TomcatInstanceManager.inject Error is occured while injecting the OpenWebBeans dependencies for instance org.omnifaces.cdi.eager.EagerBeansRequestListener@7dd5f8b3
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.omnifaces.cdi.eager.BeansInstantiator] is not found with the qualifiers 
Qualifiers: [@javax.enterprise.inject.Default()]
for injection into Field Injection Point, field name :  eagerBeansRepository, Bean Owner : [null]
    at org.apache.webbeans.util.InjectionExceptionUtil.throwUnsatisfiedResolutionException(InjectionExceptionUtil.java:65)
    at org.apache.webbeans.container.InjectionResolver.getInjectionPointBean(InjectionResolver.java:271)
    at org.apache.webbeans.inject.AbstractInjectable.inject(AbstractInjectable.java:82)
    at org.apache.webbeans.inject.InjectableField.doInjection(InjectableField.java:65)
    at org.apache.webbeans.portable.InjectionTargetImpl.injectFields(InjectionTargetImpl.java:220)
    at org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:206)
    at org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:196)
    at org.apache.webbeans.inject.OWBInjector.inject(OWBInjector.java:57)
    at org.apache.webbeans.web.tomcat7.TomcatUtil.inject(TomcatUtil.java:40)
    at org.apache.webbeans.web.tomcat7.TomcatInstanceManager.inject(TomcatInstanceManager.java:122)
    at org.apache.webbeans.web.tomcat7.TomcatInstanceManager.newInstance(TomcatInstanceManager.java:88)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4650)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5162)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:581)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1683)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

21-May-2015 23:07:19.201 SEVERE [localhost-startStop-1] org.apache.webbeans.web.tomcat7.TomcatInstanceManager.inject Error is occured while injecting the OpenWebBeans dependencies for instance org.omnifaces.cdi.eager.EagerBeansSessionListener@26cf68af
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.omnifaces.cdi.eager.BeansInstantiator] is not found with the qualifiers 
Qualifiers: [@javax.enterprise.inject.Default()]
for injection into Field Injection Point, field name :  eagerBeansRepository, Bean Owner : [null]
    at org.apache.webbeans.util.InjectionExceptionUtil.throwUnsatisfiedResolutionException(InjectionExceptionUtil.java:65)
    at org.apache.webbeans.container.InjectionResolver.getInjectionPointBean(InjectionResolver.java:271)
    at org.apache.webbeans.inject.AbstractInjectable.inject(AbstractInjectable.java:82)
    at org.apache.webbeans.inject.InjectableField.doInjection(InjectableField.java:65)
    at org.apache.webbeans.portable.InjectionTargetImpl.injectFields(InjectionTargetImpl.java:220)
    at org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:206)
    at org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:196)
    at org.apache.webbeans.inject.OWBInjector.inject(OWBInjector.java:57)
    at org.apache.webbeans.web.tomcat7.TomcatUtil.inject(TomcatUtil.java:40)
    at org.apache.webbeans.web.tomcat7.TomcatInstanceManager.inject(TomcatInstanceManager.java:122)
    at org.apache.webbeans.web.tomcat7.TomcatInstanceManager.newInstance(TomcatInstanceManager.java:88)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4650)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5162)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:581)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1683)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

21-May-2015 23:07:19.201 SEVERE [localhost-startStop-1] org.apache.webbeans.web.tomcat7.TomcatInstanceManager.inject Error is occured while injecting the OpenWebBeans dependencies for instance org.omnifaces.cdi.eager.EagerBeansSessionListener@26cf68af
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.omnifaces.cdi.eager.BeansInstantiator] is not found with the qualifiers 
Qualifiers: [@javax.enterprise.inject.Default()]
for injection into Field Injection Point, field name :  eagerBeansRepository, Bean Owner : [null]
    at org.apache.webbeans.util.InjectionExceptionUtil.throwUnsatisfiedResolutionException(InjectionExceptionUtil.java:65)
    at org.apache.webbeans.container.InjectionResolver.getInjectionPointBean(InjectionResolver.java:271)
    at org.apache.webbeans.inject.AbstractInjectable.inject(AbstractInjectable.java:82)
    at org.apache.webbeans.inject.InjectableField.doInjection(InjectableField.java:65)
    at org.apache.webbeans.portable.InjectionTargetImpl.injectFields(InjectionTargetImpl.java:220)
    at org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:206)
    at org.apache.webbeans.portable.InjectionTargetImpl.inject(InjectionTargetImpl.java:196)
    at org.apache.webbeans.inject.OWBInjector.inject(OWBInjector.java:57)
    at org.apache.webbeans.web.tomcat7.TomcatUtil.inject(TomcatUtil.java:40)
    at org.apache.webbeans.web.tomcat7.TomcatInstanceManager.inject(TomcatInstanceManager.java:122)
    at org.apache.webbeans.web.tomcat7.TomcatInstanceManager.newInstance(TomcatInstanceManager.java:88)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4650)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5162)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:581)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1683)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

21-May-2015 23:07:19.240 INFO [localhost-startStop-1] org.apache.webbeans.lifecycle.AbstractLifeCycle.bootstrapApplication OpenWebBeans Container is starting...
21-May-2015 23:07:19.242 INFO [localhost-startStop-1] org.apache.webbeans.plugins.PluginLoader.startUp Adding OpenWebBeansPlugin : [TomcatWebPlugin]
21-May-2015 23:07:19.242 INFO [localhost-startStop-1] org.apache.webbeans.plugins.PluginLoader.startUp Adding OpenWebBeansPlugin : [OpenWebBeansJsfPlugin]
21-May-2015 23:07:19.246 INFO [localhost-startStop-1] org.apache.webbeans.corespi.scanner.AbstractMetaDataDiscovery.addWebBeansXmlLocation added beans archive URL: file:/mnt/ssd/home_bis/dev/git/presences/presences_modules/editpresences/target/edit%23%231.0-SNAPSHOT/WEB-INF/classes/META-INF/beans.xml
21-May-2015 23:07:19.252 INFO [localhost-startStop-1] org.apache.webbeans.corespi.scanner.AbstractMetaDataDiscovery.addWebBeansXmlLocation added beans archive URL: jar:file:/mnt/ssd/home_bis/dev/git/presences/presences_modules/editpresences/target/edit%23%231.0-SNAPSHOT/

对于 2.0,它是:

21-May-2015 23:32:12.076 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.0.20
21-May-2015 23:32:12.090 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDescriptor Déploiement du descripteur de configuration /opt/apache-tomcat-8.0.20/conf/Catalina/localhost/apps#presences#edit.xml
21-May-2015 23:32:13.389 INFO [localhost-startStop-1] org.apache.catalina.core.StandardContext.addApplicationListener The listener "org.apache.webbeans.servlet.WebBeansConfigurationListener" is already configured for this context. The duplicate definition has been ignore
d.
21-May-2015 23:32:13.641 INFO [localhost-startStop-1] org.omnifaces.ApplicationInitializer.logOmniFacesVersion Using OmniFaces version 2.0
21-May-2015 23:32:13.644 SEVERE [localhost-startStop-1] org.omnifaces.ApplicationInitializer.checkCDIAvailable 
████████████████████████████████████████████████████████████████████████████████
▌                         ▐█     ▐                                             ▐
▌    ▄                  ▄█▓█▌    ▐ OmniFaces failed to initialize!             ▐
▌   ▐██▄               ▄▓░░▓▓    ▐                                             ▐
▌   ▐█░██▓            ▓▓░░░▓▌    ▐ This OmniFaces version requires CDI, but    ▐
▌   ▐█▌░▓██          █▓░░░░▓     ▐ none was found on this environment.         ▐
▌    ▓█▌░░▓█▄███████▄███▓░▓█     ▐                                             ▐
▌    ▓██▌░▓██░░░░░░░░░░▓█░▓▌     ▐ OmniFaces 2.x requires a minimum of JSF 2.2.▐
▌     ▓█████░░░░░░░░░░░░▓██      ▐ Since this JSF version, the JSF managed bean▐
▌     ▓██▓░░░░░░░░░░░░░░░▓█      ▐ facility @ManagedBean is semi-official      ▐
▌     ▐█▓░░░░░░█▓░░▓█░░░░▓█▌     ▐ deprecated in favour of CDI. JSF 2.2 users  ▐
▌     ▓█▌░▓█▓▓██▓░█▓▓▓▓▓░▓█▌     ▐ are strongly encouraged to move to CDI.     ▐
▌     ▓▓░▓██████▓░▓███▓▓▌░█▓     ▐                                             ▐
▌    ▐▓▓░█▄▐▓▌█▓░░▓█▐▓▌▄▓░██     ▐ OmniFaces goes a step further by making CDI ▐
▌    ▓█▓░▓█▄▄▄█▓░░▓█▄▄▄█▓░██▌    ▐ a REQUIRED dependency next to JSF 2.2. This ▐
▌    ▓█▌░▓█████▓░░░▓███▓▀░▓█▓    ▐ not only ensures that your web application  ▐
▌   ▐▓█░░░▀▓██▀░░░░░ ▀▓▀░░▓█▓    ▐ represents the state of art, but this also  ▐
▌   ▓██░░░░░░░░▀▄▄▄▄▀░░░░░░▓▓    ▐ makes for us easier to develop OmniFaces,   ▐
▌   ▓█▌░░░░░░░░░░▐▌░░░░░░░░▓▓▌   ▐ without the need for all sorts of hacks in  ▐
▌   ▓█░░░░░░░░░▄▀▀▀▀▄░░░░░░░█▓   ▐ in order to get OmniFaces to deploy on      ▐
▌  ▐█▌░░░░░░░░▀░░░░░░▀░░░░░░█▓▌  ▐ environments without CDI.                   ▐
▌  ▓█░░░░░░░░░░░░░░░░░░░░░░░██▓  ▐                                             ▐
▌  ▓█░░░░░░░░░░░░░░░░░░░░░░░▓█▓  ▐ You have 3 options:                         ▐
██████████████████████████████████ 1. Downgrade to OmniFaces 1.x.              ▐
█░▀░░░░▀█▀░░░░░░▀█░░░░░░▀█▀░░░░░▀█ 2. Install CDI in this environment.         ▐
█░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█ 3. Switch to a CDI capable environment.     ▐
█░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█                                             ▐
█░░▐█▌░░█░░░██░░░█░░░░░░▄█░░▄▄▄▄▄█ For additional instructions, check          ▐
█░░▐█▌░░█░░░██░░░█░░░░████░░░░░░░█ http://omnifaces.org/cdi                    ▐
█░░░█░░░█▄░░░░░░▄█░░░░████▄░░░░░▄█                                             ▐
████████████████████████████████████████████████████████████████████████████████
21-May-2015 23:32:13.645 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal Error during ServletContainerInitializer processing
javax.servlet.ServletException: java.lang.ExceptionInInitializerError
    at org.omnifaces.ApplicationInitializer.checkCDIAvailable(ApplicationInitializer.java:101)
    at org.omnifaces.ApplicationInitializer.onStartup(ApplicationInitializer.java:50)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5151)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:581)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1683)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ExceptionInInitializerError
    at org.omnifaces.ApplicationInitializer.checkCDIAvailable(ApplicationInitializer.java:64)
    ... 13 more
Caused by: java.lang.IllegalStateException: CDI BeanManager instance is not available in JNDI.
    at org.omnifaces.config.BeanManager.<init>(BeanManager.java:106)
    at org.omnifaces.config.BeanManager.<clinit>(BeanManager.java:49)
    ... 14 more

21-May-2015 23:32:13.651 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal Erreur de démarrage du contexte [/apps/presences/edit] suite aux erreurs précédentes
21-May-2015 23:32:13.657 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of configuration descriptor /opt/apache-tomcat-8.0.20/conf/Catalina/localhost/apps#presences#edit.xml has finished in 1 566 ms
21-May-2015 23:32:13.659 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Déploiement de l'archive /opt/apache-tomcat-8.0.20/webapps/edit##1.0-SNAPSHOT.war de l'application web
21-May-2015 23:32:14.649 INFO [localhost-startStop-1] org.apache.catalina.core.StandardContext.addApplicationListener The listener "org.apache.webbeans.servlet.WebBeansConfigurationListener" is already configured for this context. The duplicate definition has been ignored.
21-May-2015 23:32:14.767 INFO [localhost-startStop-1] org.apache.webbeans.lifecycle.AbstractLifeCycle.bootstrapApplication OpenWebBeans Container is starting...
21-May-2015 23:32:14.773 INFO [localhost-startStop-1] org.apache.webbeans.corespi.scanner.AbstractMetaDataDiscovery.addWebBeansXmlLocation added beans archive URL: file:/opt/apache-tomcat-8.0.20/webapps/edit%23%231.0-SNAPSHOT/WEB-INF/classes/META-INF/beans.xml
21-May-2015 23:32:14.779 INFO [localhost-startStop-1] org.apache.webbeans.corespi.scanner.AbstractMetaDataDiscovery.addWebBeansXmlLocation added beans archive URL: jar:file:/opt/apache-tomcat-8.0.20/webapps/edit%23%231.0-SNAPSHOT/WEB-INF/lib/deltaspike-core-impl-1.3.0.jar!/ME

只有 omnifaces 才会出现此问题。 OWB 在我的网络应用程序中工作。

启动顺序仍然非常不稳定,具体取决于容器(例如,参见 http://javaeesquad.blogspot.fr/2015/03/getting-notified-when-java-ee.html)。

我看到 OmniFaces 已经处理了 Glassfish 的特殊情况:

public class ApplicationInitializer 实现 ServletContainerInitializer {

    // Constants ------------------------------------------------------------------------------------------------------

    private static final Logger logger = Logger.getLogger(ApplicationInitializer.class.getName());

    // Actions --------------------------------------------------------------------------------------------------------

    @Override
    public void onStartup(Set<Class<?>> c, ServletContext servletContext) throws ServletException {
            logOmniFacesVersion();
            checkCDIAvailable(servletContext);
            FacesViews.registerFilter(servletContext);
    }

    private void logOmniFacesVersion() {
            logger.info("Using OmniFaces version " + getClass().getPackage().getSpecificationVersion());
    }

    private void checkCDIAvailable(ServletContext servletContext) throws ServletException {
            if (Hacks.isCDIAvailableInGlassFish(servletContext)) {
                    return; // Okay. Don't proceed, because GF4 fails to scan JNDI during servlet container initialization.
            }

            try {
                    BeanManager.INSTANCE.toString();
            }
            catch (Throwable e) {
                    logger.severe(""
                            + "\n████████████████████████████████████████████████████████████████████████████████"
                            + "\n▌                         ▐█     ▐                                             ▐"
                            + "\n▌    ▄                  ▄█▓█▌    ▐ OmniFaces failed to initialize!             ▐"
                            + "\n▌   ▐██▄               ▄▓░░▓▓    ▐                                             ▐"
                            + "\n▌   ▐█░██▓            ▓▓░░░▓▌    ▐ This OmniFaces version requires CDI, but    ▐"
                            + "\n▌   ▐█▌░▓██          █▓░░░░▓     ▐ none was found on this environment.         ▐"
                            + "\n▌    ▓█▌░░▓█▄███████▄███▓░▓█     ▐                                             ▐"
                            + "\n▌    ▓██▌░▓██░░░░░░░░░░▓█░▓▌     ▐ OmniFaces 2.x requires a minimum of JSF 2.2.▐"
                            + "\n▌     ▓█████░░░░░░░░░░░░▓██      ▐ Since this JSF version, the JSF managed bean▐"

并在 class 技巧中:

    // GlassFish related ----------------------------------------------------------------------------------------------

    /**
     * Returns <code>true</code> if CDI is available in GlassFish.
     * @param servletContext The involved servlet context.
     * @return <code>true</code> if CDI is available in GlassFish.
     */
    public static boolean isCDIAvailableInGlassFish(ServletContext servletContext) {
            return servletContext.getAttribute("org.glassfish.jsp.beanManagerELResolver") instanceof ELResolver;
    }

OWB 可以有这样的特例吗? 测试是否设置了属性对我来说足够公平了。

或者是否可以推迟 omnifaces 实例化?

最后,为什么不等待CDI通知,方法如:

public class CDIStartup {

    public void postConstruct(@Observes @Initialized(ApplicationScoped.class) Object o) {
        // CDI Ready    }
}

OmniFaces 需要更改检查代码,因为它是不可移植的。 CDI 规范没有定义 BeanManager 或任何上下文需要在 ServletContainerInitializer 中可用。这在很大程度上取决于目标环境和集成场景,因此非常不可移植。 与它完美运行的旧版本相比,这也是一种倒退。

将其移至 ServletContextListener,或将其设为警告并完成。