I really thought I had it all out of my system, but with each passing day, another aspect of the stupidity that is JBoss’ Unified Class Loader comes out and bites me.
The culprit this time? Precompiled JSPs. You see, we have this lovely Ant task that helps us precompile our JSPs – it looks something like this:
<java classname=”org.apache.jasper.JspC” classpathref=”jsp.precompile.path”>
<arg value=”-v4″/>
<arg value=”-die”/>
<arg value=”-d”/>
<arg value=”${jsp.precompile.dir}” />
<arg value=”-webinc”/>
<arg value=”${gen.mappings}”/>
<arg value=”-webapp”/>
<arg value=”${web.root}”/>
<arg value=”-uriroot”/>
<arg value=”${web.root}”/>
</java>
(You also need to merge the generated servlet definitions into your web.xml)
Things are all well and good until I begin combining all of our applications into a single JBoss instance as a part of our not-a-portal application gateway. Then, I begin seeing some very strange errors when I first access one of the applications. Kindly, Tomcat gives me an error, albeit in the form of an IllegalDispatchAction, and a line number in the translated JSP source. Strangely, however, the JSP source doesn’t contain the offending method at the specified line. And then it hits me.
That evil JBoss Universal ClassLoader has taken the precompiled index.jsp from another application and tried to use it in this application!
Now I’m sure that It-seemed-like-a-good-idea-at-the-time to design the JBoss ClassLoader the way it is. To their credit, it is very consistent in its application of these heinous rules, but this is yet another unintended consequence of this decision. I can think of very few situations where what I REALLY want is to have a precompiled JSP from a different application loading into my app. Those few situations are actually inconsistent with typical JSP behavior – if I can’t share non-precompiled JSPs between apps, why should I be able to share them in precompiled (i.e. servlet) form?
The solution is simple, but the beast of it all is tracking down the problem in the first place. All you have to to is give each app a unique package for its JSPS by adding a parameter to that JspC command:
<arg value=”-p”/>
<arg value=”uniquePackageName”/>
And voila! Another heinous consequence of the UCL worked around.