Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading Bean property values from context.xml

Currently we are loading our JDBC source values from properties file as per following:

<context:property-placeholder location="classpath:master.properties" ignore-unresolvable="true" />

<bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource"
    destroy-method="close">
    <property name="driverClass" value="${database.driver}" />
    <property name="jdbcUrl" value="${database.url}" />
    <property name="username" value="${database.user}" />
    <property name="password" value="${database.password}" />
    <property name="idleConnectionTestPeriod" value="60" />
    <property name="idleMaxAge" value="240" />
    <property name="maxConnectionsPerPartition" value="2" />
    <property name="minConnectionsPerPartition" value="2" />
    <property name="partitionCount" value="3" />
    <property name="acquireIncrement" value="10" />
    <property name="statementsCacheSize" value="50" />
    <property name="releaseHelperThreads" value="3" />
</bean>

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"
    scope="singleton">
    <property name="targetDataSource">
        <ref local="mainDataSource" />
    </property>
</bean>

This seg. works fine with classpath based app.properties file and get rid of app.properties.

We would like to load this values from context.xml (either placed in META-INF or $CATALINA_HOME/conf/context.xml). It will help us load proper values at prod/staging servers.

Will appreciate any help or alternate method/suggestions. (If similar question is already answered, please share the link) Thanks!

like image 973
navaltiger Avatar asked Mar 22 '23 00:03

navaltiger


2 Answers

As Alan Hay mentioned you could externalize the datasource configuration into Tomcat's own context.xml and then have Spring do a JNDI lookup to retrieve it. This is an approach that I've commonly used on some of the projects I've worked on.

The pieces you need to put in place to achieve would be:

1. Add the datasource configuration to $CATALINA_HOME/conf/context.xml

<GlobalNamingResources>

    <Resource type="javax.sql.DataSource" 
              name="dsName"
              factory="com.jolbox.bonecp.BoneCPDataSource" 
              driverClassName="your.driver.classname"
              jdbcUrl="your:driver:url" 
              username="username"
              password="password" 
              idleMaxAge="240" 
              idleConnectionTestPeriod="60"
              partitionCount="3" 
              acquireIncrement="10" 
              maxConnectionsPerPartition="2"
              minConnectionsPerPartition="2" 
              statementsCacheSize="50"
              releaseHelperThreads="3" />

</GlobalNamingResources>

2. Add a resource link in the application's META-INF/context.xml

<Context path="/YourApp">
    <ResourceLink description="Datasource for YourApp" 
                  global="jdbc/dsName"
                  name="jdbc/dsName" 
                  type="javax.sql.DataSource" />        
</Context>

3. Modify the Spring config to lookup the datasource in JNDI

<beans xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/jee classpath:/org/springframework/ejb/config/spring-jee-3.0.xsd">

    <jee:jndi-lookup id="dataSource" 
                     jndi-name="java:comp/env/jdbc/dsName" />

4. Move the driver and datasource jars

Since the datasource configuration is now container managed, you should place the database driver and datasource jars into $CATALINA_HOME/lib so they are available to Tomcat when it creates the datasource. These jars should no longer need to reside in the WEB-INF/lib of your application.

like image 81
Will Keeling Avatar answered Apr 02 '23 07:04

Will Keeling


The way I do it, I have default properties file in my classpath, and I have one properties file that I use to override those default (development) properties:

in my spring file:

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="ignoreResourceNotFound" value="true"/>
      <property name="locations">
        <list>
            <value>classpath:jdbc.properties</value>
            <value>classpath:camel.properties</value>
            <value>classpath:email.properties</value>
            <value>${external_config}</value>
        </list>
    </property>
</bean>

In development, I use the properties file in the classpath.
On the different envionment, staging, integration, production we start the application with the following parameter:

-Dexternal_config=file:c:/staging.properties

That way I have the same build for all environments and can choose the location of my overriding properties file.

So, ${external_config} is a place holder for a configuration file that depends on the environment. Spring looks for an environment variable named external_config, that variable should point to a configuration file. If the file is not found, Spring ignores it with ignoreResourceNotFound = true;

like image 39
Frederic Close Avatar answered Apr 02 '23 06:04

Frederic Close