<< April 2009 | Home | June 2009 >>

Mysterious injection problem...

I just found out (the hard way) about an interesting quirk in how GlassFish handles dependency injections. I updated a library JAR used in my project, and the new filename was different from the previous one due to having the version number in its name. So I had to update my build.xml to reflect the changed name both in the javac classpath and in the copy task that assembles WEB-INF/lib for the webapp. But I made a typo in the second case, so a <file> element in a <fileset> in a copy-task pointed to a non-existent file. Since the correct file was in the javac classpath, compilation of my own source code worked without problems. And "ant" happily proceeded to create the WAR file anyway, despite the missing file in the copy-task. This is not part of the mystery however — "ant" is extremely unintuitive so this behaviour is no different from business as usual.

Deployment failed of course, but in a rather peculiar way. The broken WAR file contained a servlet that was as a subclass of one of the classes in the missing library JAR. It also contained a ServletContextListener that invoked a method on an injected EJB. But this injection never happened, so I got a NullPointerException and initialization of the webapp context failed. It took me quite a long time plus some intense head-scratching to figure out why: the missing servlet superclass somehow stopped injection from happening in the context listener. The mysterious part is why the ServletContextListener.contextInitialized() method was called despite this failure. It wasn't until I removed the EJB invocation that the servlet initialization produced a ClassNotFoundException that revealed the true cause of the problem.

Moral: never assume that a failure in one part of the system won't affect other parts in non-obvious and unpredictable ways.