JNDI without an app server? part 1

We want to be able to run integration tests against our production code without always having to deploy to an app server.  Once the production code uses JNDI to get the JTA TransactionManager* and JMS and maybe Hibernate connection factories, how are we going to do those lookups without running on the app server?

*or is it UserTransaction — I haven’t read the JTA spec, so I’m not sure what magic Spring is doing to connect to the application server’s XA transaction manager.

Bypassing JNDI

There’s a paragraph in the Spring 2.5 Manual’s Testing chapter that talks about exactly the issue we’re discussing:

As far as possible, you should have exactly the same Spring configuration files in your integration tests as in the deployed environment. One likely point of difference concerns database connection pooling and transaction infrastructure. If you are deploying to a full-blown application server, you will probably use its connection pool (available through JNDI) and JTA implementation. Thus in production you will use a JndiObjectFactoryBean for the DataSource and JtaTransactionManager. JNDI and JTA will not be available in out-of-container integration tests, so you should use a combination like the Commons DBCP BasicDataSource and DataSourceTransactionManager or HibernateTransactionManager for them. You can factor out this variant behavior into a single XML file, having the choice between application server and ‘local’ configuration separated from all other configuration, which will not vary between the test and production environments. In addition, it is advisable to use properties files for connection settings: see the PetClinic application for an example.

That’s pretty on-point there!

Mocking JNDI

Another alternative is to have a bare-bones JNDI provider that gives your integration test the objects it needs.  Earlier in the Testing chapter, the Spring manual points us to the org.springframework.mock.jndi package, which provides an ExpectedLookupTemplate for this purpose.  ExpectedLookupTemplate extends JndiTemplate and lets you pass to the constructor a JNDI name and an object to return.  It appears that you could use an ExpectedLookupTemplate in your Spring bean file so that instead of just this:

	<jee:jndi-lookup id="queueConnectionFactory" jndi-name="java:activemq/QueueConnectionFactory" />

you’d add this:

    <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
        <constructor-arg index="0" value="vm://localhost" />

    <bean id="fakeJndiServer" class="org.springframework.mock.jndi.ExpectedLookupTemplate">
        <constructor-arg index="0" value="java:activemq/QueueConnectionFactory" />
        <constructor-arg index="1" ref="pooledConnectionFactory" />

And then users of the queueConnectionFactory bean could go on their merry way, not needing to know where the queueConnectionFactory came from.

You’d also need to add this to your pom.xml file:


And then all the rest of your Java code and configuration files could be the same.

Update 8/11/2008: The above example is not quite right.  See Part 2 for a working example of mocking JNDI.


3 thoughts on “JNDI without an app server? part 1

  1. Just FYI: if you’re looking to test your application outside JBoss, you’ll need a standalone TX manager to replicate exactly JBoss’ behavior.

    May I suggest you to have a look at BTM (http://docs.codehaus.org/display/BTM/Home) which is tailored to fill that exact requirement ? The upcoming version 1.3 contains everything you’re looking for especially with regard to the JNDI lookup outside the app server, see: http://blog.bitronix.be/2008/05/a-bit-more-on-upcoming-version-13/

    It’s also much easier to create an application without an application server in that way but that’s another discussion.

  2. Pingback: JNDI Tutorial With Spring JMS JNDI Example « Alan’s Script

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.