Working with application servers it is not uncommon to run into strange ClassCastExceptions which seem to have now reason. You are trying to cast an instance of MyModel to MyModel and yet them JVM is having issues with it.
Experience has shown that there are two main categories for these “strange problems”:
- Multiple versions of the same class are present in the classpath. This can easily happen if you for example accidently include some libraries in your WAR file that are also provided by the application server.
- There is only one version of the class, but it is being loaded by different classloaders. If different classloaders load the same class it is not actually the same class from JVM’s perspective. Instead you have two different classes and casting from one to another causes ClassCastException.
The easist way to dig into the second class of problems is to use Eclipse debugger. Usually you get the issues from code like this:
MyModel model = myRemoteService.getObj();
To make debugging easier you can split the code into two parts. This way you get the returned value in local variable that you can inspect:
Object obj = myRemoteService.getObj(); MyModel model = (MyModel) obj;
The ClassCastException happens on the second line. This means that the class of obj is not compatible with MyModel. To dig into the issue, put a breakpoint on the line. When the debugger stops on the line, start looking into the obj and the MyModel class.
I found that the best way is to create new expression in the debugger to see the ClassLoaders associated with each class. To do this, bring up the “Expressions” view in Eclipse (you might need to add that from Window – Show view). CLick “Add new expression” and add two expressions like this
- obj.getClassLoader();
- com.mycompany.MyModel.class.getClassLoader();
Now you see constantly in the expressions view which class loaders were used to load the classes. In the value field you can see if they are the same (if they are, they have the same id number). Most likely they are not, since otherwise you wouldn’t be getting the exception. To understand the problem, start looking into the properties of the class loaders. If you are working inside servlet container such as Tomcat the class loaders have a property name “contextName” that tells which webapplication loaded the class. This can give hints about the underlying problem. Then you can see the jarPath, jarNames, canonicalLoaderDir etc.
All this does not magically solve the problem but once you understand the actual cause of ClassCastException, it is easier to fix it.