1

I am trying to migrate from JSF 2.1 to 2.3/Servlet 4/ Tomcat 9 but I have some trouble whith CDI configuration. I followed this guide from BalusC to enable CDI on Tomcat 9 (in my case) but I still get this exception when starting my app:

com.sun.faces.config.ConfigurationException: Factory 'javax.faces.lifecycle.ClientWindowFactory' was not configured properly.
    at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:357)
    at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:243)
    at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:443)
    at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:237)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4641)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5109)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1737)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:457)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:406)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.faces.FacesException: Unable to find CDI BeanManager
    at com.sun.faces.application.ApplicationImpl.isJsf23(ApplicationImpl.java:2714)
    at com.sun.faces.application.ApplicationImpl.addELResolver(ApplicationImpl.java:549)
    at javax.faces.application.ApplicationWrapper.addELResolver(ApplicationWrapper.java:611)
    at javax.faces.application.ApplicationWrapper.addELResolver(ApplicationWrapper.java:611)
    at org.jboss.weld.environment.servlet.jsf.WeldApplication.<init>(WeldApplication.java:72)
    at org.jboss.weld.environment.servlet.jsf.WeldApplicationFactory.getApplication(WeldApplicationFactory.java:46)
    at com.sun.faces.application.InjectionApplicationFactory.getApplication(InjectionApplicationFactory.java:88)
    at com.sun.faces.config.InitFacesContext.getApplication(InitFacesContext.java:153)
    at com.sun.faces.lifecycle.ClientWindowFactoryImpl.<init>(ClientWindowFactoryImpl.java:63)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at javax.faces.FactoryFinderInstance.getImplGivenPreviousImpl(FactoryFinderInstance.java:391)
    at javax.faces.FactoryFinderInstance.getImplementationInstance(FactoryFinderInstance.java:255)
    at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:529)
    at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:292)
    at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:354)
    ... 48 more

Note that before following the guide, I had the same exception but it was thrown from another class (com.sun.faces.el.ELUtils.java method tryAddCDIELResolver(FacesCompositeELResolver composite)) and after the guide it's thrown from com.sun.faces.application.ApplicationImpl.java method private boolean isJsf23(). My librairies version are:

    <icefaces-ace.version>3.2.0</icefaces-ace.version>
    <javax.jms-api.version>2.0.1</javax.jms-api.version>
    <el-api.version>2.2</el-api.version>
    <javax.el-api.version>3.0.0</javax.el-api.version>
    <jstl.version>1.2</jstl.version>
    <javax.faces-api.version>2.3</javax.faces-api.version><!--JSF API-->
    <javax.faces.version>2.3.8</javax.faces.version> <!--Mojarra-->
    <javax.ws.rs-api.version>2.1.1</javax.ws.rs-api.version>
    <javax.servlet-api.version>4.0.1</javax.servlet-api.version>
    <javax.servlet.jsp.jstl-api.version>1.2.2</javax.servlet.jsp.jstl-api.version>
    <javaee-web-api.version>8.0</javaee-web-api.version>
    <weld-servlet-shaded.version>3.0.5.Final</weld-servlet-shaded.version>

Could someone tell me what am I doing wrong? Thanks a lot.

EDIT

The piece of code which trying to find the BeanManager is this one:

 public static BeanManager getCdiBeanManager(FacesContext facesContext) {
    BeanManager result = null;

    if (facesContext != null && facesContext.getAttributes().containsKey(RIConstants.CDI_BEAN_MANAGER)) {
        result = (BeanManager) facesContext.getAttributes().get(RIConstants.CDI_BEAN_MANAGER);
    } else if (facesContext != null && facesContext.getExternalContext().getApplicationMap().containsKey(RIConstants.CDI_BEAN_MANAGER)) {
        result = (BeanManager) facesContext.getExternalContext().getApplicationMap().get(RIConstants.CDI_BEAN_MANAGER);
    } else {
        try {
            InitialContext initialContext = new InitialContext();
            result = (BeanManager) initialContext.lookup("java:comp/BeanManager");
        }
        catch (NamingException ne) {
            try {
                InitialContext initialContext = new InitialContext();
                result = (BeanManager) initialContext.lookup("java:comp/env/BeanManager");
            }
            catch (NamingException ne2) {
            }
        }

        if (result == null && facesContext != null) {
            Map<String, Object> applicationMap = facesContext.getExternalContext().getApplicationMap();
            result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.javax.enterprise.inject.spi.BeanManager");
        }

        if (result != null && facesContext != null) {
            facesContext.getAttributes().put(RIConstants.CDI_BEAN_MANAGER, result);
            facesContext.getExternalContext().getApplicationMap().put(RIConstants.CDI_BEAN_MANAGER, result);
        }
    }

    return result;
}

I added some breakpoints to check the result' and it is reallynullbut thefacesContext` isn't.

akuma8
  • 4,160
  • 5
  • 46
  • 82
  • Explicit mention of EL / Servlet / JSP API versions in your pom.xml is slightly scary. Normally you never need to worry about them because Tomcat already ships this stuff out the box. So having them explicitly specified implies that you're manually bundling them along with the webapp and thus inducing duplicate library conflicts when deployed. Related/possibledupe: https://stackoverflow.com/q/8081234 – BalusC Nov 22 '18 at 14:59
  • @BalusC I added the `provided` scope to EL/Servlet dependencies. – akuma8 Nov 22 '18 at 15:12
  • 1
    @BalusC i downgraded the faces-config.xml version to 2.2, the problem goes away but I think it's not the good solution. – akuma8 Nov 22 '18 at 16:40
  • Suggestion: use TomEE... saves you a lot of manual configuration. – Kukeltje Nov 22 '18 at 17:45
  • 1
    @akuma8 are you sure you did not miss out step (3) "Create a (empty) `/WEB-INF/beans.xml` file"? Is your `/META-INF/context.xml` correctly deployed and you made sure it is actually processed by Tomcat? – Selaron Nov 22 '18 at 20:32
  • About the context.xml I am sure it is processed by Tomcat. beans.xml is under /webapp/META-INF/ To make some tests I’d move it under /WEB-INF/ but didn’t change anything – akuma8 Nov 22 '18 at 20:46
  • @Selaron The file beans.xml was created by IntelliJ so when you say ´empty’, should I remove the added when file was created – akuma8 Nov 22 '18 at 20:58
  • I added the method which searches the `beanManager` – akuma8 Nov 23 '18 at 11:58
  • @BalusC Do you think the old version of `icefaces` could cause this problem? – akuma8 Nov 23 '18 at 13:55
  • It could, IceFaces are built on top of JSF from what I gathered. Therefore having newer JSF might mean IceFaces are incompatible. – Siliarus Nov 26 '18 at 09:34
  • 1
    I had facing the same problem for hours, I solved it just adding an empty (really empty) beans.xml file under WEB-INF. @BalusC, what's the reason to add this empty file? Thanks very much for your guide http://balusc.omnifaces.org/2013/10/how-to-install-cdi-in-tomcat.html – Néstor Almeida Feb 28 '19 at 09:28
  • @NéstorAlmeida: It tells server to enable CDI. – BalusC Feb 28 '19 at 09:52
  • CDI should be enabled by default to avoid developers losing time for this kind of issue. JSF isn't really user friendly. – akuma8 Feb 28 '19 at 10:44
  • @BalusC Following your guide I added the com.sun.faces.expressionFactory and javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_‌​A‌​S_NULL context param on Tomcat 8.5.35 but I still getting the error: java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at com.sun.faces.util.ByteArrayGuardAESCTR.decrypt(ByteArrayGuardAESCTR.java:157) I'm using EL 3.0.1-b11 Oracle's implementation. – Néstor Almeida Feb 28 '19 at 10:49
  • @akuma8: This is only the case when you use Java EE 8 or newer. In older Java EE versions or in customized Tomcat-based server stacks you may need to explicitly enable it. – BalusC Feb 28 '19 at 14:22

0 Answers0