Category Archives: jackrabbit

TDD With JackRabbit

… tips on Apache JackRabbit configuration for Test Driven Development. 

As AJ mentioned, we are currently working with Apache JackRabbit for an internal project.  It has been an interesting voyage of discovery, with some very interesting stops along the way. One of the first steps was to build some tests around the JCR.  I started with some simple exploratory tests around the API.  These helped build my understanding of the JCR and how it works.

The next step was to begin really working out our persistence API with TDD.  As a part of this, I wanted to be able to have a predominantly memory based repository to work with.  This is possible to do, as per the attached memoryRepository.xml file.

The key is to use a org.apache.jackrabbit.core.fs.mem. MemoryFileSystem for all file system elements, and a org.apache.jackrabbit.core.persistence.mem. InMemPersistenceManager for all persistence manager elements.  Unfortunately, with the attached config the file system is still used to store Lucene search indexes.  This means that the file system is still used, and needs to be cleaned up in the tests.

The attached JcrRepositoryTestBase.java file has the setup and teardown code that handles the cleanup of the search index directories.  This combination of code combines to allow the 35 JCR tests that we have run in about 10 seconds, and gives 100% coverage of all non exception handling code1.

1 – i.e. not including code that does nothing but catch (Exception e) {throw Wrapper(e) }, which while is testable is not currently tested by us.

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.

3 – like my attempt at culture?4  

4 – sorry about the footnote overkill.