Sunday, February 22, 2009

Tips regarding Spring's PropertyPlaceholderConfigurer

Most of the Spring users are familiar with the PropertyPlaceholderConfigurer that is used to replace placeholders defined in the context xml with the actual values. In this post I want to describe some of its less known features.

Ignore Unresolvable Placeholders


By default a PropertyPlaceholderConfigurer throws an exception, when it completes resolving the placeholders, and there are still unresolved placeholders left. However, suppose that your application is built from the several modules, which are combined to the same spring context. Each module has its own PropertyPlaceholderConfigurer and simply cannot resolve the others. You won't like it to fail the whole application loading, right?

Setting property ignoreUnresolvablePlaceholders to true will tell the PropertyPlaceholderConfigurer to ignore the unresolvable placeholders.

In general, I would suggest for all modules to set this property to true to ensure that none of the modules fails the whole system.

Placing validating PropertyPlaceholderConfigurer


"But" - you may say - "I still want to know that the context is incorrect. How can I do it, if all the PropertyPlaceholderConfigurers are set to ignore the unresolvable placeholders?"

To do so, you'll need to place a validating PropertyPlaceholderConfigurer, which task will be to run after all PropertyPlaceholderConfigurers completed their job and check, if all the properties were resolved. Its definition is very simple and won't include any special configuration.

"But" - you should ask now - "I don't know the order in which the PropertyPlaceholderConfigurers run".

Actually it's untrue and you know the order, you just don't know about it:

Setting the Order of PropertyPlaceholderConfigurers


PropertyPlaceholderConfigurer is a BeanFactoryPostProcessor that implements PriorityOrdered interface. This cause it to run before the BeanFactoryPostProcessors that implement Ordered interface and they run before the BeanFactoryPostProcessors that don't implement these interfaces at all.
Both PriorityOrdered and Ordered objects implement a method getOrder that returns an order in which the objects should be applied. Zero means a highest priority. Integer.MAX_VALUE means the lowest priority.
By default the order is set to Integer.MAX_VALUE.
And what happens if two PropertyPlaceholderConfigurer have a same priority? They run in the order of their definition in the context xml file.

Overriding Properties Defined in the PropertyPlaceholderConfigurer


Consider the following situating: you are using some module, which has defined its own PropertyPlaceholderConfigurer and you want to override a property. Without "order" and "ignoreUnresolvablePlaceholders" properties it can be quite cumbersome. However, when using "order" and "ignoreUnresolvablePlaceholders" it becomes very simple:
  1. Define a PropertyPlaceholderConfigurer with order set to a lower order (higher priority) then a PropertyPlaceholderConfigurer in the module.
  2. Set ignoreUnresolvablePlaceholders to true, since you don't want to override all the properties. Moreover, there are may be additional modules, who have their own placeholders...
  3. Define the properties you want to override.

Summary


When using a PropertyPlaceholderConfigurer you need to identify if your product is a stand alone application or a module in a bigger system. The default PropertyPlaceholderConfigurer is good for a stand alone application. But if you are writing the module make sure that:
  1. The order property should be set between 1 and Integer.MAX_VALUE. I would suggest setting it somewhere between 10000 and Integer.MAX_VALUE-10000 to ensure that anyone can insert a PropertyPlaceholderConfigurer both before and after yours. I assume that none system would have more then 10000 PropertyPlaceholderConfigurers.
  2. Set ignoreUnresolvablePlaceholders to true, to ensure that your module won't fail because of others placeholders. Your placeholder is still responsible to fill the placeholders in your module and I would recommend to create a unit test, which will hold a validating PropertyPlaceholderConfigurer and fail if someone forgets to resolve a placeholder.
  3. The main system should include the validating PropertyPlaceholderConfigurer to ensure that all modules have filled their placeholders.
  4. Include module name and version in the properties names. This will reduce conflicts and backward compatibility problems. Example: if module has name "example" and version is "4.1", make all properties to start with "example.4.1" or "example_4_1". Meaning "debug" propery would be called "example.4.1.debug" or "example_4_1_debug".


Recommended Reading

1. Spring in Action
2. Effective Java
3. Joel on Software: And on Diverse and Occasionally Related Matters That Will Prove of Interest to Software Developers, Designers, and Managers, and to Those Who, Whether by Good Fortune or Ill Luck, Work with Them in Some Capacity
4. Small Gods

3 comments:

Anton said...

Hey, this one is 3rd result in google search for "PropertyPlaceholderConfigurer"! Way to go! :)

James Selvakumar said...

Fantastic post! Found this after spending some frustrating hours. A "must have" item in your bookmarks.

Amit Jha said...

Thanks man, it worked for my case. I was using as application and it has already defined the propertyPlacehoder. I just need to define order in my configuration and it works.