Java – ClassCastException in datanucleus Dao object when using JDO to persist / retrieve object
I created a simple webapp using spring Jetty, I'm using datanucleus & to create a hello world JDO test DB4O.
I can insist that there is no problem with a class, but when I query the class, I get a ClassCastException, which cannot convert a.b.c.myclass to a.b.c.myclass
When I check the classloader of the original object I created, it is [webappclassloader @ 1592226291]. Of course, it is the spring webapp classloader
I perform persist and query operations in the same servlet method. When I reread objects from the DB through a simple query, I get a group of abcmyclass objects from the DB, but the class loader is [sun. Misc. Launcher]$ AppClassLoader@5acac268 ], so it's an exception
Follow datauucleus docs http://www.datanucleus.org/extensions/classloader_resolver.html
I introduced the first two recorded options and verified that the class loader is the webappclassloader in the servlet and these debugging steps in the servlet:
Thread.currentThread().getContextClassLoader().toString() ((JDOPersistenceManagerFactory)pm.getPersistenceManagerFactory()).getPrimaryClassLoader().toString()
Both use [webappclassloader @ 1592226291] as the class loader
I don't know where I was wrong
Solution
As an answer to my previous comments:
This exception indicates that it is a classloader problem Compare the class loader of the object with the class you used to convert
ClassLoader loaderOfObject = theObject.getClass().getClassLoader(); ClassLoader loaderOfLocalClass = MyClass.getClassLoader(); // have to be the same. assert loaderOfObject.equals(loaderOfLocalClass);
By the way: if db4o uses the wrong class loader You can change it explicitly by configuring class loader
EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration(); JdkReflector reflector = new JdkReflector(Thread.currentThread().getContextClassLoader()); configuration.common().reflectWith(reflector); ObjectContainer container = Db4oEmbedded.openFile(configuration,"database.db4o");
When a single classloader is not enough: you can also pass an instance of db4o interface jdkloader instead of a classloader There, you can implement any class lookup method For example, find multiple class loaders