Details
-
Type: Bug
-
Status: Closed
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 1.1.1
-
Component/s: None
-
Labels:None
Description
(From Padraic Renaghan)
Just an FYI in case anybody else runs across the issue I just diagnosed...
Pre-1.1 xstream would use the Thread classloader of the thread that made the
call to xstream.
In 1.1, the Thread classloader is initialized to the Thread being used to construct
the xstream instance.
In our application we had been creating Xstream in a static initializer and then
reusing it in various methods. Pre 1.1 this worked fine. In 1.1 it stopped working
b/c the Thread class loader when xstream was created was different than the
Thread class loader in force when the xstream.unmarshal method was called.
I'll probably just extend Composite class loader and have it get the Thread class
loader in the loadClass method.
Just wanted to possibly help others out, and make others aware of the change
in case it wasn't the desired effect.
------------
Symptom was a com.thoughtworks.xstream.alias.CannotResolveClassException
for something that most definitely should have been located, and something that
pre 1.1 was able to locate.
I've since created my own ClassLoader impl and passed that in to XStream's constructor
which seems to have done the trick. Example code below.
The more I think about it though, the more I think that grabbing the Thread classloader in the
constructor is a bug. It really shouldn't do that - at least from a do what is intuitive and most
likely what the client wants perspective.
xstream = new XStream(null, new DefaultClassMapper(new XStreamClassLoader()), new XppDriver());
public class XStreamClassLoader extends ClassLoader {
public Class loadClass(String name) throws ClassNotFoundException
{ Class c = null; // try classloader of current thread, often used by J2ee container c = tryToLoad(name, Thread.currentThread().getContextClassLoader()); if (c != null) return c; // try whichever classloader loaded this jar. c = tryToLoad(name, getClass().getClassLoader()); if (c != null) return c; // bootstrap class loader c = tryToLoad(name, Object.class.getClassLoader()); if (c != null) return c; throw new ClassNotFoundException("Can't locate " + name + " class in any ClassLoader"); } private Class tryToLoad(String name, ClassLoader classLoader) {
try
catch (ClassNotFoundException notFound)
{ // ok.. we'll try another one } return null;
}
}