Aug 6th, 2007, 02:41 PM
Porting from Tomcat to WebSphere
We are trying to port a working JSF (MyFaces)/Spring/Hibernate application to WebSphere. We originally put all of the library jars into the root of the EAR. After configuring WebSphere data sources and installing the application, we thought we had everything working. But, some of our web pages were not working "right". We found out that this was due to the fact that WebSphere 6.1 ties Sun's JSF RI into their web container. Reference: http://wiki.apache.org/myfaces/Websphere_Installation
Because of that, the app was using the Sun's RI and not MyFaces jars. To get around this, we put the 'web tier' libraries into WEB-INF/lib and changed WebSphere's module classloader policy to application first. Now, when the application server starts, the following exception is thrown:
[8/6/07 15:29:35:241 EDT] 0000001e SystemOut O 2007-08-06 15:29:34,897 ERROR [WebContainer : 1] (StartupServletContextListener.java:96, initFaces) - Error initializing ServletContext
java.lang.IllegalArgumentException: Class org.springframework.web.jsf.DelegatingVariableReso lver is no javax.faces.el.VariableResolver
We realize that this is not actually a Spring issue, but more of a configuration problem. But we were wondering if anybody on this forum had some insight into this exception, and what we might do to get around it in a WebSphere 6.1 environment.
Aug 6th, 2007, 04:07 PM
I guess DelegatingVariableResolver actually implements VariableResolver? Then it is a class loader issue in that way that VariableResolver is probably loaded by two different class loaders. Since classes are actually determined by their name AND their class loader this would explain the exception. This is often caused by deploying an API in both a shared/common/global/whatever class loader and the actual web application. If that's the case try to remove your JSF API jar form your web application.
Hope that helps,
PS: My 1000th post
Aug 6th, 2007, 05:46 PM
Thanks. I notice that org.springframework.web.jsf.DelegatingVariableReso lver extends javax.faces.el.VariableResolver. I took the MyFaces libraries out of the root of the EAR and put them in WEB-INF/lib, so that I could override the WebSphere container's default inclusion of Sun's JSF RI set of classes. So, Spring.jar is in the root of the EAR, and the JSF classes are in WEB-INF/lib. I set the WAR's class loader to application first in the WebSphere console, so I think the Sun's JSF RI are not getting loaded, (this is how I want it, since we are using MyFaces). As such, I don't think Spring is finding the base class, since it can't look into the WAR. Does this sound plausible? I don't have much Spring experience yet - I was just charged with porting the app to WebSphere. I am not at work at the moment, but I will test this tomorrow.
Aug 6th, 2007, 07:20 PM
Your explanation is very plausible except for one minor detail - for which your setup is doomed to fail. What happens?
First Spring is loaded independently from any web application. One of the things that happen here is the instantiation of DelegatingVariableResolver and to do this the super class must be loaded. As you noticed Spring (or better said EAR root class loader) can't look into the web application, but it finds the VariableResolver in Sun's JSF RI.
Second you have your web application accessing the Spring context and the DelegatingVariableResolver instance. The latter one is checked for being an instance of the web application class loader's VariableResolver. The DelegatingVariableResolver (extending the EAR root's VariableResolver) is not compatible to it.
Moving the JSF API jar from the EAR root to WEB-INF/lib is not a solution but the cause of the problem. If it is Sun's RI or MyFaces in one or the other class loader does not matter at all, the different class loaders are the problem. An API jar must be loaded by only one class loader. Spring does not change anything in this picture, it's just another jar.
Aug 6th, 2007, 08:25 PM
Okay, originally I had all of the library jars in the root of the EAR and the 'business tier' classes (Hibernate stuff, mostly) jarred up in one jar in the root of the EAR. I had the web tier classes in WEB-INF/classes and of course the jspx's and faces config xml's in the WAR as well. Also, I put the library jars that I figured the web tier needed on the manifest class path, which I generated with Ant in the war task. The server started up fine and the pages loaded and the DB2 data sources were accessed via Hibernate with aplomb. The only problem was that the app was using an imposter, that is, the Sun RI bundled into the WebSphere web container. I know this because exceptions that only the Sun RI throws (like duplicate id exceptions) were being thrown on several pages, and also because this app has been runnning for several months on Tomcat without incident. So, I decided to move the 'web tier' library jars into the WEB-INF/lib folder and set the war's classloader policy to application first, which, as you have noted, turned out to be a fool's errand.
So, maybe this will work: put everything back to the way I had it (all library jars in the root of the EAR), but still set the war's classloader policy to application first, which I don't think I did in the first place. Then, since I have the MyFaces and associated jars on the WAR's manifest class path, maybe the MyFaces etc. jars will get loaded instead of the Sun RI ones, and everything will work according to plan. If not, then I will be the one getting loaded, at 9:00 am tomorrow morning.
Aug 6th, 2007, 11:55 PM