6 Tips for Managing Property Files with Spring

April 20th, 2009 Ben Northrop, Consultant  (email the author)

What could be simpler than property files? In an enterprise application, it turns out, many things! In this post I’ll take a look at a few subtle complexities to managing properties in an enterprise Java Spring application, and hopefully demonstrate how a little fore-thought in design can yield big savings in terms of time, confusion, bugs, and gray hair down the road.

Types of Properties

Before designing an approach to managing property files, it’s critical first to understand the types of properties are to be managed. Here are four characteristics to consider:

  • Are some properties environment specific – in other words, do they have a different value in one environment than another? For example, a database connection string would differ in the TEST environment than it would the PROD environment.
  • Do any properties contain sensitive information, like passwords or credentials, that can’t sit in plain text in the deployment unit (e.g. WAR, EAR)?
  • Do any properties need to be located external from the deployment unit (e.g. on the file system rather than in the WAR, perhaps to be managed by a systems administrator)?
  • Should properties be dynamic, in the sense that they can be updated at runtime (i.e. without requiring a restart of the application)?
  • Each of these special characteristics adds a degree of complexity to applications – necessitating additional infrastructure beyond the simple Java Properties class.

    Spring’s PropertyPlaceholderConfigurer

    Fortunately for us, the Spring framework, with the PropertyPlaceholderConfigurer and PropertyOverrideConfigurer, provides the features and hooks we need to manage these cases (with the exception “dynamic” properties). And true to its philosophy, Spring makes simple things simple, and complicated things possible.

    The PropertyPlaceholderConfigurer allows properties to be pulled in to the application context file. For example, in the simplest case, a property “db.user” defined in database.properties could be pulled into the ${db.user} placeholder:

    <bean id="propertyPlaceholderConfigurer"	
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="locations">
        <list>
          <value>classpath:database.properties</value>
        </list>
      </property>
    </bean>
    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="user" value="${db.user}"/>
      <property name="password" value="${db.password}"/>
      ...
    </bean>
    
    

    The PropertyOverrideConfigurer works in the opposite way, pushing properties from property files into properties in the context file (without having to specifically define a place holder – e.g. ${db.user}). These are both well documented in the Spring API and documentation.

    Tips

    Given the different possible types of properties, and Spring’s property framework, here are a few tips for managing them:

    1) Consider using a JVM System property that sets the environment of the machine (e.g. “my.env=TEST”), telling the configurer which property file to use. For example:

      <context:property-placeholder 
          location="classpath:db-${my.env}.properties"/>
    

    If the “my.env” property was set to “TEST”, then obviously the PropertyPlacementConfigurer would look for a file called “db-TEST.properties”. For Tomcat, this property can be set in the admin console or defined in a startup script (e.g. “-Dmy.env=TEST”) – neither of which is very elegant. Alternatively, it is possible to use JNDI with Tomcat, defining “my.env” in the server.xml and the context.xml of the web app. (Note, there are of course many other ways to solve this environment-specific problem, but this is an easy and relatively straight-forward one.)


    2) It may be necessary to set the ignoreUnresolvablePlaceholders to true for any PropertyPlaceholderConfigurer, which will ensure that a configurer won’t fail if it can’t find a property. Why would this be a good thing? Oftentimes, one context file will import other context files, and each may have their own configurer. If ignoreUnresolvablePlaceholders is set to false (the default), then one configure would fail if it couldn’t find the property, even if another configurer down-stream could find it (see good explanation here). Beware, however, since this will suppress warnings for legitimate missing properties, making for some tough-to-debug configuration problems.


    3) To encrypt properties, subclass the PropertyPlacementConfigurer and override the convertPropertyValue() method. For example:

    protected String convertPropertyValue(String strVal) {
      //if strVal starts with “!!” then return EncryptUtil.decrypt(strVal)
      // else return strVal
    }
    

    4) Consider using the systemPropertiesMode property of the configurer to override properties defined in property files with System properties. For one-off environment specific properties this can be a helpful solution, however, for defining many properties, this configuration can be cumbersone.


    5) For properties that need to be managed outside of the WAR, consider using a System property to define where the file is located. For example, the property ${ext.prop.dir} could define some default directory on the file system where external property files are kept:

    <context:property-placeholder 
         location="file:///${ext.prop.dir}db.properties"/>
    

    This entails, however, that this property is set for any process that leverages the Spring container (e.g. add the param to the Run Configuration for integration/unit tests, etc.), otherwise the file would not be found. This can be a pain. To circumvent, the configurer can be overridden – changing the behavior such that it looks to the external directory only if the System property is set, otherwise it pulls from the classpath.


    6) Beware of redundancy of environment-specific properties. For example, if the solution is to have one property file for each environment (e.g. “db-test.properties”, “db-dev.properties”, etc.), then maintaining these properties can be a bit of a nightmare – if a property “foo” is added, then it would have to be added to the property file for each environment (e.g. DEV, TEST, PROD, etc.). The PropertyOverrideConfigurer is appropriate to eliminate this redundancy, setting the default value in the application context itself, but then the overriding value in a separate file. It’s important, however, to document this well, since it can look a bit “magical” to an unsuspecting maintenance developer who sees one value specified in the context file, but another used at runtime.

    Conclusion

    Managing properties for an enterprise application is a little trickier than one might expect. With Spring’s property configurers, however, the toughest part is just knowing what you need – the rest comes out of the box, or with some minor extensions.

    Hopefully a few of these tips will be useful for you. Please let me know some of your own!

    Be Sociable, Share!

Entry Filed under: Agile and Development

57 Comments Add your own

  • 1. Jeff Johnston  |  September 28th, 2009 at 11:28 pm

    I started a project that people may be interested in. It is called Configleon and solves the problem of loading property attributes in different environments and/or server contexts. With Configleon you can build one war file that can be deployed to every location.

    Configleon really shines is in its ability to cascade the property attributes. This allows all the common attributes to be defined in a global file and then overridden for each application server context.

    http://code.google.com/p/configleon/

  • 2. James  |  November 9th, 2009 at 4:20 am

    Ben, the tips you mentioned were extremely useful. Thanks a lot.

  • 3. Ben  |  April 16th, 2010 at 7:00 am

    Ben, I don’t want Spring to load my properties file as I want to check it and reload it if it changes, so my semantics are more complex than what Spring offers.

    However, what I want to do is to pass in name of properties file location (using absolute path), via a system property, ala:

    Using system properties in this way does not seem to work, spring only supports system properties *within* properties placeholder config….

  • 4. Ronald  |  July 6th, 2010 at 2:58 am

    Another option is to use multiple propertie files, one in the war and one in your home directory and override (if required) certain settings in the properties file in your home dir, for instance the db connect string can be defined in both files. If you put your home properties file as last, then the settings in that file will override the original ones:

    classpath:/someApp.properties
    file:${user.home}/someApp.properties-->


    The ignoreResourceNotFound will skip the setting for user.home if it is not found. Thus it will also run in a test environment where that file is not available.

  • 5. Ronald  |  July 6th, 2010 at 3:01 am

    well the code tag didnt help so, lets try it like this:

    <bean id=”propertyConfigurer” class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”^gt;
    <property name=”locations”>
    <list>
    <value>classpath:/competities.properties</value>
    <value>file:${user.home}/someApp.properties</value>
    </list>
    </property>
    <property name=”ignoreResourceNotFound” value=”true”/>
    </bean>

  • 6. Mike Gage  |  September 8th, 2010 at 7:49 am

    Great tips. Thank you!

  • 7. Vishwas  |  September 19th, 2010 at 4:07 pm

    Thanks Ben! Just what I was looking for

  • 8. Anil Mathew  |  September 30th, 2010 at 1:30 pm

    Beautiful tips from Ben. Thank You.

    I do have one question – so does this mean we can’t use the spring if we need the property to be updated at runtime (ie. dynamic)?

    Thanks
    Anil

  • 9. Ben Northrop  |  September 30th, 2010 at 2:36 pm

    Thanks Anil! Good question…and to be honest, I don’t know the answer completely.

    If you have properties that need to be updated at run-time, my sense is that the PropertyPlaceholderConfigurer is not what you’re looking for…since this will inject properties into beans at the time the application context is loaded.

    What I’m unsure of…is if you have some bean defined in Spring as “prototype” scope…which has some properties injected into it from some property file (via the PropertyPlaceholderConfigurer)…whether (a) when this bean is instantiated Spring loads afresh the property file and injects this property or (b) Spring uses the property values as they were at application start-up to inject into that bean. It’s a great question though…and when I get a free minute, I’ll test it out and get back to you.

    In general though, if you have dynamic properties, you may want to just consider a simple ResourceBundle…or maybe just externalize these properties to a database (if possible).

    Hope that helps!

  • 10. donn  |  October 8th, 2010 at 9:33 am

    nice tips. Thanks.

    In case you have tested out the dynamic loading of properties, please let us know.

    thanks again.

  • 11. Ben Northrop  |  October 8th, 2010 at 11:31 am

    So…it turns out that dynamic properties using the PropertyPlaceholderConfigurer doesn’t work, even with a prototyped-scope bean.

    I ran a quick test…and it seems that property values are cached from the time the application context is loaded. Even if you change a given property value in the property file after the application starts, your bean will still be injected with the property value that was initially loaded.

    If you’re interested, here’s the test I ran: SpringPropTest.zip.

  • 12. Tarun  |  October 13th, 2010 at 1:12 pm

    Is there a way to log the resolved values of all the properties? I have the same properties defined in different properties files and i want to know which is the finally resolved value of the property.
    Also : For Dynamic Properties, I found the the apache-configuration framework very usefull.

  • 13. Ben Northrop  |  October 13th, 2010 at 2:26 pm

    Hi Tarun. Yeah…try subclassing the PropertyPlaceholderConfigurer, like this::

      public class LoggingPPC extends PropertyPlaceholderConfigurer {
        @Override
        protected void loadProperties(Properties props) throws IOException {
          super.loadProperties(props);
          for (Entryentry : props.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
          }
        }
      }

    Then use this class when you load properties:

      <bean id="myPropertyPlaceholderConfigurer" class="com.foo.LoggingPPC ">
        ...
      </bean>

    Hope that works!

  • 14. Tarun  |  October 13th, 2010 at 3:13 pm

    Thanks Ben, it works just fine :), great help

  • 15. Anil Mathew  |  October 21st, 2010 at 12:51 pm

    Thanks Ben for testing it out. In fact i also tried and has concluded same (dynamic property update may not work with Spring).

    I saw Tarun mentioned that “the apache-configuration framework” works fine. Can you give some more tips on that please? An example how it works or reference to any website?

  • 16. Sharath  |  October 25th, 2010 at 4:12 am

    Hi Ben,
    Thanks for all the tips.
    I actually have a requirement that I have to use the property file external to the war; I am trying to use the external file location in the property-placeholder
    eg:

    After this code I have a code configuration in my xml which uses the property within the Sample.properties

    The code fails as it is not able to fetch the values from the property-placeholder; it fails at war deployment as the xml files I use are used during war deploying.

    can you please help in this regard.

  • 17. Sharath  |  October 25th, 2010 at 4:32 am

    Hi Ben,
    Thanks for all the tips.
    I actually have a requirement that I have to use the property file external to the war; I am trying to use the external file location in the property-placeholder
    eg:

    After this code I have a code configuration in my xml which uses the property within the Sample.properties

    The code fails as it is not able to fetch the values from the property-placeholder; it fails at war deployment as the xml files I use are used during war deploying.

    can you please help in this regard.

  • 18. Sharath  |  October 25th, 2010 at 4:32 am

    context:property-placeholder location=”file:D:/property/Sample.properties

  • 19. Gabriel  |  January 10th, 2011 at 1:02 pm

    Is there a way of getting a default value if the system property is not set?

    For example in this line of code you wrote,

    if -Dmy.env parameter is not passed it will blow up, is there a way to tell Spring that if that property is not set, then use a default value (E.g. dev)

    so it will get resolved in something like this:

    I read time ago that using :value after the variable name will do it, but it does work, for example like this

    Any suggestion?

  • 20. Ben Northrop  |  January 10th, 2011 at 3:40 pm

    Yeah, definitely…check out this:

    http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html#setSystemPropertiesMode(int)

    Basically, if I understand your question correctly, you can set the systemPropertiesMode and set it to “2″ (override), and it should pick up the System property first, and if it’s not there, get the property normally.

    It’s also a very powerful fall-back solution to sub-class PropertyPlaceholderConfigurer in cases where you need to do really tricky things.

  • 21. Leena  |  January 19th, 2011 at 12:58 pm

    is it possible to load a property xml using ?

  • 22. Leena  |  January 19th, 2011 at 1:01 pm

    is it possible to load a property xml using — <context:property-placeholder?

  • 23. gsathya  |  January 21st, 2011 at 5:41 am

    Hi

    is it possible to use nested properties like this and use @value annotation to set the values.

    ########################################
    schema.name=report
    select.query=select * from ${schema.name}.user
    ########################################

    public @Value(“#{query['select.query']}”) String selectQuery;

    ** When i print the value of selectQuery the same string is printed , without interpreting the place holder value

  • 24. AndyB  |  February 20th, 2011 at 3:21 pm

    Thanks for this write-up, very useful.
    In Spring 3.0 you can set default values for placeholders. e.g. ${env:local} where ‘local’ is the default value if ${env} is not resolved.
    This is useful for if you’re setting a system property to resolve a placeholder, e.g the environment, but in development you can just fall back to the locally defined default value.

  • 25. Ben Northrop  |  February 21st, 2011 at 8:27 am

    Thanks very much Andy! When I wrote this post I was using Spring 2.5, so I’ll swing back and incorporate this into my post.

  • 26. Wendy  |  February 22nd, 2011 at 4:42 am

    Hey.
    I’d like to thank you for this post.
    This has been very useful for me !

  • 27. Properties files in Sprin&hellip  |  February 24th, 2011 at 11:06 am

  • 28. Joshua Smith  |  May 25th, 2011 at 10:34 am

    Very useful post. Thanks.

    I was successful switching things out with environmental variables, but not using JNDI properties when running in tomcat. I can print out the JNDI properties in a JSP and they are set fine, but Spring doesn’t seem to find them and so it defaults to what is in the war file.

    This what I put in my TOMCAT_HOME/conf/context.xml file:

    This is what I have in my application context:

    And the following in my application context:

    The goals is that it uses JNDI variables to resolve the property files if they are available (which is when it’s running in Tomcat). It uses the environmental variables if they are available (when it’s running as a stand-alone Java application). And it uses the properties files in the JAR/WAR file if the others are not found. All of that works fine except the JNDI properties.

    Any ideas?
    Thanks,
    Joshua Smith

  • 29. Joshua Smith  |  May 25th, 2011 at 10:41 am

  • 30. Rippon  |  June 15th, 2011 at 4:23 am

    Thanks for the article.
    But I tried reading the properties from the disk e.g If I want to load the properties from C:\projects
    I tried using

    But it is not working..
    Any help will be appreciated.

  • 31. Rippon  |  June 15th, 2011 at 4:29 am

    sorry the code above is

  • 32. Rippon  |  June 15th, 2011 at 4:31 am

    Sorry Guys ,I wasnt using code tags which caused my code not displaying.Code I tried was
    </code

  • 33. Rippon  |  June 15th, 2011 at 4:37 am

    Sorry guys the code
    file:///c:/datasource.properties works fine and I Am able to load the properties external to war
    I had messed some other thing that was causing this not working.

  • 34. alsky  |  July 16th, 2011 at 1:44 pm

    Thank you mate, you made my day.

  • 35. java guy  |  August 29th, 2011 at 2:27 pm

    Thanks, you made my day * 2

  • 36. Abdulkadir  |  September 16th, 2011 at 2:28 am

    Thank you very much, you saved my day.

  • 37. Kurosaki  |  September 17th, 2011 at 1:04 pm

    Hi , cool , please can you make exmaple of any scenrio/option you mentioned using Spring 3 ?
    encrypt part wasn’t so clear ,
    and genral question , why to use properties file at all ? it’s just another file , we can use Spring 3 XML property definition and use EL expression for example …. and why to make more than 1 file ? why not merge all into 1 file?
    Thanks

  • 38. Asif  |  October 9th, 2011 at 1:29 am

    Hello Ben, thanks for this great help article. Can you please suggest something about my below problem. I was trying to load the environment variable from another property file.

    I am try to do as below. Does this have any problem? Although I get the error that ${app.env}.properties is not found why is this so. Thanks.

    The env.properties file has this
    app.env=app.test

  • 39. Jasper  |  October 30th, 2011 at 4:11 am

  • 40. Aneesh Sebastian  |  November 14th, 2011 at 3:34 am

    Finally what is the conclusion of dynamic property binding in spring3? Any one got solution? My application needs to refer some property files on login action rather than application start up.Please let me know if any of you has a solution.

  • 41. How to access Environment&hellip  |  December 1st, 2011 at 3:02 pm

    [...] more in-depth look at property files can be found here. Share this:TwitterFacebookEmailPrintRedditDiggLinkedInStumbleUponLike this:LikeBe the first to [...]

  • 42. Nik  |  December 5th, 2011 at 4:15 am

    Hey, Ben!
    You made my day! (or two)
    Thank you very much!

    Maybe it will be useful for someone.
    If you want to transfer you property from main argument (System[] args) to spring application context xml file, do following:
    1. in your xml file use your property
    Example:
    (bean …)
    (property name=”logFileName” value=”${my.env}” /)
    (/bean)
    2. in main() add this line
    System.setProperty(“my.env”, args[0]);
    3. Done! It was easy.

    Attension: On next launch of program, if you delete setProperty(“my.env… line, this property will be null.

  • 43. Nagababu  |  December 28th, 2011 at 2:53 am

    hey ben,
    Can we configure the application-config-file based on user selection in GUI lavel.
    for example if i have combo box with some specified options like 1,2,3
    if i select 1 our application use the configfile1 to connect db

    please give the reply as soon as possible.

  • 44. Ben Northrop  |  December 30th, 2011 at 11:06 am

    Thanks everyone for the feedback! I’m glad this post has been helpful.

    Also, I’m sorry (Nagababu, etc.) that I haven’t replied to specific questions. Maybe StackOverflow would be a better forum for quicker feedback? Thanks again.

  • 45. Keny  |  January 25th, 2012 at 3:28 am

    Thanks Ben,its really helpfull

    As i want to keep my .properties file out side src folder(to exclude it from jac)

    now i gave a code of

    (filemanage is prjct name)
    here i am getting an exception of could nt load properties nested exception

    did i give anything wrong here

    Any help will be appreciated

    Thanks

  • 46. Keny  |  January 25th, 2012 at 3:33 am

    well i am sorry i dont see my code, that is why giving once again

  • 47. Keny  |  January 25th, 2012 at 3:38 am

    (bean id=”placeholderConfig”)

    class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”)

    (property name=”location”

    value=”file:${/home/dev06/Java_Works/filemanage}/Configuration.properties” /)

    (/bean)

  • 48. shasr  |  January 30th, 2012 at 10:41 am

    Hi Ben…Thank you so much for this wonderful article.

    Joshua , This link may be helpful for you

    https://jira.springsource.org/browse/SPR-3030

  • 49. Bhasker  |  February 12th, 2012 at 11:43 pm

    Thanks Ben, it really helpd me…

  • 50. Properties und Umgebungsv&hellip  |  March 18th, 2012 at 5:36 am

    [...] Summa: 6 Tips for Managing Property Files with Spring [...]

  • 51. Tarun  |  August 7th, 2012 at 11:26 am

    Thanks a lot Ben. This was really helpful.

  • 52. Nic  |  October 3rd, 2012 at 4:32 am

    Hi

    Tomcat server.xml is configured:

    In applicationContext.xml I have:
    to result to classpath:META-INF/spring/dev/*.properties

    When starting tomcat, the properties files can’t be located.
    Spring exception with error:
    Could not resolve placeholder ‘database.driverClassName’ (which is a property in database.properties)

    Am I missing something?
    Should ${server_name} be resolved to ‘dev’ by just using ?

    Thanks
    Nic

  • 53. Gevorg  |  January 9th, 2013 at 4:05 pm

    Thanks Ben, I’d like to know what you (or anybody else) think about an additional option to set “environment specific” properties. I was thinking about using a system environmental variable what could be easily accessed with Java 5 ‘System.getenv()’. This would be a very simple way to access a ‘machine specific’ property.

    For instance, by using something like ‘System.getenv(“MY_APP_HOME”) + my_app_properties.properties’ I could access different machine dependent file by setting MY_APP_HOME on my machines. This would be helpful for instance when switching from a windows based development environment to a Linux based production one. I’m sure that Spring offers some nice ways to access the environmental variables as well.

  • 54. anand  |  July 2nd, 2013 at 3:11 pm

    hi

    I am not able to reload properties file dynamically if any sample code .Please provide me

  • 55. Binh Thanh Nguyen  |  February 16th, 2014 at 10:15 pm

    Thanks, nice post

  • 56. Terrance  |  July 25th, 2014 at 11:34 pm

    The drinking wateer has ɑ staabilizing аnd relaxin еffect
    օn үοur joints. Ҭake repeated breaks, lie ɗօwn fοr ѕome time, and warn Ƅy ʏourself օn structural
    power. Attempt tօ follow thе simple ideas and finest techniques
    that cɑn support уߋu manage
    thе destructive effects of strain.

  • 57. makanan yang membuat subur  |  July 26th, 2014 at 6:48 am

    The person wɦо has died ɦɑs tο bbe
    buried аs ѕoon ɑs probable аnd fߋr tҺe
    duration οff daylight. Secific pregnancy recommendations
    ann anticipating mother օught tߋ ߋften hold іn their brain. Checklist аll appoointments аnd tasks оn ƴοur
    calendar, աhich yyou need to maintain ԝith уօu аt household ɑnd operate.

Leave a Comment

Required

Required, hidden


6 + six =

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed

© 2010-2014 Summa All Rights Reserved