My developer connection home My Developer Connection
knowledgebase for software developers
Configuring datasource in spring through JNDI:
There are several ways to configure JNDI based data source in Spring. The following steps explains the same using Sun's file system based JNDI implementetion along with JndiTemplate in Spring. The following code uses apache c3p0 connection pool. You can replace the datasource creationg code with simple data source or some other connection pool api.

Step1: Define a connection properties file in class path. The properties file should have all the keys and values required for creating a datasource. You can replace the connection properties file with a xml file or constants in your code.
a simple properties file for c3p0 and postgres looks like this:

driverClass=org.postgresql.Driver
user=postgres
password=postgres
jdbcUrl=jdbc:postgresql://localhost/mydb

Step 2: Place the following piece of code in standalone class or wherever you get your bean factory. When executed, it generates a .binding file in your jndi root directory (c:/temp here). This .binding file contains your datasource information which could be used by jndi lookup api. You can use eclipse to resolve import depedencies. The following api needs to be in class path
  1. jndi.jar, fscontext.jar and providerutil.jar downloadable from Sun's JNDI download page.
  2. c3p0-0.9.0.jar available from apache or hibernate.
        System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.fscontext.RefFSContextFactory");
        System.setProperty(Context.PROVIDER_URL, "file:c:/temp"); // change provider url to a platform specific path
        Context registry = new InitialContext();
        // create a new connection pool data source, read the properties
        // file
        // and bind it to a name
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        Properties dsProperties = new Properties();
        FileInputStream cpdsPropFile = new FileInputStream("myconnection.properties);// myconnection.properties created in step1
        dsProperties.load(cpdsPropFile);
        cpds.setDriverClass(dsProperties.getProperty("driverClass"));
        cpds.setUser(dsProperties.getProperty("user"));
        cpds.setDescription("MYCONNECTIONKEY" + " Data Source"); //replace MYCONNECTIONKEY with the key you wish to use for lookup
        cpds.setPassword(dsProperties.getProperty("password"));
        cpds.setJdbcUrl(dsProperties.getProperty("jdbcUrl"));
        Connection con = cpds.getConnection();
        if (con != null){
                //Success
                registry.rebind("MYCONNECTIONKEY", cpds);
                // "closing" a connection sends it back to the pool
                con.close();
        } else {
        //Something wrong
        }

Step3:  The following entry in applicationcontext.xml configures a datasource bound with JNDI key created in step2.
    <!-- JNDI datasource for hibernate -->               
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
        <property name="environment">
            <props>
                <prop key="java.naming.factory.initial">com.sun.jndi.fscontext.RefFSContextFactory</prop>
                <prop key="java.naming.provider.url">file:c:/temp</prop>
            </props>
        </property>
    </bean>
    <bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate">
          <ref bean="jndiTemplate"/>
        </property>
        <property name="jndiName">
              <value>MYCONNECTIONKEY</value>
        </property>
      </bean>
    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"><ref bean="jndiDataSource"/></property>
        <property name="mappingResources">
            <list>
                <value>.......</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.jdbc.batch_size">1000</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
            </props>
        </property>
    </bean>

That's it. Whenever you change your connection properties, make sure the code in step2 gets executed to rebind new data source. Similar approach could be used with LDAP based jndi.