我们有一个应用程序的 EAR,我们将它部署在我们的旧服务器上:Windows Server 2003 R2,32 位,WebSphere 8.0.0.4。现在我已经在另一台机器上建立了一个理论上等效的 WebSphere 8.0.0.4 实例:Windows Server 2012 R2 标准,64 位。
我们正在使用(是的,我知道,我知道,这是遗留问题,我现在无法更改)带有 myfaces/richfaces[1] 的 JSF 1.2。(选择“SunRI 1.2”作为应用程序的 WebSphere 设置中使用的实现。)
我在它们两个上部署了相同的 EAR 文件,执行相同的步骤。
在原始服务器上一切正常。然而,在新服务器上,(显然)成功部署后,我在登录应用程序时不断收到此异常(即,在将呈现的第一页上):
(我用 ***** 匿名化单元格/EAR/WAR/包名称)
javax.el.ELException: //C:/Program Files (x86)/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/****Node01Cell/*****.ear/*******.war/index.xhtml: Property 'chooseLocale' not found on type
***.UserLanguageBean
at com.sun.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:53)
at com.sun.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:39)
at com.sun.facelets.compiler.UILeaf.encodeAll(UILeaf.java:149)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:257)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:155)
(请注意,它——即 h:commandLink——不应该像这里那样查找属性,而是要执行的方法!)
实际上,这(几乎)是 JSF 引擎遇到的第一个 EL 表达式:
<c:when test="#{not empty param.language}"> <!-- THIS IS OK, PARSED/INTERPRETED CORRECTLY! -->
<h:form style="display:none;" id="languageForm">
<h:commandLink action="#{userLanguageBean.chooseLocale}" id="languageButton"> <!-- THIS IS NOT, CAUSES EXCEPTION ON NEW SERVER -->
<f:param name="locale" value="#{param.language}"/>
</h:commandLink>
</h:form>
...
类 UserLanguageBean 注册为 JSF bean,它确实有一个方法 chooseLocale()。(否则它也不会在旧服务器上工作。)有趣的是,旧服务器甚至没有到达引发异常的代码部分,至少根据调试器!
现在(基于怀疑某些 JSF/Myfaces/Richfaces 库未正确加载)我尝试了以下操作:
接下来是血腥的细节,所以如果你是那种不耐烦但已经有想法的人,请随时发布答案而无需继续阅读!
--- 血腥细节:---
我已经在两台服务器上打开了详细的类加载并比较了 native_stderr.log 文件。存在差异,但所有与 JSF 相关的类(如在 grep "(face\|jsf)" 中)似乎都来自同一个 jar。
- 有一些类只加载到旧服务器上,但没有加载到新服务器上,但是(根据这些类的直觉)我把它归结为新服务器没有达到实际上呈现了它遇到的第一个 xhtml 页面(见上文),而旧页面则这样做了。
我已经为这两个平台中的每一个都附加了一个调试器,并查看了类加载器(以及它们的父类加载器等)——它们的类路径中似乎有相同的 jar。(包括那些不在EAR 中的。) - 我通过一些复制粘贴、grepping 和排序来确定这一点,就像在第 1 点中一样。
我在新服务器上部署期间检查了错误:(“坏”)
- 在 WebSphere 控制台上它说一切正常
- 在部署期间记录了一些异常,这些异常在旧的日志中没有(“好”的),但它们似乎都不需要对 JSF 或 EL 表达式做任何事情
我已经导出了配置并(不包括一些服务器名称和基本目录差异)对它们进行了比较。
- 再次,我确实发现了设置的差异,但似乎与 JSF 等没有任何关系。
在调试器中,我检查了 a) 在旧服务器上由 JSF 调用 UserLanguageBean.chooseLocale() 的堆栈跟踪 [2],以及 b) 在新服务器上抛出 ELException 的位置
==> 这部分似乎在 FacesServlet.service() (来自 myfaces-api-1.2.7.jar)中:
try
{
this._lifecycle.execute(facesContext); // <--- new server: Exception! further code is not reached
if (!handleQueuedExceptions(facesContext))
{
this._lifecycle.render(facesContext); // <--- old server: renders the tag
}
}
脚注:
[1]
$ ls -1 "c:\Program Files (x86)\IBM\WebSphere\AppServer\profiles\AppSrv01\installedApps\*******Node01Cell\*****.ear\*****.war\WEB-INF\lib\\" | grep faces
myfaces-api-1.2.7.jar
myfaces-extval-core-1.2.2.jar
myfaces-extval-generic-support-1.2.2.jar
myfaces-extval-property-validation-1.2.2.jar
myfaces-impl-1.2.7.jar
richfaces-api-3.3.1.GA.jar
richfaces-impl-3.3.1.GA.jar
richfaces-ui-3.3.1.GA.jar
==> 所以我真的不知道我们到底在使用哪一个
[2]
a)在旧服务器上正确执行:
TagMethodExpression.invoke(ELContext, Object[]) line: 68
_MethodExpressionToMethodBinding.invoke(FacesContext, Object[]) line: 78
ActionListenerImpl.processAction(ActionEvent) line: 57
HtmlCommandLink(UICommand).broadcast(FacesEvent) line: 141
AjaxViewRoot.processEvents(FacesContext, EventsQueue, boolean) line: 321
AjaxViewRoot.broadcastEvents(FacesContext, PhaseId) line: 296
AjaxViewRoot.processPhase(FacesContext, PhaseId, InvokerCallback) line: 253
AjaxViewRoot.processApplication(FacesContext) line: 466
InvokeApplicationExecutor.execute(FacesContext) line: 32
LifecycleImpl.executePhase(FacesContext, PhaseExecutor, PhaseListenerManager) line: 103
LifecycleImpl.execute(FacesContext) line: 76
FacesServlet.service(ServletRequest, ServletResponse) line: 151
b) 新服务器上的异常:参见开头的堆栈跟踪 + PropertyNotFoundException 的堆栈跟踪(实际异常):
javax.el.PropertyNotFoundException: Property 'chooseLocale' not found on type ******.UserLanguageBean
at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:225)
at javax.el.BeanELResolver$BeanProperties.access$400(BeanELResolver.java:202)
at javax.el.BeanELResolver.property(BeanELResolver.java:312)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:87)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:55)
at org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:140)
at org.apache.el.parser.AstValue.getValue(AstValue.java:169)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:283)
at com.sun.facelets.el.ELText$ELTextVariable.toString(ELText.java:174)
at com.sun.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:49)
at com.sun.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:39)
at com.sun.facelets.compiler.UILeaf.encodeAll(UILeaf.java:149)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:257)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:41)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:155)