24

I am working on a Spring WebFlow project which has a lot of property values in XML files, as any Spring programmer knows. I have database user names, password, URLs, etc.

We are using Eclipse with Spring WebFlow and Maven. We are trying to have an SA do the builds but the SA does not want to go into the XML files to change the values, but on the other hand, we don't know the production values. How do we work with this?

kuporific
  • 10,053
  • 3
  • 42
  • 46
techsjs2012
  • 1,737
  • 5
  • 25
  • 57
  • See the accepted answer on this question. I've just done some work where I needed to externalize the config; the solution referenced here allows for default values as well as a easy mechanism for overriding them from one properties file. http://stackoverflow.com/questions/13093346/how-do-i-control-spring-injections-that-vary-between-the-test-environment-and-th – chad Nov 08 '12 at 21:04

3 Answers3

48

Most SA are more willing and confident to deal with .properties file rather than .xml.

Spring provide PropertyPlaceholderConfigurer to let you define everything into one or several .properties file and substitute the placeholder in applicationContext.xml.

Create a app.properties under src/main/resources/ folder:

... ...

# Dadabase connection settings:
jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/app_db
jdbc.username=app_admin
jdbc.password=password

... ...

And use PropertyPlaceholderConfigurer in applicationContext.xml like so:

... ...

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location">
    <value>app.properties</value>
  </property>
</bean>

... ...

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
</bean>

Check out Spring PropertyPlaceholderConfigurer Example for more details.

In addition, from application deployment perspective, we usually package app in some executable format and the .properties files are usually packed inside the executable war or ear file. A simple solution is to configure your PropertyPlaceholderConfigurer bean to resolve properties from multiple location in a pre-defined order, so in the deployment environment, you can use a fixed location or environment variable to specify the properties file, also note that in order to simplify the deploy/configure task for SA, we usually use a single external .properties file define all runtime configuration, like so:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
    <list>
      <!-- Default location inside war file -->
      <value>classpath:app.properties</value>
      <!-- Environment specific location, a fixed path on server -->
      <value>file:///opt/my-app/conf/app.properties</value>
    </list>
  </property>
  <property name="ignoreResourceNotFound" value="true"/>
</bean>

Hope this helps.

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
yorkw
  • 40,926
  • 10
  • 117
  • 130
  • Medium-sized enterprises usually apply some policy to restrict developer access production environment, a common software development/deployment strategy is to let developer develop software (of cause), build and pack them into a deliverable format, provide the package with deployment instruction to SA, and let SA build/maintain the hardware infrastructure, deploy/config the software and tuning performance (CPU, RAM usage and etc). It is more reasonable to let developer build the package, not the system admin. – yorkw Nov 08 '12 at 21:49
  • For the second solution where you get the property file from external location(outside war), what if a property changes ? Do we have to redeploy the application/ restart the server ? Because Property configurer configures the file only once if I understand correctly. – PavanSandeep Oct 03 '14 at 01:27
2

Another simple way is Spring Expression Language (SpEL) for example

 <property name="url" value="#{ systemProperties['jdbc.url'] }" />

Documentation spring documentations

borino
  • 1,720
  • 1
  • 16
  • 24
1

Also you can define a propertyConfigurer programmatically in configuration class:

@Configuration
@PropertySource("classpath:application.properties")
public class PropertiesConfiguration {

    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(Environment env) {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setEnvironment(env);
        return configurer;
    }
}