First a bit of background, I am working as part of a team responsible for building a bespoke content management system for educational uses and the back end uses the following technologies:
- Java Tomcat 7.0 server
- Rest Easy 3.0.6.Final
- ElasticSearch 1.0.1
- Google Guice 3.0 for dependency injection
- Eclipse Kepler Build 20130919-0819
- Counterclockwise (Clojure plugin For Eclipse) 0.20.0 & 0.24.1.STABLE001 – This becomes important later even though I am not using it really.
Now to describe the problem. For some reason after integrating ElasticSearch with our project a nasty error as seen below started happening (and breaking the whole site at runtime when running within eclipse):
SEVERE: Servlet.service() for servlet [jsp] in context with path [/rutherford-server] threw exception [Filter execution threw an exception] with root cause
java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/catalina/loader/WebappClassLoader) previously initiated loading for a different type with name "javax/servlet/http/HttpSession"
This problem seemed to refer at a random place in our code in the stack trace. This random place had previously worked (and is totally unrelated to the Elastic Search stuff I was working on) in my case it occurred in a User Manager class that deals with sessions (hence the reference to HttpSession). The elastic search stuff didn’t have anything to do with the user manager or even use the HttpSession class as far as I was aware but seemed to trigger the error when the code for the elasticsearch java api was inserted.
A really useful explanation of how class loaders work can be found in Frank Kieviet’s blog; it certainly helped me understand the strange behaviour i.e. random things breaking that are totally unrelated to the change being made.
As mentioned in Frank Kieviet’s blog, this type of error is extremely difficult to debug and it appears that it is related to the sequence in which classes are loaded into the jvm.
My approach, after initially (and wrongly) blaming Google Guice and ElasticSearch, eventually lead me to investigate what was actually asking for another version of the HttpSession class. In order to do this I added the following to my run configuration for the tomcat server within the eclipse run configuration.
Naturally, this caused a huge torrent of information to be spewed out of the console screen; so much so that I had to make the console buffer set to unlimited size to preserve all of the information.
After some targeted searching of the output I found the following two lines (in different areas of the output):
[Loaded javax.servlet.http.HttpSession from file:/C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%207.0/lib/servlet-api.jar]
[Loaded javax.servlet.http.HttpSession from file:/C:/eclipse/plugins/ccw.core_0.20.0.STABLE001/lib/servlet-api.jar]
Strange I hear you all say. Why would there be an eclipse plugin displayed in the console of my tomcat run environment. Well that is what I thought too. After some more investigation the offending plugin is Counter Clockwise, a cojure plugin for eclipse.
After uninstalling the clojure plugin everything was fine again; elastic search and the user manager worked like a dream. I did try updating from Clojure plugin version 0.20.0 to 0.24.1 but everything still broke.
I have a few outstanding questions like:
- Why are my eclipse plugins interfering with my tomcat environment running in eclipse (I thought it would run in a different JVM)?
- Why is clojure running all the time anyway (I wasn’t even using the plugin for anything I was doing at the time)?
- Shouldn’t the tomcat instance running within eclipse be sandboxed from plugins etc.
Note: I will try and come up with a simple example that breaks consistently and post it here but in the mean time if anyone is interested I can set you up with a copy of the code base at the point we were having the errors.