We have an EAR of our application, which we deploy on our old server: Windows Server 2003 R2, 32 bit, WebSphere 8.0.0.4. Now I have set up a theoretically equivalent WebSphere 8.0.0.4 instance on another machine: Windows Server 2012 R2 standard, 64 bit.
We're using (yes, I know, I know, it's legacy, I can't change it right now) JSF 1.2 with myfaces/richfaces[1]. ("SunRI 1.2" is choosen as the implementation used in the WebSphere setup for the application.)
I deployed the same EAR file on both of them, executing the same steps.
On the original server everything works fine. On the new server, however, after an (apparently) successful deploy, I keep getting this exception when logging into the application (i.e., on the first page that would be rendered):
(I'm anonymizing the cell/EAR/WAR/package names with *****)
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)
(Note that it -- i.e., h:commandLink -- SHOULDN'T look for a property like it does here, but a method to execute instead!)
actually this is (almost) the very first EL expression the JSF engine encounters:
<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>
...
Class UserLanguageBean is registered as a JSF bean and it does have a method chooseLocale(). (Otherwise it wouldn't work on the old server either.) Interestingly, the old server doesn't even reach the part of the code where the exception is thrown, at least according to the debugger!
Now (based on the suspicion that some JSF/Myfaces/Richfaces library is not properly loaded) I have tried the following:
Gory details follow, so if you're the impatient kind but already have an idea, feel free to post an answer without reading on!
--- GORY DETAILS: ---
I have turned on verbose class loading on both servers and compared the native_stderr.log files. There were differences, but all the JSF-related classes (as in grep "(face\|jsf)") seem to come from the same jars.
- there were a few classes that had only been loaded on the old server but not on the new one, but (gut feeling based on which classes those were) I put that down to the fact that the new server didn't reach the point of actually rendering the first xhtml page it came upon (see above), whereas the old one did.
I have attached a debugger to each of the two platforms and took a look at the classloaders (and their parent classloaders etc.) -- they seem to have the same jars in their classpaths. (Including the ones not residing in the EAR.) - I determined this by some copy pasting, grepping and sorting, just like in point 1.
I have checked for errors during deployment on the new server: (the "bad" one)
- on the WebSphere console it said everything was OK
- there were some Exceptions logged during deployment that weren't there in the log on the old one (the "good" one), but neither of them seemed even remotely to have to do anything with JSF or EL expressions
I have exported the configurations and (excluding some server-name- and base-directory-differences) compared them.
- again, I did find differences in the setup, but nothing that seemed to have anything to do with JSF etc.
In the debugger I have checked the stack traces[2] of a) where UserLanguageBean.chooseLocale() is called by JSF on the old server, and b) where the ELException is thrown on the new one
==> it seems that in FacesServlet.service() (comes from myfaces-api-1.2.7.jar) at this part:
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
}
}
FOOTNOTES:
[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
==> so I don't really know which one exactly we're using
[2]
a) proper execution on old server:
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) exception on new server: see stack trace at the beginning + the stack trace of the PropertyNotFoundException (the actual exception) :
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)