views:

46

answers:

1

If I have classes that need to be shared between my webapp and Tomcat (e.g. a custom realm and principal), where should the .jar file containing those classes go?

Currently I'm putting the .jar in ${CATALINA_HOME}/lib. This result is a ClassCastException when assigning references from classes of the same type. Here's an example:

MyCustomPrincipal principal = (MyCustomPrincipal)FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();

The method above throws a ClassCastException. The method returns an actual MyCustomPrincipal type (since that's what my custom realm gave Tomcat when it performed authentication) that, apparently, was created by a different classloader. How do I fix this so both Tomcat and my webapp can use MyCustomPrincipal?

http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

Any help is appreciated. Andrew

+2  A: 

It looks like you have 2 copies loaded, once in tomcat and once in your WEB-INF/lib jars or other classpath of your deployed application.

The reason you get classpath exception lies in the way a WAR looks for classes. Contrary to the normal Java rules, a war first looks inside the war for a class and only then passes the request to teh parent classloader.

A class's identity is dependent of the classloader and the same class loaded in 1 classloader will generate a classcast exception when it is casted in the other classloader.

The solution is to make sure that the war does not contain the classes which should be provided by the container. If you use maven you can mark these dependencies as 'provided', if you use ant, you have to split your classpath list in 2 and compile against both, but use only the ones you need for constructing the war.

Peter Tillemans
ok, that makes sense. If I understand correctly, I need to be sure there's only one source for the class file. I'm using NetBeans, which uses Ant to build the .war file. Currently I've updated the build.xml to pre-deploy the .jar containing my custom principal and realm to ${CATALINA_HOME}/lib. Can I just update the build.xml and tell Ant not to deploy MyCustomPrincipal.class in the .war?
Andrew
yes, if that is the only one, then add an exclude line. If it are more duplicates then it pays to keep 2 lists.
Peter Tillemans
Thanks a lot for your help. I really appreciate it.
Andrew