Spring loading application.properties based on tomcat servlet context definition

27,747

Solution 1

One feature of PropertyPlaceholder is that you can define multiple resource locations. So for example you can define your-production-config.properties along with file:C:/Users/${user.name}/test-application.properties

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:your-production-config.properties</value>
            <value>file:C:/Users/${user.name}/test-application.properties</value>
        </list>
    </property>
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>        
</bean>

for production you need to place prod configuration into classpath somewhere(really not important where exactly, just classpath) - for local env you can use convension like this file:C:/Users/${user.name}/test-application.properties

Solution 2

I ended up solving it by not using context params. Instead we have defined

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:application.properties</value>
            <value>file:C:\Users\Bill\prod-application.properties</value>
        </list>
    </property>
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="ignoreResourceNotFound" value="true"/>
</bean>

This way tries to load both files. On test servers we do not have the prod file so it is not loaded. On prod server the prod-application.properties file exists and overrides the test which is in the classpath. Cumbersome but works!

Solution 3

<context:property-placeholder location="file:${catalina.home}/conf/myFirst.properties" ignore-unresolvable="true" />
<context:property-placeholder   location="classpath:second.properties"  ignore-unresolvable="true"  />

I do it like above. The catalina.home variable allows the properties file to be lcoated in the tomcat home conf directory.

Solution 4

Personally, try to avoid specify locations. I think best thing for you is to use JNDI to achieve this.

In tomcat/conf/server.xml

<Resource name="jdbc/prod" auth="Container"
          type="javax.sql.DataSource" driverClassName="${database.driverClassName}"
          url="${database.url}"
          username="${database.username}" password="${database.password}"
          maxActive="20" maxIdle="10"
          maxWait="-1"/>

and In tomcat catalina.properties (If using Oracle XE otherwise change it accordingly):

database.driverClassName=oracle.jdbc.driver.OracleDriver
database.url=jdbc:oracle:thin:@//localhost:1521/XE
database.username=user
database.password=password

In your application create properties file in your classpath named jdbc.properties and put followings (If using Oracle XE otherwise change it accordingly)

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:user/password@//localhost:1521/XE

then In Spring applicationContext.xml

<context:property-placeholder location="classpath:jdbc.properties" />

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/prod" />
    <property name="defaultObject" ref="dataSourceFallback" />
</bean>
<bean id="dataSourceFallback" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="poolPreparedStatements">
        <value>true</value>
    </property>
    <property name="maxActive">
        <value>4</value>
    </property>
    <property name="maxIdle">
        <value>1</value>
    </property>
</bean>
Share:
27,747
checklist
Author by

checklist

Updated on April 22, 2020

Comments

  • checklist
    checklist about 4 years

    I need to have a development and production settings for our spring project. I understand that you can use profiles for spring but that is not something that we can do.

    What I want to do is place on the development environment a test-application.properties file and on production a prod-application.properties file. In the tomcat context definition we sent the following:

    <Context>
        <context-param>
            <param-name>properties_location</param-name>
            <param-value>file:C:\Users\Bill\test-application.properties</param-value>
        </context-param>
    </Context>
    

    And we can have the value changed for the production servers. In the spring config we have something like this:

    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>${properties_location}</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="false" />
    </bean>
    

    But we keep getting errors like:

    org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/${properties_location}]

    Any ideas on how to solve?