A previous post described the process for registering a custom PropertySource in a Spring 3.1 application. Part 1 covered registering the custom PropertySource in a stand-alone Spring application. As part of building out an example, I also wanted to be able to test the custom PropertySource in a JUnit test case - the kind of test case you would write when doing integration testing.
In the stand-alone example, the important part of the code involved registering the custom PropertySource after an application context was created, but before the beans in the context are instantiated and their properties set (including the resolving of any property placeholders in property settings). Since the code in the stand-alone example is in full control of creating and setting up the application context, adding the custom PropertySource to the context was straight-forward.
Spring provides the TestContext framework to make setting up JUnit integration test cases fast and easy. With Spring 3.1, the TestContext framework was updated to support some of the major 3.1 themes such as Java configuration and Bean Profiles. Implementations of the ContextLoader interface are responsible for setting up the application context, and the @ContextConfiguration annotation applied to the test case class gives control over how the context is loaded. Since most of the work of setting up the application context is done by a ContextLoader implementation, it takes a bit more work to manipulate the context after it is created but before it is refreshed.
The trick to making this work is to leverage a hook that is implemented in one of the classes in the ContextLoader heirarchy - the customizeContext() method. By providing your own implementation of the ContextLoader and overriding the customizeContext() method, you get the chance to manipulate the context before it is refreshed.
The attributes used with the @ContextConfiguration annotation determine the subclass of AbstractGenericContextLoader that Spring uses to load the context. Here is an example of an integration test case that uses XML configuration:
The "loader" attribute of the @ContextConfiguration is the most important part of this test case. By default, using the "locations" attribute of @ContextConfiguration causes the Spring to load the application context using a GenericXmlContextLoader. The "loader" attribute is used to specify an application-specific subclass of GenericXmlContextLoader that overrides the customizeContext() method. Using the same RedisPropertySource implementation and XML configuration file from Part 1, this ContextLoader will instantiate and register the custom PropertySource into the application context:
That's it! As usual, Spring provides just enough extension points in the just right places to get the job done.
All the code listed here is available in a runnable project in GitHub. The GitHub project also shows all the configuration using Java config in addition to the XML config shown here.
Thanks for great article. Any plans for having this write up for web application trying to use the same concept.
ReplyDeleteAs requested... http://scottfrederick.blogspot.com/2012/05/custom-property-source-in-spring-31.html
DeleteI am trying to supply a runtime name of the file (my message queue.properties file differs for my different environment)
ReplyDeleteBut I am not able to set the $(hostname} with the name of my hostname for spring application context to load it dynamically.
If you have pointers for the same that would be really helpful