views:

1718

answers:

3

Hi,

I have 2 different java projects, one has 2 classes

dynamicbeans.DynamicBean2

dynamic.Validator

On the other project, I load both of these classes dynamically and store them on an Object

class Form {
    Class beanClass;
    Class validatorClass;
    Validator validator;
}

I then go ahead and create a Validator object using validatorClass.newInstance() and store it on "validator" then I create a bean object as well using beanClass.newInstance() and add it to the session.

portletRequest.setAttribute("DynamicBean2", bean);

During the lifecycle of the "Form" project, I call validator.validate() which loads the previously created bean object from the session (I'm running Websphere Portal Server). When I try to cast this object back into a DynamicBean2 it fails with a ClassCastException.

When I pull the object back out of the session using

faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces);

and check the class of it using .getClass() I get dynamicbeans.DynamicBean2. This is the class I want to cast it to however when I try I get the ClassCastException.

Any reason why I'm getting this??

Thank you

+2  A: 

I am not quite following your description of the program flow, but usually when you get ClassCastExceptions you cannot explain you have loaded the class with one classloader then try to cast it to the same class loaded by another classloader. This will not work - they are represented by two different Class objects inside the JVM and the cast will fail.

There is an article about classloading in WebSphere. I cannot say how it applies to your application, but there are a number of possible solutions. I can think of at least:

  1. Change the context class loader manually. Requires that you can actually get a reference to an appropriate class loader, which may not be possible in your case.

    Thread.currentThread().setContextClassloader(...);

  2. Make sure the class is loaded by a class loader higher in the hierarchy.

  3. Serialize and deserialize the object. (Yuck!)

There is probably a more appropriate way for your particular situation though.

waxwing
My guess (I don't have experience with the portal server) is that you are loading the class in different portlets, each with its own classloader. You then place the instance into a session object, and when you retrieve it from the wrong portlet (from which it was created) you have your exception. I would guess (based on WAS experience) that you need to place the jar with your class somewhere higher in the classloading hierarchy so that it is loaded by a parent of both portlets classloaders.
Robin
i.e. Number 2, with details.
Robin
+1  A: 

The class objects were loaded in different classloaders, therefore the instances created from in each of classes are seen as 'incompatible'. This is a common issue in a an environment where there are many different classloaders being used and objects are being passed around. These issues can easily arise in JEE and portal environments.

Casting an instance of a class requires that the Class linked to the object being casted is the same as the one loaded by the current thread context classloader.

Robin
Is there a right way I should load the classes to stop this from happening?
ferrari fan
The mysterious part is why two class loaders should load the same class. In any Java application any class should always be loaded by only one class loader. Whenever you get this behavior something really weird is going on with your class loaders.
Steven Devijver
That depends on the environment you are operating in. If you use a singleton to cache information, and you put data into this cache from two different webapps that are in the same EAR, they can each have their own classloader creating instances, and when an item is retrieved from this cache from the other webapp, it will result in a ClassCastException. Sharing of in memory data can be very tricky in these environments, so you have to be aware of where classes are being loaded from for it to work.
Robin
+1  A: 

There is another solution, involving serialVersionUID: http://java-cookbook.info/O.Reilly-2004-Java.Cookbook.Second.Edition/0596007019/javacook2-CHP-10-SECT-19.html

Ehrann Mehdan