PrimeFaces调用Javax.faces 2.2方法,但2.1在WebSphere 9中的路径中



我使用custom JSF提供商(设置为默认为was)中部署了一个在9中的应用程序。罐子与一个孤立的类加载器共享LIB。一切都很好,直到我们从Richfaces迁移到Primefaces。我们使用javax.faces 2.1.29,但由于某种原因,PrimeFaces似乎检测到我们正在使用2.2,并且正在调用仅在2.2中存在的方法(GetPassThroughAttributes)。查看游戏中的堆栈版本似乎正确,因此我不确定为什么要进行2.2方法调用。有人遇到了吗?

> 3/19/19 17:19:07:671 CDT] 00000091 ServletWrappe E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception root cause Faces Servlet: javax.servlet.ServletException: javax/faces/component/UIComponent.getPassThroughAttributes(Z)Ljava/util/Map; (loaded from file:/opt/IBM/WebSphere/AppServer_2/trunkLib/javax.faces-2.1.29-10.jar by 
com.ibm.ws.classloader.CompoundClassLoader@abecddd0[library:trunkLib]
   Local ClassPath: /opt/IBM/WebSphere/AppServer_2/trunkLib/javax.faces-2.1.29-10.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/httpclient-4.5.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/httpcore-4.4.4.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/commons-codec-1.11.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/hk2-api-2.4.0-b34.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/hk2-locator-2.4.0-b34.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/hk2-utils-2.4.0-b34.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/javax.annotation-api-1.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/jaxrs-ri-2.22.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/jersey-guava-2.22.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/validation-api-1.1.0.Final.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/classes:/opt/IBM/WebSphere/AppServer_2/trunkLib/javassist-3.23.1-GA.jar
   Parent: com.ibm.ws.classloader.ProtectionClassLoader@a5c5ece8

> Caused by: java.lang.NoSuchMethodError: javax/faces/component/UIComponent.getPassThroughAttributes(Z)Ljava/util/Map; (loaded from file:/opt/IBM/WebSphere/AppServer_2/trunkLib/javax.faces-2.1.29-10.jar by 
com.ibm.ws.classloader.CompoundClassLoader@abecddd0[library:trunkLib]
   Local ClassPath: /opt/IBM/WebSphere/AppServer_2/trunkLib/javax.faces-2.1.29-10.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/httpclient-4.5.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/httpcore-4.4.4.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/commons-codec-1.11.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/hk2-api-2.4.0-b34.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/hk2-locator-2.4.0-b34.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/hk2-utils-2.4.0-b34.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/javax.annotation-api-1.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/jaxrs-ri-2.22.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/jersey-guava-2.22.2.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/validation-api-1.1.0.Final.jar:/opt/IBM/WebSphere/AppServer_2/trunkLib/classes:/opt/IBM/WebSphere/AppServer_2/trunkLib/javassist-3.23.1-GA.jar
   Parent: com.ibm.ws.classloader.ProtectionClassLoader@a5c5ece8
   Delegation Mode: PARENT_LAST) called from class org.primefaces.util.Jsf22Helper (loaded from file:/opt/IBM/WebSphere/AppServer_2/profiles/server1/installedApps/loggerheadNode03Cell/trunk80_war.ear/trunk80.war/WEB-INF/lib/primefaces-6.2.jar

看起来PrimeFaces搜索JSF 2.2类的类Path-不幸的是,在这种情况下,PrimeFaces必须在提供的JSF 2.2捆绑包中找到这些类。将primefaces-6.2移出您的应用程序trunk80.war并将其移至隔离的共享库trunkLib应该解决此问题。

首先让primefaces源开放,它是easilly调试的。在源(在您的IDE或GITHUB中本地)中的简单搜索将使您成为JSF22Helper.java的来源。您可以检查在哪里被调用。在调试模式下运行是最简单的,但是GitHub的PrimeFaces存储库中的搜索仅在Corerenderer.java

中显示一个位置。
protected void renderDynamicPassThruAttributes(FacesContext context, UIComponent component) throws IOException {
    if (PrimeApplicationContext.getCurrentInstance(context).getEnvironment().isAtLeastJsf22()) {
        Jsf22Helper.renderPassThroughAttributes(context, component);
    }
}

接下来您应该检查

PrimeApplicationContext.getCurrentInstance(context).getEnvironment().isAtLeastJsf22()

和此的Getter返回从

获得其布尔值的属性
atLeastJsf22 = LangUtils.tryToLoadClassForName("javax.faces.flow.Flow") != null;

在此处,您会看到为了确定"最小"版本,他们尝试加载JSF 2.2或UP中存在的的类。这意味着,无论您是使用父级载荷还是独立于放置PrimeFaces的位置,如果javax.faces.flow.Flow在classPath上,PrimeFaces都会认为JSF 2.2可用。jsf 2.1是否在classPath上,甚至在JSF 2.2之前也也没有关系,因为此特定类在JSF2.1中不存在,并且将从JSF中加载始终2.2罐头。

要解决此问题,您有三个选项

  • 覆盖PrimeFaces PrimeEnvironment.java(例如,通过从web.xml读取明确的上下文属性,因此您可以选择手动覆盖版本检测并使用PrimeFaces为此创建拉动请求,以便他们可以接受它作为改进
  • '正确'覆盖JSF版本的方法类似于如何使WebSphere 8.5使用Mojarra而不是MyFaces
  • 切换到JSF 2.2

后者将是最好的,甚至可能只是开箱即用。

最新更新