I firmly believe that you are not a seasoned Java developer until you have faced an irritating class loading issue.
Recently
found myself in xerces hell, trust me its not a good place to be in.
Without going into too much details and various issues I faced (internet is
filled with them). I will talk about what solved the issues for me:
Background:
XercesImpl.jar and xml-apis.jar are both part of Apache xerces and
XML4J xml parser library. One of the product I was working on,
somehow was shipping with only XercesImpl.jar. Things worked fine
until now. (looks like xml-apis.jar delivered classes were getting
picked from the JDK. xerces parser jars are part of JDK since version
6 at-least, may be even earlier)
Problem:
Suddenly there were errors thrown up related to
“XMLGregorianCalendar2 class not found” , “Duration2 class not
found”. Looks like these classes are present in the XML4J -
xml-apis.jar. As this jar was not packed with the product, hence the
error.
Why
these error didn't come up previously: Looks like there was no
Gregorian calendar related XML parsing happening in the product
previously. Due to some change it started and hence the error.
Possible
solution (not working):
Add xml-apis.jar in the products/web-inf. But on doing so the
xml-apis classes started conflicting with the already loaded apis
from the JDK. You would see errors like
org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl cannot be cast to
javax.xml.datatype.DatatypeFactory. Don't be too surprised, as both
the classes are fully compatible but looks like the problem is
classloader. Classes are loaded by different classloader and hence
mismatch.
Even
if the the application is having “parent last” classloader
setting, you will see this error. Also I saw some pages where it said
that adding xml-apis.jar to web-inf/lib is not suggested.
Correct
solution (at-least which worked for me): Removed the
xercesImpl.jar from the web-inf/lib. (classes will get served from
the JDK)
In
case you are using some ancient version of JDK with no XML parser,
there is another safer solution > Keep xercesImpl.jar in
web-inf/lib, and keep the xml-apis.jar in appserver/domain/lib
directory.
This
way the required API classes will not be loaded, even if they are,
will not conflict with the JDK classes as these will be loaded in the
same classloader as that of JDK.
The
only problem I see with this solution is that, keeping the jar in
domain lib will be extra manual step, outside of the regular app
deployment.
In
case you are aware of any better solution then do let me know.
(There
is a setting in to Prefer application packages in Weblogic, that
might also work, but I I have not tried. Anyways its a app server
specific fix and playing too much with application class-loading
sequence is not suggested)
No comments:
Post a Comment