could not find Factory: javax.faces.context.FacesContextFactory

bertie picture bertie · Oct 25, 2011 · Viewed 58.8k times · Source

I notice that when trying to setup my JSF 2 webapp running on jetty, i have this error :

java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory

which is easily solved by adding this to my web.xml

<listener>
    <listener-class>
        com.sun.faces.config.ConfigureListener
    </listener-class>
</listener>

I've tried searching for a detailed explanation but in futile ..

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

And here's my maven dependency :

<dependencies>
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.faces</artifactId>
        <version>2.1.3</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

Here's my web.xml :

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <display-name>Basic Setup Web Application</display-name>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
    <listener>
        <listener-class>
            com.sun.faces.config.ConfigureListener
        </listener-class>
    </listener>
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
</web-app>

and here's the output of the jetty plugin :

[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 o.m.j.p.JettyWebAppContext{/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 o.m.j.p.JettyWebAppContext{/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 o.m.j.p.JettyWebAppContext{/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.

Any thoughts ?

Answer

BalusC picture BalusC · Oct 25, 2011

This listener is since JSF 1.x supposed to be automatically registered by the jsf_core.tld tag library definition file. You can find it in the /META-INF folder of the JSF implementation JAR file. In case of Mojarra 2.1.3 (which you seem to be using according the logs), the listener is registered as follows from line 80 and on:

<!-- ============== Configuration Listener ============== -->

<!--
      This ServletContextListener initializes the runtime environment
      of the JavaServer Faces Reference Implementation when a web
      application including it is initialized by the container.
-->
<listener>
   <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>      

However, this is apparently not been picked up properly by Jetty. I've also read somewhere that when the FacesServlet is been initialized before the TLD file is been processed, then you will also get exactly this exception. Perhaps this is happening in Jetty. To exclude the one and other, try to remove the <load-on-startup> entry so that it will be loaded only on first concrete HTTP request, far after the TLD is been processed. In any way, explicitly registering the listener in web.xml should indeed solve it.

Further, since JSF 2.x, in addition to the TLD file, the listener is also supposed to be automatically registered by a ServletContainerInitializer implementation in the JAR file in order to workaround a Glassfish 3 bug. In Mojarra 2.x this is the com.sun.faces.config.FacesInitializer class which has the following lines starting at line 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);

This works in Servlet 3.0 containers only, such as Tomcat 7, Glassfish 3, Jetty 8 (supposedly!), etc. You seem to be using Jetty 8.0 which should thus comply Servlet 3.0, but your web.xml is declared conform Servlet 2.5, so the container will run in Servlet 2.5 fallback modus. Changing your web.xml to conform Servlet 3.0 should trigger this initializer.