找不到工厂:javax.faces.context.FacesContextFactory
Posted
技术标签:
【中文标题】找不到工厂:javax.faces.context.FacesContextFactory【英文标题】:could not find Factory: javax.faces.context.FacesContextFactory 【发布时间】:2011-12-14 17:19:46 【问题描述】:我注意到,当我尝试设置在码头上运行的 JSF 2 webapp 时,我遇到了这个错误:
java.lang.IllegalStateException:应用程序不正确 启动时初始化,找不到工厂: javax.faces.context.FacesContextFactory
通过将其添加到我的 web.xml 中很容易解决
<listener>
<listener-class>
com.sun.faces.config.ConfigureListener
</listener-class>
</listener>
我试过寻找详细的解释,但徒劳无功..
jetty-maven-plugin:8.0.3.v20111011:run + jdk 7 + eclipse indigo
这是我的 Maven 依赖项:
<dependencies>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.1.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
这是我的 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>
这是码头插件的输出:
[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 SelectChannelConnector@0.0.0.0:8080 STARTING
[INFO] Starting scanner at interval of 10 seconds.
有什么想法吗?
【问题讨论】:
你有 mojarra 依赖吗? @Bozho:我认为是的,因为只需添加侦听器标签就可以了 【参考方案1】:我的项目遇到了这个问题,其中包含两个 jar 文件到 lib 文件夹,现在我的问题解决了。谢谢
com.sun.faces:jsf-api:2.2.9 com.sun.faces:jsf-impl:2.2.9
【讨论】:
【参考方案2】:还有一个解决办法: 在我使用 wsdl 中的 CXF 动态创建 java 文件后出现此错误。
JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
Client client = factory.createClient(wsdlURL, serviceName);
CXF 将它自己的 ClassLoader(URLClassLoader 的实例)放到 Thread 的类加载器中。它以正常方式工作,直到用户的线程进入 JSF 的 FactoryFinder,它由 ClassLoader 作为键缓存。 因为 ClassLoader 发生了变化,所以创建了一个新的 FactoryManager,无法初始化,因为在原来的 FactoryManager 启动时,实现实例列表被移除了。因此,找不到实现类,因此抛出 IllegalStateException。
解决方法:在CXF的createClient之前备份原来的ClassLoader,把URLClassLoader保存在一个变量中,然后把原来的ClassLoader放回Thread。 当您想从 CXF 访问动态类时,请通过您放入变量的 URLClassLoader 搜索它。
【讨论】:
【参考方案3】:这个监听器自JSF 1.x 起应该由jsf_core.tld
标记库定义文件自动注册。您可以在 JSF 实现 JAR 文件的 /META-INF
文件夹中找到它。对于 Mojarra 2.1.3(您似乎正在根据日志使用),侦听器从第 80 行开始注册如下:
<!-- ============== 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>
然而,这显然没有被 Jetty 正确接收。我还在某处读到,当FacesServlet
被初始化在 TLD 文件被处理之前,你也会得到这个异常。也许这发生在码头。要排除一个和另一个,请尝试删除 <load-on-startup>
条目,以便仅在处理 TLD 之后的第一个具体 HTTP 请求时加载它。无论如何,在web.xml
中显式注册监听器确实应该解决它。
此外,从 JSF 2.x 开始,除了 TLD 文件之外,还应该通过 JAR 文件中的 ServletContainerInitializer
实现自动注册侦听器,以解决 Glassfish 3 的错误。在 Mojarra 2.x 中,这是 com.sun.faces.config.FacesInitializer
类,从第 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);
这仅适用于 Servlet 3.0 容器,例如 Tomcat 7、Glassfish 3、Jetty 8(据说!)等。您似乎使用的是 Jetty 8.0,因此应该符合 Servlet 3.0,但您的 web.xml
被声明为符合Servlet 2.5,因此容器将以 Servlet 2.5 后备方式运行。更改您的 web.xml
以符合 Servlet 3.0 应该会触发此初始化程序。
【讨论】:
我已尝试删除启动时加载并切换到 3.0,但仍然失败。我认为是时候再次迁移到 tomcat7 来测试了。我正在考虑使用码头,因为它能够通过 maven 插件的爆炸式战争快速部署。稍后我会为这些在 tomcat7 中工作找到其他方法。谢谢! 启用 Jetty 8“注释”功能后,我发现 Jetty 使用了 GlassFish 中的 Jasper 版本,该版本有意跳过 TLD 文件中定义的 Mojarra ConfigureListener。此外,如果 FacesServlet 在 web.xml 中定义,Mojarra FacesInitializer 将不会注册 Mojarra ConfigureListener。我通过注册一个自定义的 ServletContainerInitializer 让它工作。有关详细信息,请参阅Deploying JSF Portlets on Jetty 和 FACES-1668。 @Neil:很好的发现!这确实解释了这种行为。 Jetty 最好从 Tomcat 借用 Jasper 或者自己开发。 @BalusC:感谢 Bauke 的客气话。我还发现将 jsf-api.jar 和 jsf-impl.jar 添加到 $JETTY_HOME/lib/jsp 是一种将 Mojarra 添加到 Jetty 全局类路径的方法,这将导致 Jetty 自动注册 ConfigureListener。请注意,必须启用“注释”功能。以上是关于找不到工厂:javax.faces.context.FacesContextFactory的主要内容,如果未能解决你的问题,请参考以下文章
java.lang.IllegalStateException:找不到工厂 javax.faces.context.FacesContextFactory 的备份
java.lang.IllegalStateException:找不到工厂javax.faces.context.FacesContextFactory的备份
javax.faces.context.FacesContextFactory 使用 JSF 应用程序嵌入 Undertow 时出现异常
Grails 插件项目中的 jsf2“...backup for factory javax.faces.context.FacesContextFactory”出错