не удалось найти фабрику: javax.faces.context.FacesContextFactory

#servlets #jsf-2 #jetty #maven-jetty-plugin

#сервлеты #jsf-2 #причал #maven-jetty-plugin

Вопрос:

Я заметил, что при попытке настроить мое веб-приложение JSF 2, работающее на jetty, у меня возникает эта ошибка :

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>
 

и вот результат работы плагина 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:UsersalbertworkspaceBasicSetupsrcmainwebapp does not exist. Defaulting to C:UsersalbertworkspaceBasicSetupsrcmainwebapp
[INFO] Reload Mechanic: automatic
[INFO] Classes = C:UsersalbertworkspaceBasicSetuptargetclasses
[INFO] Context path = /basicSetup
[INFO] Tmp directory = C:UsersalbertworkspaceBasicSetuptargettmp
[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:UsersalbertworkspaceBasicSetupsrcmainwebapp
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.
 

Есть мысли?

Комментарии:

1. есть ли у вас зависимость от mojarra?

2. @Bozho: я предполагаю, что да, поскольку простое добавление тега прослушивателя заставляет его работать

Ответ №1:

Этот прослушиватель, поскольку предполагается, что JSF 1.x автоматически регистрируется jsf_core.tld файлом определения библиотеки тегов. Вы можете найти его в /META-INF папке JAR-файла реализации JSF. В случае 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 is инициализируется до обработки файла TLD, вы также получите именно это исключение. Возможно, это происходит в Jetty. Чтобы исключить одно и другое, попробуйте удалить <load-on-startup> запись, чтобы она загружалась только при первом конкретном HTTP-запросе, намного позже обработки TLD. В любом случае явная регистрация слушателя в web.xml действительно должна решить эту проблему.

Кроме того, начиная с JSF 2.x, в дополнение к файлу TLD, предполагается, что прослушиватель также автоматически регистрируется ServletContainerInitializer реализацией в файле JAR, чтобы обойти ошибку 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 должно вызвать этот инициализатор.

Комментарии:

1. Я пробовал как удалить загрузку при запуске, так и переключиться на 3.0, но все с тем же сбоем. Я думаю, что пришло время снова перейти на tomcat7, чтобы все проверить. Я подумывал использовать jetty для его быстрого развертывания с помощью exploded war с помощью плагина maven. Позже я найду другие способы, чтобы они работали в tomcat7. Спасибо!

2. После включения функции Jetty 8 «аннотации» я обнаружил, что Jetty использует версию Jasper от GlassFish, которая намеренно пропускает конфигурационный список Mojarra, определенный в файле TLD. Кроме того, инициализатор Mojarra FacesInitializer не будет регистрировать Mojarra ConfigureListener, если FacesServlet определен в web.xml . Я заставил его работать, зарегистрировав пользовательский инициализатор ServletContainerInitializer. Дополнительные сведения см. в разделе Развертывание портлетов JSF на Jetty и FACES-1668 .

3. @Нил: Хорошая находка! Это действительно объясняет поведение. Джетти лучше бы позаимствовал Джаспер у Tomcat или разработал свой собственный.

4. @BalusC: Спасибо за добрые слова Бауке. Я также обнаружил, что добавление jsf-api.jar и jsf-impl.jar to $JETTY_HOME/lib/jsp — это способ добавления Mojarra в глобальный путь к классу Jetty, который заставит Jetty автоматически зарегистрировать ConfigureListener. Обратите внимание, что функция «аннотации» должна быть включена.

Ответ №2:

Еще одно решение: я получил эту ошибку после того, как создал java-файлы «на лету» с помощью CXF из wsdl.

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

CXF помещает свой собственный загрузчик классов (экземпляр URLClassLoader) в загрузчик классов потока. Это работает обычным способом, пока поток пользователя не попадет в FactoryFinder JSF, который кэшируется загрузчиком классов в качестве ключа.
Поскольку загрузчик классов изменился, он создает новый FactoryManager, который не может быть инициализирован, поскольку списки экземпляров реализации удаляются при инициализации исходного FactoryManager. Из-за этого классы реализации не найдены, следовательно, генерируется исключение IllegalStateException.

Решение: создайте резервную копию исходного загрузчика классов перед createClient CXF, сохраните URLClassLoader в переменной и верните исходный загрузчик классов в поток. Если вы хотите получить доступ к динамическому классу из CXF, выполните поиск по URLClassLoader, который вы ввели в переменную.

Ответ №3:

У меня была эта проблема в моем проекте, в который были включены два файла jar в папку lib, теперь моя проблема решена.Спасибо

com.sun.faces:jsf-api: 2.2.9 com.sun.faces:jsf-impl:2.2.9