从Wildfly10/Java9迁到Wildfly24/Java16后WAR启动找不到javax.faces.application.ApplicationFactory
异常信息
11:37:44,290 SEVERE [javax.faces] (ServerService Thread Pool -- 89) Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?
11:37:44,292 SEVERE [javax.faces] (ServerService Thread Pool -- 89) Application was not properly initialized at startup, could not find Factory: javax.faces.application.ApplicationFactory. Attempting to find backup.
11:37:44,293 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 89) MSC000001: Failed to start service jboss.deployment.unit."myApplication.war".undertow-deployment: org.jboss.msc.service.StartException in service jboss.deployment.unit."myApplication.war".undertow-deployment: java.lang.RuntimeException: java.lang.IllegalStateException: Could not find backup for factory javax.faces.application.ApplicationFactory.
...
Caused by: java.lang.IllegalStateException: Could not find backup for factory javax.faces.application.ApplicationFactory.
根因分析
异常的核心原因是JSF实现冲突:
Wildfly 24默认内置了Mojarra作为官方JSF实现,而你的WAR包中自行打包了Apache MyFaces的JSF实现,两个实现在初始化时抢占ApplicationFactory等核心工厂类的注册,导致容器找不到可用的工厂实例。
可落地解决方案
- 方案1:使用容器自带JSF实现
如果不需要自定义MyFaces版本,直接在打包配置中将所有org.apache.myfaces相关依赖的scope设置为provided,确保WAR包的WEB-INF/lib目录下不存在MyFaces相关jar包,直接使用Wildfly内置的Mojarra实现即可。 - 方案2:强制使用自定义MyFaces实现
如果业务必须依赖特定版本的MyFaces,需要在WEB-INF目录下新增jboss-deployment-structure.xml配置,主动排除容器内置的JSF模块:
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <exclusions> <!-- 排除容器自带的JSF API和实现模块 --> <module name="javax.faces.api" /> <module name="org.jboss.as.jsf" /> <module name="com.sun.jsf-impl" /> </exclusions> </deployment> </jboss-deployment-structure>
- 方案3:版本兼容性校验
- 确认你使用的MyFaces版本同时支持Java 16和Wildfly 24对应的JSF 3.0 API规范,低于适配版本的话需要升级MyFaces
- 检查
WEB-INF/faces-config.xml的头部版本声明,和你使用的JSF实现版本保持一致 - Java 16对反射权限做了严格限制,如果后续出现反射访问异常,可在Wildfly启动参数中添加
--add-opens java.base/java.lang=ALL-UNNAMED等对应权限开放配置
内容的提问来源于stack exchange,提问作者siddy

