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
- jndi.jar, fscontext.jar and providerutil.jar downloadable from Sun's JNDI download page.
- 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.