28
votes

I have following bean declaration:

  <bean
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>WEB-INF/classes/config/properties/database.properties</value>
                <value>classpath:config/properties/database.properties</value>
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true"/>
    </bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <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>

Now I want to change above PropertyPlaceholderConfigurer to following format:

<context:component-scan base-package="org.example.config"/>
<util:properties id="jdbcProperties" 
           location="classpath:config/properties/database.properties"/>
  1. ignoreResourceNotFound will ignore the property while running. e.g: When testing application WEB-INF/.. path will ignore( since maven project and property file is under src/main/resources/..), while launching web application, other property will ignore path, I need to implement same with above format.
  2. should be able to add multiple property file like database.properties, test.properties etc.
  3. in Spring 3, can I use annotation instead of these xml files for DB loading, how can I do it? since I am using only one xml file(given above) to load db stuff.

I am using Spring 3 framework.

3

3 Answers

48
votes

<context:property-placeholder ... /> is the XML equivalent to the PropertyPlaceholderConfigurer. So, prefer that. The <util:properties/> simply factories a java.util.Properties instance that you can inject.

In Spring 3.1 (not 3.0...) you can do something like this:

@Configuration
@PropertySource("/foo/bar/services.properties")
public class ServiceConfiguration { 

    @Autowired Environment environment; 

    @Bean public javax.sql.DataSource dataSource( ){ 
        String user = this.environment.getProperty("ds.user");
        ...
    } 
}

In Spring 3.0, you can "access" properties defined using the PropertyPlaceHolderConfigurer mechanism using the SpEl annotations:

@Value("${ds.user}") private String user;

If you want to remove the XML all together, simply register the PropertyPlaceholderConfigurer manually using Java configuration. I prefer the 3.1 approach. But, if youre using the Spring 3.0 approach (since 3.1's not GA yet...), you can now define the above XML like this:

@Configuration 
public class MySpring3Configuration {     
        @Bean 
        public static PropertyPlaceholderConfigurer configurer() { 
             PropertyPlaceholderConfigurer ppc = ...
             ppc.setLocations(...);
             return ppc; 
        } 

        @Bean 
        public class DataSource dataSource(
                @Value("${ds.user}") String user, 
                @Value("${ds.pw}") String pw, 
                ...) { 
            DataSource ds = ...
            ds.setUser(user);
            ds.setPassword(pw);                        
            ...
            return ds;
        }
}

Note that the PPC is defined using a static bean definition method. This is required to make sure the bean is registered early, because the PPC is a BeanFactoryPostProcessor - it can influence the registration of the beans themselves in the context, so it necessarily has to be registered before everything else.

19
votes

First, you don't need to define both of those locations. Just use classpath:config/properties/database.properties. In a WAR, WEB-INF/classes is a classpath entry, so it will work just fine.

After that, I think what you mean is you want to use Spring's schema-based configuration to create a configurer. That would go like this:

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

Note that you don't need to "ignoreResourceNotFound" anymore. If you need to define the properties separately using util:properties:

<context:property-placeholder properties-ref="jdbcProperties" ignore-resource-not-found="true"/>

There's usually not any reason to define them separately, though.

0
votes

Following worked for me:
<context:property-placeholder location="file:src/resources/spring/AppController.properties"/>

Somehow "classpath:xxx" is not picking the file.