Skip to main content

glassfish JavaSE java.lang.ClassCastException: EntityManagerFactoryProvider

3 replies [Last post]
rumpi
Offline
Joined: 2005-12-14

Hi,

I am trying to use the glassfish-implementation for an Eclipse RichClient application and I get always the same ClassCast exception (given at the end of this posting). From a TestCase in the same directory it works (within eclipse). I have debugged the application with the source code from glassfish (class Persistence : line 88) and I really dont understand why I cannot cast the returned (not null) object from type EntityManagerFactoryProvider to the PersistenceProvider :

providers.add((PersistenceProvider)loader.loadClass(s).newInstance());

I tried to start the application also without the LazyStart option and also by setting the default class loader to the one which eclipse uses. Didn't help. It has in my opinion to do with the runtime-properties of the project, so I will really appreciate an opinion about the meaning of this exception.

java.lang.ClassCastException: oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
at javax.persistence.Persistence.findAllProviders(Persistence.java:88)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
...

Message was edited by: rumpi

Message was edited by: rumpi

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ss141213
Offline
Joined: 2005-03-30

> Hi,
>
> I am trying to use the glassfish-implementation for
> an Eclipse RichClient application and I get always
> the same ClassCast exception (given at the end of
> this posting).

Can you try running the application outside Eclipse, i.e. from command prompt? All you have to do is to run as follows:

java -javaagent:$GLASSFISH_HOME/lib/toplink-essentials-agent.jar -classpath :client.jar mypkg.MyMain

Replace client.jar and mypkg.MyMain with appropriate values.

> From a TestCase in the same directory
> it works (within eclipse). I have debugged the
> application with the source code from glassfish
> (class Persistence : line 88) and I really dont
> understand why I cannot cast the returned (not null)
> object from type EntityManagerFactoryProvider to the
> PersistenceProvider :
>
> providers.add((PersistenceProvider)loader.loadClass(s)
> .newInstance());
>

The only reason I can think of is that there are somehow [b]two[/b] class loaders involved here and both of them have defined javax.persistence.spi.PersistenceProvider.class [b]separately[/b]. Some how, the class loader that defined your main class (let's call it [b]mainCL[/b]) is not same as Thread.getContextClassLoader() (let's call this as [b]tCL[/b]). mainCL loads its own version of Persistence class which then uses tCL to load toplink.EntityManagerFactoryProvider class. Since, tCL and mainCL have loaded javax.persistence.PersistenceProvider separately, that results in a ClassCastException.

I suggest, you run your app outside Eclipse and see if it works or not.

Secondly, add the following printlns in your main method...
main(String[] args) throws Exception {
ClassLoader tlc = Thread.currentThread().getContextClassLoader();
System.out.println(tlc);
ClassLoader mainCL = Persistence.class.getClassLoader();
System.out.println(mainCL);
System.out.println(tCL.loadClass("javax.persistence.spi.PersistenceProvider") == javax.persistence.spi.PersistenceProvider.class);

// now call createEntityManagerFactory
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU");
}

Ideally mainCL & tCL should point to same instance and the last one should print true.

Let us know what it prints...

Thanks,
Sahoo

rumpi
Offline
Joined: 2005-12-14

Thanks for the reply. You are right, the problem was in the different classloaders (eclipse uses its own and the default CL of a thread is not that of eclipse). Before calling the createManager... I have set the current thread classloader to that of eclipse and with it I loaded some classes.
Thanks for the rappid answer and help.

Thread current = Thread.currentThread();
ClassLoader oldLoader = current.getContextClassLoader();
try{ current.setContextClassLoader(getClass().getClassLoader());
current.getContextClassLoader().loadClass("oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider");
current.getContextClassLoader().loadClass("javax.persistence.spi.PersistenceProvider");
current.getContextClassLoader().loadClass("javax.persistence.Persistence");
...createManager...

}finally{
current.setContextClassLoader(oldLoader);
}

ss141213
Offline
Joined: 2005-03-30

I am glad, it now [b]works[/b] for you. See comments in line...

> Thanks for the reply. You are right, the problem was
> in the different classloaders (eclipse uses its own
> and the default CL of a thread is not that of
> eclipse). Before calling the createManager... I have
> set the current thread classloader to that of eclipse
> and with it I loaded some classes.
> Thanks for the rappid answer and help.
>
> Thread current = Thread.currentThread();
> ClassLoader oldLoader =
> current.getContextClassLoader();
> try{ current.setContextClassLoader(getClass().getCla
> ssLoader());
>

Ideally, you should not have to do this in your code. So, I hope, you shall be taking it up with Eclipse team to see how to configure Eclipse.

More over, those loadClass calls before createEMF are not necessary.

Thanks,
Sahoo