WebSphere Liberty 24.0.0.5中Mojarra与MyFaces冲突问题求助
在IBM WebSphere Liberty Server 24.0.0.5上运行JSF 2.3 + Spring MVC应用时,启动阶段抛出如下错误:
The MyFaces JSF Implementation is selected for SampleApp but a Sun RI ConfigureListener is also registered.
实际项目中使用的是Mojarra(GlassFish JSF实现),并未引入MyFaces相关依赖。
相关配置文件
server.xml
<server description="new server"> <featureManager> <feature>jsf-2.3</feature> <feature>cdi-2.0</feature> <feature>jdbc-4.2</feature> <feature>servlet-4.0</feature> <feature>websocket-1.1</feature> </featureManager> <httpEndpoint httpPort="9081" httpsPort="9443" id="defaultHttpEndpoint"/> <applicationManager autoExpand="true"/> <webApplication contextRoot="SampleApp" id="SampleApp" location="D:\workspace\SampleApp\target\SampleApp-0.0.1-SNAPSHOT.war" name="SampleApp"> <classloader apiTypeVisibility="spec, ibm-api, third-party"/> </webApplication> </server>
web.xml
<listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <servlet> <servlet-name>FacesServlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>/faces/*</url-pattern> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>
pom.xml 核心依赖
<dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.3.9</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-core</artifactId> <version>3.1.8.Final</version> </dependency>
已执行的排查操作
- 用
mvn dependency:tree检查依赖树,未发现MyFaces相关依赖 - 移除了WEB-INF/lib中的
javax.faces-api-2.2.jar
但问题仍存在,同时伴随空指针异常:
Stack Dump = java.lang.NullPointerException at com.sun.faces.config.InitFacesContext.cleanupInitMaps(InitFacesContext.java:312) at com.sun.faces.config.InitFacesContext.<init>(InitFacesContext.java:116) at com.sun.faces.config.FacesInitializer.onStartup(FacesInitializer.java:148) at com.ibm.ws.webcontainer.webapp.WebApp.initializeServletContainerInitializers(WebApp.java:2577) at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:1052) at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:6722) at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost.startWebApp(DynamicVirtualHost.java:484) at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost.startWebApplication(DynamicVirtualHost.java:479) at com.ibm.ws.webcontainer.osgi.WebContainer.startWebApplication(WebContainer.java:1208) at com.ibm.ws.webcontainer.osgi.WebContainer.access$100(WebContainer.java:113) at com.ibm.ws.webcontainer.osgi.WebContainer$3.run(WebContainer.java:996) at com.ibm.ws.threading.internal.ExecutorServiceImpl$RunnableWrapper.run(ExecutorServiceImpl.java:280) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
- 为何Liberty会检测到MyFaces,而我明确使用的是Mojarra?
- 是否可以强制Liberty仅使用Mojarra,忽略MyFaces?
- 应如何配置server.xml以避免JSF冲突?
1. 问题原因
WebSphere Liberty自带的jsf-2.3特性默认采用MyFaces作为JSF实现。即使你在pom.xml中声明Mojarra为provided scope,Liberty启动时仍会优先加载内置的MyFaces。同时你在web.xml中手动注册了Mojarra的ConfigureListener,导致Liberty检测到两种不同JSF实现的初始化逻辑,触发冲突错误。
2. 强制使用Mojarra的可行性
完全可以强制Liberty使用Mojarra,核心思路是排除Liberty内置的MyFaces实现,让应用优先加载自身的Mojarra库。
3. server.xml及相关配置调整
步骤1:修改server.xml
移除jsf-2.3特性(避免加载内置MyFaces),并调整类加载器为parentLast(让应用优先使用自身打包的库):
<server description="new server"> <featureManager> <!-- 移除jsf-2.3特性,避免内置MyFaces --> <feature>cdi-2.0</feature> <feature>jdbc-4.2</feature> <feature>servlet-4.0</feature> <feature>websocket-1.1</feature> </featureManager> <httpEndpoint httpPort="9081" httpsPort="9443" id="defaultHttpEndpoint"/> <applicationManager autoExpand="true"/> <webApplication contextRoot="SampleApp" id="SampleApp" location="D:\workspace\SampleApp\target\SampleApp-0.0.1-SNAPSHOT.war" name="SampleApp"> <!-- parentLast让应用库优先于容器库加载 --> <classloader apiTypeVisibility="spec, ibm-api, third-party" delegation="parentLast"/> </webApplication> </server>
步骤2:调整pom.xml的Mojarra依赖
将Mojarra的scope从provided改为compile,让Mojarra库打包到war的WEB-INF/lib中:
<dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.3.9</version> <!-- 改为compile,将Mojarra打包到应用中 --> <scope>compile</scope> </dependency>
步骤3:修改web.xml
移除手动注册的ConfigureListener,因为Mojarra会自动初始化该监听器,手动注册会引发冲突:
<!-- 移除以下监听器配置 --> <!-- <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> --> <servlet> <servlet-name>FacesServlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>/faces/*</url-pattern> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>
原理说明
- 移除
jsf-2.3特性:彻底避免Liberty加载内置的MyFaces实现 parentLast类加载策略:让应用优先使用自身打包的Mojarra,而不是容器级的库- 移除手动监听器:防止Mojarra的自动初始化流程与手动注册的监听器冲突,同时消除Liberty对混合JSF实现的检测
内容的提问来源于stack exchange,提问作者Osman Canbaz

