Thursday 26 August 2010

Java just isn't being friendly today

Is it just me? Shouldn't Java app servers be more consistent?

I'm developing a commercial web application. This app must work in a variety of application servers, on a variety of databases, with minimal configuration of the kind that doesn't require users to understand Java.

So, I'm using Hibernate, and after a lot of faffing, have got Hibernate to work using a SequenceStyleGenerator (very nice) so it can handle different id generation schemes (sequences vs auto-increment).

I'm also using Spring, for dependency injection, transactions, and a bunch of other things like MVC, annotations and security. Spring is very nice for all of these things, but is a bit of a pain when it comes to changing anything without opening up the WAR / EAR.

My datasource, defined in Spring config, gets DB connections from a JNDI lookup. I define that JNDI lookup in the application server, but of course every application server exposes JNDI in a different way, so unless I want to maintain different WAR file builds for different application servers, I need a way to change the properties on startup.

Recently, I started using Spring's PropertyPlaceholderConfigurer, which takes a properties file as an argument: in my case 'classpath:my.properties'. This allows me to externalise the properties for the key things that need to be changed, like the datasource.


<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:my.properties</value>
</property>
</bean>


So now my datasource bean declaration is


<jee:jndi-lookup id="dataSource" name="${myDatasource}" />


All well and good. In most app servers, you then just drop the properties file on the classpath. In Weblogic (on Windows in this case), however, try as I might, I just couldn't get the thing to recognise the properties file, and since the datasource is pretty central to the app, it just didn't start. It's apparently not enough to just put it in the lib directory that Weblogic happily loads JAR files from.

The solution, which was simple, took a long time as I tried different things. It involves editing %WL_HOME%/user_projects/domains/base_domain/bin/setDomainEnv.cmd and adding the following line near the top:

set CLASSPATH=.;%CLASSPATH%

All this does is add the current directory to the classpath. Then, just drop the properties file into %WL_HOME%/user_projects/domains/base_domain and you're good to go.

Next problem! JNDI woes. I'd done this before in Weblogic and thought I had it sussed, so was disappointed when it suddenly stopped. I'd created my datasource with a JNDI name of jdbc/myDS, and I was looking up that same name from my Spring config (no need to prepend java:comp/env/ in Weblogic). But it didn't work. The solution, again simple when you know, is to make sure that you don't click 'Finish' prematurely when creating the datasource, but click 'Next' straight to the final screen, where you choose the 'targets'. If you're using a default install, that target will be 'AdminServer'. Then it will work.