首页 > 解决方案 > 迁移到 JSF 2.3,MyFaces 初始化问题

问题描述

我正在升级一个由“common”和“myapp”两个项目组成的应用程序。我现在将其升级到JSF 2.3 (MyFaces)Primefaces 7,但我不知道如何克服初始化失败。

我应该注意到还有很多其他的变化。这两个项目都已成功升级到OpenJDK 11Tomcat 9和使用Maven。并且随着对 JSF 2.3 的更改,不再支持托管 bean,而是支持 JAVA 的 CDI API,不方便的是,在 JAVA 11 中默认不再支持它。所以我引入了OpenWebBeans 2.0DeltaSpike 1.9.1。尽管存在所有这些移动部件,但该应用程序正在运行到更新 JSF 的地步,所以我相信问题就在那里。

在这一点上,我有两种可能的配置,都失败了。使用一种配置,我收到此错误:

[main] ERROR [Catalina].[localhost].[/myapp] - StandardWrapper.Throwable
No Factories configured for this Application. This happens if the faces-initialization 
does not work at all - make sure that you properly include all configuration settings
necessary for a basic faces application and that all the necessary libs are included. Also 
check the logging output of your web application and your container for any exceptions!
If you did that and find nothing, the mistake might be due to the fact that you use some
special web-containers which do not support registering context-listeners via TLD files 
and a context listener is not setup in your web.xml.
A typical config looks like this;
<listener>
  <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>

所以,明显的解决方案是添加监听器,但后来我得到了这个:

[main] ERROR myfaces.config.FacesConfigurator - No ManagedBeanDestroyerListener instance
found, thus @PreDestroy methods won't get called in every case. This instance needs to be
published before configuration is started.

这似乎是一个排序问题,在 Faces 配置开始之前StartupServletContextListener没有发布。ManagedBeanDestroyerListener但是,在我的研究中,我读到它StartupServletContextListener不应该是必需的,因为它是从 JSF jar 中的 TLD 自动加载的。

任何人都明白这里发生了什么?我怎样才能克服这个?

以下是我的 pom 和 web.xml 的精简版本:

常见/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.company</groupId>
    <artifactId>common</artifactId>
    <version>2.1.8</version>

    <properties>
       <dependency.locations.enabled>false</dependency.locations.enabled>   
       <owb.version>2.0.12</owb.version>
       <deltaspike.version>1.9.1</deltaspike.version>      
    </properties>

    <repositories>
        <repository>
            <id>local_repository</id>
            <url>https://server.company.com/repository</url>
        </repository>
    </repositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.deltaspike.distribution</groupId>
                <artifactId>distributions-bom</artifactId>
                <version>${deltaspike.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-api</artifactId>
            <version>2.3.5</version>
        </dependency>

        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-impl</artifactId>
            <version>2.3.5</version>
        </dependency>

        <dependency>
            <groupId>org.apache.myfaces.core.internal</groupId>
            <artifactId>myfaces-impl-shared-public</artifactId>
            <version>2.3.5</version>
        </dependency>

        <!-- Stored in local maven repository -->
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>7.0</version>
        </dependency>

        <!-- Stored in local maven repository -->
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>all-themes</artifactId>
            <version>1.0.10</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>4.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-core</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
            <version>1.0.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>catalina</artifactId>
            <version>6.0.53</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-util</artifactId>
            <version>9.0.12</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-impl</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-spec</artifactId>
            <version>1.2.5</version>
        </dependency>

        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-bundle</artifactId>
            <version>2.3.5</version>
        </dependency>


        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>2.0.SP1</version>
        </dependency>

        <!-- OpenWebBeans - implements CDI Container -->
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-spi</artifactId>
            <version>${owb.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-impl</artifactId>
            <version>${owb.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-web</artifactId>
            <version>${owb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-jsf</artifactId>
            <version>${owb.version}</version>
        </dependency>

        <!-- DeltaSpike - manages CDI container -->
        <dependency>
            <groupId>org.apache.deltaspike.core</groupId>
            <artifactId>deltaspike-core-api</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.deltaspike.modules</groupId>
            <artifactId>deltaspike-jsf-module-api</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.deltaspike.core</groupId>
            <artifactId>deltaspike-core-impl</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.deltaspike.modules</groupId>
            <artifactId>deltaspike-jsf-module-impl</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--  CDI Control API -->
        <dependency>
            <groupId>org.apache.deltaspike.cdictrl</groupId>
            <artifactId>deltaspike-cdictrl-api</artifactId>
            <scope>compile</scope>
        </dependency>       

        <!--  CDI Control for OpenWebBeans -->
        <dependency>
            <groupId>org.apache.deltaspike.cdictrl</groupId>
            <artifactId>deltaspike-cdictrl-owb</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.deltaspike.modules</groupId>
            <artifactId>deltaspike-servlet-module-api</artifactId>
            <version>${deltaspike.version}</version>
            <scope>compile</scope>
        </dependency>       
        <dependency>
            <groupId>org.apache.deltaspike.modules</groupId>
            <artifactId>deltaspike-servlet-module-impl</artifactId>
            <version>${deltaspike.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src</sourceDirectory>
        <testSourceDirectory>test</testSourceDirectory>
        <resources>
            ...
        </resources>

        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <debug>${debugBuild}</debug>
                    <debuglevel>lines,vars,source</debuglevel> 
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
                ...
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                ...
            </plugin>

        </plugins>
    </build>    
</project>

我的应用程序/pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.company</groupId>
  <artifactId>myapp</artifactId>
  <version>0.1.0</version>
  <packaging>war</packaging>

  <properties>
       <commonVersion>2.1.8</commonVersion>
       <dependency.locations.enabled>false</dependency.locations.enabled>
  </properties>

  <dependencies>
    <dependency>
        <groupId>com.company</groupId>
        <artifactId>common</artifactId>
        <version>${commonVersion}</version>
    </dependency>
  </dependencies>

  <build>
    <sourceDirectory>src</sourceDirectory>
    <testSourceDirectory>test</testSourceDirectory>
    <resources>
      <resource>
        <directory>resources</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>

    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.1</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
        </configuration>
      </plugin>

      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <source>11</source>
          <target>11</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

common/META-INF/web-fragment.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-fragment metadata-complete="true" version="3.0"
              xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd">

    <name>common</name>

    <filter>
        <filter-name>ResourceFilter</filter-name>
        <filter-class>com.company.common.web.ResourceFilter</filter-class>
        <async-supported>true</async-supported>
    </filter>
    <filter-mapping>
        <filter-name>ResourceFilter</filter-name>
        <url-pattern>/javax.faces.resource/*</url-pattern>
        <url-pattern>/resources/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
        <init-param>
            <param-name>thresholdSize</param-name>
            <param-value>100000000</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>


    <listener>
        <display-name>httpSessionListener</display-name>
        <listener-class>com.company.common.usersession.UserSessionListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
      <param-name>org.apache.myfaces.annotation.USE_CDI_FOR_ANNOTATION_SCANNING</param-name>
      <param-value>true</param-value>
    </context-param>   
    <context-param>
        <param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
        <param-value>65535</param-value>
    </context-param>
    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>mytheme</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
        <param-value>20</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION</param-name>
        <param-value>2</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES</param-name>
        <param-value>31536000000</param-value> <!-- 1 year -->
    </context-param>
    <context-param>
        <param-name>primefaces.UPLOADER</param-name>
        <param-value>commons</param-value>
    </context-param>
</web-fragment>

myapp/WEB-INF/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"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   version="3.0">

  <absolute-ordering>
    <name>common</name> <!-- Get the common web fragment -->
  </absolute-ordering>

    <!-- 
        AppApplicationContextListenerhas to happen before WebBeansConfigurationListener
        so that the application context (e.g. app name, db connections) is set before
        web beans are scanned  
    -->
    <listener>
        <listener-class>com.company.application.app.AppApplicationContextListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class>
    </listener>

<!-- INCLUDE ??? -->
    <listener>
      <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
    </listener>

  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>



  <!-- Faces Servlet can't be moved into common's web-fragment.xml due to a bug in Apache's MyFaces -->
  <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>
<!-- or possibly:                         -->
<!--     <url-pattern>*.jsf</url-pattern> -->
  </servlet-mapping>

</web-app>

标签: mavenjsfmyfacesjsf-2.3

解决方案


[2020 年 1 月 3 日更新:我正在更新此条目以删除一些不好的建议。具体来说,重命名faces-config.xmlstandard-faces-config.xml阻止 MyFaces 正确初始化。]

我已经解决了我的大部分问题。有几个组件干扰了我的项目。


马文:

作为 Eclipse 的新手,这是一个痛苦的教训,我必须确保重新运行 Maven 构建并清理我的部署文件夹,这样我才能真正执行我的更改。在那之后,这里是我发现并修复的要点。

  • 显然,在处理第二个引用项目时,m2e 无法正确处理测试 jar。所以一个<dependency>使用<classifier>tests</classifier>or的块<type>test-jar</type>不起作用,但是下面会将测试源复制到依赖项目进行编译。(请务必根据需要编辑该<source>值,并在 Eclipse 中运行的 Maven 中启用 m2e 配置文件)
    <profiles>
      <profile>
        <id>m2e</id>
        <activation>
          <property>
            <name>m2e.version</name>
          </property>
        </activation>
        <build>
          <plugins>
            <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>build-helper-maven-plugin</artifactId>
              <version>3.0.0</version>
              <executions>
                <execution>
                  <id>include-test-source-eclipse</id>
                  <phase>generate-test-sources</phase>
                  <goals>
                    <goal>add-test-source</goal>
                  </goals>
                  <configuration>
                    <sources>
                      <source>../common/test/java</source>
                    </sources>
                  </configuration>
                </execution>
              </executions>
            </plugin>
          </plugins>
        </build>
      </profile>
    </profiles>
  • org.apache.myfaces.core:myfaces-bundle只是org.apache.myfaces.core:myfaces-apiorg.apache.myfaces.core:myfaces-impl组合成一个包。包括一个/或但不包括两者。(我收到的建议是使用单独的包,而不是捆绑包。)

  • 尽管我在 Apache 读到过,但 DeltaSpike 并没有让启动 CDI (OpenWebBeans) 变得更容易,所以我删除了它。似乎注册 OpenWebBeans 启动监听器就足够了(见下文)。

  • cobertura ( ) 不支持 JDK 11 org.codehaus.mojo:cobertura-maven-plugin。人们推荐 JaCoCo #67 代替它。


web.xml

在从托管 bean 切换到 CDI 时,web.xml 中需要以下几行。托管 bean 虽然已弃用,但仍默认启用。

<context-param>
    <param-name>org.apache.myfaces.SUPPORT_MANAGED_BEANS</param-name>
    <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>org.apache.myfaces.annotation.USE_CDI_FOR_ANNOTATION_SCANNING</param-name>
    <param-value>true</param-value>
</context-param> 

以下是我目前正在使用的听众(及其顺序):

<listener>
    <listener-class>com.company.application.app.MyApplicationContextListener</listener-class>
</listener>

<listener>
    <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
  <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>


面孔-config.xml:

不要做我做的事。 不要创建standard-faces-config.xml文件。这会阻止 Faces 正确初始化。 [没有找到通用项目的文件,重命名它似乎可以解决问题。faces-config.xml坏主意。] 这个错误导致 MyFaces 无法创建<action-listener>org.primefaces.application.DialogActionListener</action-listener>也是。


所以,总结...

  • 似乎 MyFaces StartupServletContextListener 确实需要包含在 web.xml 中。
  • 奇怪的“未发布 Bean Destroyer”错误似乎是由于切换到 CDI 但未禁用 MyFaces 的托管 Bean 支持。
  • standard-faces-config.xml由于我的文件阻止了正确初始化,导致多次启动问题。


[@tandraschko:非常感谢您的帮助和关注,因为我正在努力解决这个问题!]


推荐阅读