First Rule of Enterprise Java Development
The first rule of Enterprise Java Development is:
……
any unexpected behaviour is caused by a classpath problem
Todays instance of this rule is a particularly fun one, given the line of code that exposed the problem.
I am using Apache Jackrabbit as an embedded JCR repository, mostly following the Jackrabbit embedded mode instructions. I saw mostly because the Jackrabbit website doesn't actually match the 1.3 released version of JackRabbit (this is most annoying when following the "First Hops", but that is a digression).
So I've got a nice little webapp with an embedded repository that is accessed via JNDI. The repository is responsible for shutting itself down which it does via a shutdown hook (BindableRepositories do this). Unfortunately the shutdown hook gets called after the web app class loader has started unloading, and things are beginning to cleanup. The first symptom of this problem is a null pointer exception when logging a message12. After isolating that the log message (in org.apache.jackrabbit.core.RepositoryImpl.doShutdown) really was causing a NPE, I commented out he line of code, redeployed and confirmed the nasty problems, getting the following exception:
org.apache.catalina.loader.WebappClassLoader loadClass
INFO: Illegal access: this web application instance has been stopped already. Could not load org.apache.commons. collections.map.AbstractReferenceMap$ReferenceValuesIterator. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
So while I am not yet in a position to report a fix this problem, I have been able to isolate it, and identify yet another instance of the first rule of enterprise development.
1 - When I first saw that this line of code was causing the problem, I thought that it would end badly — either the source code I had didn't match the binary or I was getting a null pointer exception while logging. ↩
2 - This is particularly ironic given the raison d’être3 of SL4J is to remove problems like this.↩