Forget what I said. Obviously this cannot work. I have to look in my tests
It seems to work.
Loader 1 javax.jdo.spi.StateManager is
[EMAIL PROTECTED]
Loader 2 javax.jdo.spi.StateManager is [EMAIL PROTECTED]
javax.jdo.spi.StateManager in use is [EMAIL PROTECTED]
Loader 1 javax.jdo.spi.StateManager is
[EMAIL PROTECTED]
Loader 2 javax.jdo.spi.StateManager is [EMAIL PROTECTED]
javax.jdo.spi.StateManager in use is [EMAIL PROTECTED]
Here is the unit test I'm running
File root = new
File(ClassLoaderTest.class.getResource("/org/jpox/persistence/ClassLoaderTest.class").getPath()).getParentFile().getParentFile().getParentFile().getParentFile();
URL path1 = new URL(root.toURL().toString()+"/");
URL path2 = new URL(path1.toString()+"/test/");
URL path3 = new URL(path1.toString()+"/test-classes/");
String jar =
JDOHelper.class.getResource("/javax/jdo/JDOHelper.class").getPath();
if( jar.indexOf('!')>0 ) // jar
{
jar = jar.substring(0,jar.indexOf('!'));
}
else
{
jar = new
File(jar).getParentFile().getParentFile().getParentFile().toURL().toString();
}
URL path4 = new URL(jar);
URLClassLoader loader = new URLClassLoader(new URL[] {path1, path2,
path3, path4},null);
ClassLoader l = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(loader);
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
Object id = null;
try
{
l.loadClass("javax.jdo.spi.StateManager").forName("javax.jdo.spi.StateManager",true,l);
loader.loadClass("javax.jdo.spi.StateManager").forName("javax.jdo.spi.StateManager",true,loader);
System.out.println("Loader 1 javax.jdo.spi.StateManager is
"+l.loadClass("javax.jdo.spi.StateManager").getClassLoader());
System.out.println("Loader 2 javax.jdo.spi.StateManager is
"+loader.loadClass("javax.jdo.spi.StateManager").getClassLoader());
Person p = new Person(987322,"cl","last","mail");
tx.begin();
pm.makePersistent(p);
id = pm.getObjectId(p);
System.out.println("javax.jdo.spi.StateManager in use is
"+((org.jpox.PersistenceManagerImpl)pm).getStateManagerById(id).getClass().getClassLoader());
tx.commit();
}
finally
{
if (tx.isActive())
{
tx.rollback();
}
pm.close();
}
pm = pmf.getPersistenceManager();
Thread.currentThread().setContextClassLoader(l);
tx = pm.currentTransaction();
try
{
tx.begin();
Person p = (Person) pm.getObjectById(id);
l.loadClass("javax.jdo.spi.StateManager").forName("javax.jdo.spi.StateManager");
loader.loadClass("javax.jdo.spi.StateManager").forName("javax.jdo.spi.StateManager");
System.out.println("Loader 1 javax.jdo.spi.StateManager is
"+l.loadClass("javax.jdo.spi.StateManager").getClassLoader());
System.out.println("Loader 2 javax.jdo.spi.StateManager is
"+loader.loadClass("javax.jdo.spi.StateManager").getClassLoader());
System.out.println("javax.jdo.spi.StateManager in use is
"+((org.jpox.PersistenceManagerImpl)pm).getStateManagerById(id).getClass().getClassLoader());
assertEquals("cl",p.getFirstName());
pm.deletePersistent(p);
tx.commit();
}
finally
{
if (tx.isActive())
{
tx.rollback();
}
Hi Erik,
If your Employee is loaded by classloader 1 and your implementation
is loaded by classloader 2 then the implementation won't work using
the standard JDO 2 binary compatible contracts.
Your implementation implements cl2.StateManager but the Employee
expects cl1.StateManager. I don't see how it can work.
Craig
Craig,
We can make it work easily. We are able to verify by class name the
interfaces
implemented, but I wonder if there is some security restriction on
that.
Regards,
Erik Bengtson
Hi Erik,
No, this is not ok.
The problem is for example when the application calls
pm.makePersistent(employee). If the jdoimpl does a check (if (! o
instanceof PersistenceCapable) throw JDOUserException("Object was not
enhanced");) then the different classes will be an issue. The
PersistenceCapable in the 2nd jar is not the same class as in the 1st
jar even though they have the same name.
Have you tried it?
Craig
Hi,
An app has two classloaders, the 1st with jdoimpl.jar+jdo2.jar and
the 2nd with
persistent classes +jdo2.jar.
The PCclass links to jdo2.jar(2) and the jdoImpl links to jdo2.jar
(1). I guess
that's ok, right? In any case, it may worth mentioning that in the
spec.
Regards,
Erik Bengtson
Craig Russell
jdo
P.S. A good JDO? O, Gasp!
Craig Russell
P.S. A good JDO? O, Gasp!