开发者

Servlet Exception + Class Cast Exception + Glassfish + Netbeans + JPA Entities + Vaadin

I get this error:

StandardWrapperValve[Vaadin Servlet]: PWC1406: Servlet.service() for servlet Vaadin Servlet threw exception java.lang.ClassCastException: com.delhi.entities.Category cannot be cast to com.delhi.entities.Category

when I try to run my webapps on glassfish v2.

Category is a JPA entity object

the offending code according to the server log is:

for (Category c : categories) {
          mymethod();
   }

categories is derived from:

List<Category> categories = q.getResultList();

Any 开发者_StackOverflow社区idea what went wrong?


This is a class loader issue. If a class is loaded by different class loaders, it's objects cannot be assigned to each other. You have probably passed an object from one WAR into another one. There are several options to resolve this:

  • Put all your code into a single WAR.
  • Use some form of remoting between your WARs. Serialization takes care of the class loader problem.
  • Try putting all you WARs into a single EAR. If that doesn't work, put all code into JARs that are on the EAR's Classpath in the MANIFEST.MF.


I once had the same problem and the environment I had was following:

  • I had Glassfish v4
  • Netbeans with following projects
    • webpage war project containing entities
    • and ear project with that webpage war project

The problem was that in war's project settings I had checked [x] Run>Deploy on save. This was causing deploying war project everyime I hit save. It was sometimes leading to PermGen (memory) problems and unability to deploy EAR correctly (because e.g. in between undeploying and deploying EAR - this "crazy" Netbeans was deploying this war).

Solution: If Netbeans && using EAR, then uncheck deploy on save in project properties.

EDIT:

it seems that this error is connected with

SEVERE:   The web application [/faces] created a ThreadLocal with key of type [org.glassfish.pfl.dynamic.codegen.impl.CurrentClassLoader$1] (value [org.glassfish.pfl.dynamic.codegen.impl.CurrentClassLoader$1@249ea63a]) and a value of type [org.glassfish.web.loader.WebappClassLoader] (value [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.


I've had same problem today. Solution was closing EntityManagerFactory after use.
This answer helped me: https://stackoverflow.com/a/13823219/2455506


I'm experiencing this problem too with Glassfish v2 and Glassfish v3.

Can I ask you a question: Are you attempting to initialize any persistence object when the application is deployed (through a servlet loaded on startup or a context listener)?

Like bguiz, I've noticed this problem only happens on redeploy. A new deploy to a freshly restarted Glassfish server, never has this problem.

Like FelixM mentioned, I'm convinced this is a class loader issue, however I don't believe it's an issue with multiple wars (I only have 1 deployed to my server). In Glassfish 3, I can see that my WAR is utilizing 2 Glassfish "engines". One for the web(war) and one for the jpa. From what I understand, these are different containers each with their own classloader. I'm guessing Glassfish v2 works in the same manner.

I'm using Spring and (re)initialize some persistence objects on (re)deploy. What I'm thinking, is that while the web engine is reinitializing the war, the jpa engine is still using the old class definitions. Often if I retry the redeploy after this initial failure, it may succeed (sometimes it may take more than one retry but eventually I can get it to succeed without a restart - having better success with Glassfish v3 than v2).

At this point I'm thinking that either these two classloaders are out of sync or there is some sort of race condition on redeploy allowing this operation to sometimes succeed. I've tried to force the classloader, writing code like this

HashMap<Object, Object> properties = new HashMap<Object, Object>();
properties.put(PersistenceUnitProperties.CLASSLOADER, this.getClass().getClassLoader());
entityManagerFactory = Persistence.createEntityManagerFactory(jpaContext, properties);

but it didn't seem to have any affect.

I'm also wondering if eliminating the initialization at startup could fix the problem, giving the appserver time to resynchronize both engines before using any jpa classes (which is why I asked my follow up question).


My observation is that it only happens when using a hot redeploy or a static redeploy. This only applies, of course, if you get a class cast exception where both the to and from classes are the same.

Workarounds:

  • Don't use undeploy and deploy instead of redeploy
  • Restart app server
  • Remove static members of the affected classes
  • Use a remote interface (serialization makes this go away)

IMO I think the class loader was unable to reload the class and the old version was reused, resulting in the error.


This article doesn't talk about this error directly, but it is good background info on how the class loader works.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜