I have an extremely puzzling situation and looking for any ideas.
I’m running a small Spring MVC app, where I make use of the RequestMapping annotation on my controller “AnsController“. When RequestDispatcher is scanning my beans for the RequestMapping annotation, at some point it comes down to this line:
clazz.getAnnotation(RequestMapping.class)
(clazz = AnsController.class)
The line above does not find the annotation, even though it is there.
I started investigating this in Eclipse debugger and found a very puzzling problem. The reason why the above line fails is b/c RequestMapping.class is returning a Class object which seems to describe the correct annotation, but has a different internal id and hashCode then the Class object stored in the annotations array on the AnsController.class!
I wrote a test servlet where I placed the above line of code, and I can see that the Class stored in the annotations array and the Class returned by RequestMapping.class are the same object.
Yet in the RequestDispatcher servlet, RequestMapping.class seems to instantiate another instance of the Class for that same annotation (I can tell b/c the internal id is much higher than the id of the Class object in the annotations map).
In other words, calling RequestMapping.class in my Test Servlet results in a different Class object than calling exactly the same code in RequestDispatcher servlet.
Should this be even possible, assuming the same classloader is being used? Is this sufficient evidence to conclude that these distinct instances of the Class object that are supposed to represent one and the same annotation must be produced by different classloaders?
I can’t find anything in writing that would confirm my assumption that only one instance of Class object per class is allowed, but it seems reasonable… Or am I wrong?
And there we have it. After being convinced by all the answers here that I have a classloader mess, I was able to find the problem. I was bit in the ass by a hack I did a year ago :).
At the time I wrote an Eclipse plugin that I used to launch the Jetty 6 server with the app deployed in-place. That plugin placed all of the web project build dependencies on the AppClasspath via the commandline
-classpathswitch. This was desirable for the app I was using it for, b/c it allowed me to greatly simplify the classloading strategy in development mode for that specific case. In this case, however, I ended up with Spring jars on theAppClassLoaderandWebClassLoader, b/c the Spring jars were inWEB-INF/lib.Once I realized that, I just had to set
parentLoaderPriorityonWebAppContexttotruein my jetty config and the problem went away. It’s still a hack of course, but good enough for the quick-and-dirty app I’m doing here.Thank you for all the helpful responses!