Hai All,
finally a new technical item. It is a short item, but I have been struggling to get this to work. Therefore I want to share this so other can use it to configure there properties in a flexible way.

Problem:
Properties like database url’s, userid’s and pasword’s are different in your test environment and your production environment. There are other items you might want to configure.

Solution:
You can make complicated deployment scripts that get the right property files for the right environment. But you need to create different packages for different environments. I think a more elegant solution is to use the JNDI parameters to load the specific environmental values. If there are a lot a good way might be to store them in a database and only configure the database access parameters using JNDI.

The following solution is based on two posts in different forums:
http://forum.java.sun.com/thread.jspa?threadID=647327&messageID=3810991 – gives details about the configuration of tomcat.
http://forum.springframework.org/showthread.php?t=30991 – gives details about the spring configuration

Now the code, we start with the tomcat configuration. The server.xml file contains all the actual values connected to the exposed JNDI parameter names.

server.xml

  <!-- Global JNDI resources -->
  <GlobalNamingResources>
    <!-- Test entry for demonstration purposes -->
    <Environment name="jdbc/username" value="myUser" type="java.lang.String"/>
    <Environment name="jdbc/password" value="myPwd" type="java.lang.String"/>
    <Environment name="jdbc/url" value="jdbc:mysql://servername/schema" type="java.lang.String"/>
    <Environment name="jdbc/drivername" value="com.mysql.jdbc.Driver" type="java.lang.String"/>
  </GlobalNamingResources>

We need to tell the application the names of the parameters that are available. We must add the following items to the web configuration file.

web.xml

<resource-env-ref>
    <resource-env-ref-name>jdbc/username
    <resource-env-ref-type>java.lang.String
</resource-env-ref>

Of course you need to do this for all four parameters. Then the tricky part. This is the one I missed while getting this to work. You need to add a tomcat specific deployment configuration with the following lines

META-INF/context.xml

<Context path="/webapp">
    <ResourceLink name="jdbc/username" global="jdbc/username" type="java.lang.String"/>
    <ResourceLink name="jdbc/password" global="jdbc/password" type="java.lang.String"/>
    <ResourceLink name="jdbc/url" global="jdbc/url" type="java.lang.String"/>
    <ResourceLink name="jdbc/drivername" global="jdbc/drivername" type="java.lang.String"/>
</Context>

Thats is all we need to do to make these values available to the spring beans. So the last part is the spring configuration. We are going to create a PropertyPlaceHolderConfigurer. That way you can access the properties just like properties from a file.

spring-config.xml

    <bean id="databaseprops" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="properties">
            <bean class="java.util.Properties">
                <constructor-arg>
                    <map>
                        <entry key="database.username">
                            <jee:jndi-lookup jndi-name="java:comp/env/jdbc/username"/>
                        </entry>
                        <entry key="database.password">
                            <jee:jndi-lookup jndi-name="java:comp/env/jdbc/password"/>
                        </entry>
                        <entry key="database.url">
                            <jee:jndi-lookup jndi-name="java:comp/env/jdbc/url"/>
                        </entry>
                        <entry key="database.drivername">
                            <jee:jndi-lookup jndi-name="java:comp/env/jdbc/drivername"/>
                        </entry>
                    </map>
                </constructor-arg>
            </bean>
        </property>
    </bean>
    <bean id="sampleConfigBean" class="nl.gridshore.samples.config.SampleConfiguredBean">
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
        <property name="url" value="${database.url}"/>
        <property name="drivername" value="${database.drivername}"/>
    </bean>

This made my deployment life a lot easier, hope you will find some good use of it. Thanks again to contributers on the forum for making the different parts clear to me.

Till next time, which is going to be a piece about JPA.

greetz Jettro Coenradie

Loading properties using JNDI within the springframework deployed on tomcat