imansible trovare Factory: javax.faces.context.FacesContextFactory

Ho notato che quando provo a configurare la mia webapp JSF 2 in esecuzione su jetty, ho questo errore:

java.lang.IllegalStateException: l’applicazione non è stata inizializzata correttamente all’avvio, non è stata trovata Factory: javax.faces.context.FacesContextFactory

che è facilmente risolvibile aggiungendo questo al mio web.xml

  com.sun.faces.config.ConfigureListener   

Ho provato a cercare una spiegazione dettagliata ma in futile ..

jetty-maven-plugin: 8.0.3.v20111011: run + jdk 7 + eclipse indigo

    E qui c’è la mia dipendenza da esperti:

       org.glassfish javax.faces 2.1.3 compile   

    Ecco il mio web.xml:

       Basic Setup Web Application  Faces Servlet javax.faces.webapp.FacesServlet 1   Faces Servlet /faces/*   faces/index.xhtml    com.sun.faces.config.ConfigureListener    javax.faces.PROJECT_STAGE Development   

    ed ecco l’output del plugin jetty:

     [INFO] <<< jetty-maven-plugin:8.0.3.v20111011:run (default-cli) @ BasicSetup <<< [INFO] [INFO] --- jetty-maven-plugin:8.0.3.v20111011:run (default-cli) @ BasicSetup --- [INFO] Configuring Jetty for project: BasicSetup Maven Webapp [INFO] webAppSourceDirectory C:\Users\albert\workspace\BasicSetup\src\main\webapp does not exist. Defaulting to C:\Users\albert\workspace\BasicSetup\src\main\webapp [INFO] Reload Mechanic: automatic [INFO] Classes = C:\Users\albert\workspace\BasicSetup\target\classes [INFO] Context path = /basicSetup [INFO] Tmp directory = C:\Users\albert\workspace\BasicSetup\target\tmp [INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml [INFO] Web overrides = none [INFO] web.xml file = file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/WEB-INF/web.xml [INFO] Webapp directory = C:\Users\albert\workspace\BasicSetup\src\main\webapp 2011-10-25 14:24:51.091:INFO:oejs.Server:jetty-8.0.3.v20111011 2011-10-25 14:24:51.334:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one. 2011-10-25 14:24:52.108:INFO:oejsh.ContextHandler:started omjpJettyWebAppContext{/basicSetup,[file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/, jar:file:/C:/Users/albert/.m2/repository/org/glassfish/javax.faces/2.1.3/javax.faces-2.1.3.jar!/META-INF/resources/]},file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/ 2011-10-25 14:24:52.108:INFO:oejsh.ContextHandler:started omjpJettyWebAppContext{/basicSetup,[file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/, jar:file:/C:/Users/albert/.m2/repository/org/glassfish/javax.faces/2.1.3/javax.faces-2.1.3.jar!/META-INF/resources/]},file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/ 2011-10-25 14:24:52.108:INFO:oejsh.ContextHandler:started omjpJettyWebAppContext{/basicSetup,[file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/, jar:file:/C:/Users/albert/.m2/repository/org/glassfish/javax.faces/2.1.3/javax.faces-2.1.3.jar!/META-INF/resources/]},file:/C:/Users/albert/workspace/BasicSetup/src/main/webapp/ 2011-10-25 14:24:52.149:WARN:/basicSetup:unavailable java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:967) at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:316) at javax.faces.webapp.FacesServlet.init(FacesServlet.java:302) at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:456) at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:276) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:779) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:255) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1212) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:610) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:453) at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:256) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224) at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) at org.eclipse.jetty.server.Server.doStart(Server.java:262) at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:65) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59) at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:511) at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:364) at org.mortbay.jetty.plugin.JettyRunMojo.execute(JettyRunMojo.java:514) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:107) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59) at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156) at org.apache.maven.cli.MavenCli.execute(MavenCli.java:534) at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196) at org.apache.maven.cli.MavenCli.main(MavenCli.java:141) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290) at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409) at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352) [INFO] Started Jetty Server 2011-10-25 14:24:52.165:INFO:oejs.AbstractConnector:Started [email protected]:8080 STARTING [INFO] Starting scanner at interval of 10 seconds. 

    Qualche idea ?

    Questo listener è da quando JSF 1.x dovrebbe essere automaticamente registrato dal file di definizione della libreria di tag jsf_core.tld . Puoi trovarlo nella cartella /META-INF del file JAR di implementazione JSF. In caso di Mojarra 2.1.3 (che sembra utilizzare secondo i registri), l’ascoltatore viene registrato come segue dalla riga 80 e su:

        com.sun.faces.config.ConfigureListener  

    Tuttavia, apparentemente questo non è stato raccolto correttamente da Jetty. Ho anche letto da qualche parte che quando FacesServlet è stato inizializzato prima che il file TLD sia stato elaborato, otterrete anche esattamente questa eccezione. Forse sta succedendo a Jetty. Per escludere l’uno e l’altro, provare a rimuovere la voce modo che venga caricata solo sulla prima richiesta HTTP concreta, molto tempo dopo che il TLD è stato elaborato. In ogni caso, la registrazione esplicita del listener in web.xml dovrebbe in effetti risolverla.

    Inoltre, poiché JSF 2.x, oltre al file TLD, si suppone che il listener venga automaticamente registrato da un’implementazione ServletContainerInitializer nel file JAR per risolvere il problema di un bug di Glassfish 3. In Mojarra 2.x questa è la class com.sun.faces.config.FacesInitializer che ha le seguenti righe che iniziano alla riga 131:

     // The following line is temporary until we can solve an ordering // issue in V3. Right now the JSP container looks for a mapping // of the FacesServlet in the web.xml. If it's not present, then // it assumes that the application isn't a faces application. In this // case the JSP container will not register the ConfigureListener // definition from our TLD nor will it parse cause or JSP TLDs to // be parsed. servletContext.addListener(com.sun.faces.config.ConfigureListener.class); 

    Funziona solo in contenitori Servlet 3.0, come Tomcat 7, Glassfish 3, Jetty 8 (presumibilmente!), Ecc. Sembra che tu stia utilizzando Jetty 8.0 che dovrebbe quindi soddisfare Servlet 3.0, ma il tuo web.xml è dichiarato conforms Servlet 2.5, quindi il contenitore verrà eseguito in modalità ripiego Servlet 2.5. Modifica del tuo web.xml per conformarsi Servlet 3.0 dovrebbe triggersre questo inizializzatore.

    Ancora una soluzione: ho ricevuto questo errore dopo aver creato file java al volo con CXF da wsdl.

     JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance(); Client client = factory.createClient(wsdlURL, serviceName); 

    CXF inserisce il proprio ClassLoader (istanza di URLClassLoader) nel classloader di Thread. Funziona normalmente, finché il thread dell’utente non entra in FactoryFinder di JSF, che viene memorizzato nella cache dal ClassLoader come chiave. Poiché ClassLoader è stato modificato, crea un nuovo FactoryManager, che non può essere inizializzato, poiché gli elenchi delle istanze di implementazione vengono rimossi all’avvio del FactoryManager originale. Per questo motivo, le classi di implementazione non vengono trovate, quindi viene generata l’IllegalStateException.

    Soluzione: eseguire il backup del ClassLoader originale prima di createClient di CXF, salvare URLClassLoader in una variabile e ripristinare il ClassLoader originale nella Thread. Quando si desidera accedere a una class dynamic da CXF, cercarla tramite URLClassLoader inserendo una variabile.