maven - 迁移到 JSF 2.3,MyFaces 初始化问题
问题描述
我正在升级一个由“common”和“myapp”两个项目组成的应用程序。我现在将其升级到JSF 2.3 (MyFaces)和Primefaces 7,但我不知道如何克服初始化失败。
我应该注意到还有很多其他的变化。这两个项目都已成功升级到OpenJDK 11、Tomcat 9和使用Maven。并且随着对 JSF 2.3 的更改,不再支持托管 bean,而是支持 JAVA 的 CDI API,不方便的是,在 JAVA 11 中默认不再支持它。所以我引入了OpenWebBeans 2.0和DeltaSpike 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>
解决方案
[2020 年 1 月 3 日更新:我正在更新此条目以删除一些不好的建议。具体来说,重命名faces-config.xml
以standard-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-api
和org.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:非常感谢您的帮助和关注,因为我正在努力解决这个问题!]
推荐阅读
- python - Pandas groupby 值并获取最大日期和最小日期的值
- latex - “缺少插入的 $”,即使我使用的是 \begin{equation}
- python - 如何从 pandas read_csv 获取值/行
- google-apps-script - 在一行的第一个空白单元格中设置时间戳
- authentication - Slim 4 - 如果身份验证失败,则具有自定义响应的身份验证中间件
- excel - 打开访问,导入模块并运行宏
- matlab - 如何在 MATLAB 中编写开始时间约束?
- jquery - 为什么通过 jQuery Ajax 将 Plaid 链接结果发布到 ASP.NET MVC 控制器时缺少属性数据?
- kotlin - 通用 Kotlin 工厂到 DRY 构造函数参数
- authentication - 如何通过 keycloak 向 github 企业中的每个用户添加主电子邮件?