views:

342

answers:

2

Hi there.

I've got a question regarding the difference between PropertyPlaceholderConfigurer (org.springframework.beans.factory.config.PropertyPlaceholderConfigurer) and normal filters defined in my pom.xml.

I've been looking at examples, and it seems that even though filters are defined and marked to be active by default in the pom.xml they still make use of PropertyPlaceholderConfigurer in Spring's applicationContext.xml.

This means that the pom.xml has a reference to a filter-LOCAL.properties while applicationContext.xml has a reference to application.properties and they both contain the same settings.

Why is that? Is that how it is supposed to be done? I'm able to run the goal mvn jetty:run without the application.properties present, but if I add settings to the application.properties that differ from the filter-LOCAL.properties they don't seem to override.

Here's an example of what I mean:

pom.xml

    <profiles>  
        <profile>  
            <id>LOCAL  
            <activation>  
                <activeByDefault>true  
            </activation>   
            <properties>  
                <env>LOCAL  
            </properties>  
        </profile>  
    </profiles>

applicationContext.xml

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:application.properties
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

an example of the content of application.properties and filters-LOCAL.properties

jdbc.driver=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost/shoutbox_dev
jdbc.username=tester
jdbc.password=tester

Can I remove the propertyConfigurer from the applicationContext, create a PROD filter and disregard the application.properties file, or will that give me issues when deploying to the production server?

+1  A: 

You should rather use Maven to select which Spring properties file to use depending on which environment you're building for.

When you're testing in your IDE, you should just start the Spring container from the test without using Maven for anything else than managing your dependencies.

Espen
Do you have a suggestion for what I should google to find out how to use Maven to select the spring properties as you suggested?
John
@John: Personally, I prefer Ivy and Ant, but the principals should be the same. Dependent on which environment I'm building for, I copy different properties file and rename it to for example application.properties. Then my Spring application context that imports the PropertyPlaceholderConfigurer only knows about application.properties. If this is copied from test.properties or production.properties is unkown for the Spring container. It's only my test contexts that knows about the test properties for my JUnit tests.
Espen
-1 - building seperate instances of your deployable for each environment is a bad idea. It doesn't scale well and you will end up having to crack open war to see which properties are included. See my answer here for an alternative approach: http://stackoverflow.com/questions/1311360/property-placeholder-location-from-another-property/1312341#1312341
Pablojim
@Pablojim: Why should I open a war file to see my properties? No, I prefer to have the system's properties in a separate folder. And then configure the web container to add that folder to the classpath. Then I end up with just one environment specific properties file instead of many and the potential situation of using wrong file.Related to security, it can be nice to limit the information available for each environment. That each environment only knows about its own settings.
Espen
I agree with you comment above. But don't understand why then you have this in your answer "You should rather use Maven to select which Spring properties file to use depending on which environment you're building for." - a seperate build process for each environment is a smell.
Pablojim
+1  A: 

For the record, here is what the author of the blog series the OP is following wrote in this comment:

I used to be a big fan of Spring’s PropertyPlaceholderConfigurer but ever since I started using maven I don’t find it as useful as maven’s filters, using either a filters file as explained here, or by having multiple profiles in the pom for the different deployment layers with each profile specifying the properties.

The biggest gripe I have with the PropertyPlaceholderConfigurer is that you can only have one PropertyPlaceholderConfigurer bean. And it’s not well documented.

With maven’s filter files you can have as many as you like.

The other reason I prefer maven’s filters is that with them you can do a ‘mvn package’ and then poke around in the target directory and eyeball the filtered config files and see what it did. With Spring’s PropertyPlaceholderConfigurer you don’t find out what’s been substituted until the app is started.

I second this opinion and prefer the filter approach over using the PropertyPlaceholderConfigurer and the Antrun plugin to copy say test.properties into application.properties when running my tests. And using filtered resources is well supported by all major IDEs (Eclipse, IntelliJ, NetBeans) so I don't see why I should not use it.

Pascal Thivent
I prefer to use Spring's <util:properties> element, since I'm not a huge fan of global properties.
Espen