This post is the third in a series of posts showing examples of registering a custom property source in Spring 3.1, where the property source requires non-trivial initialization of its own. Part 1 showed initialization of a stand-alone application, and Part 2 showed initialization of integration tests. This part will show how to initialize a custom property source in a Spring MVC web application.
Spring 3.1 introduced a very convenient hook for customizing the application context in a Spring web application - the ApplicationContextInitializer interface. An ApplicationContextInitializer can be used to set active profiles and register custom property sources, among other things.
Here is an example of an ApplicationContextInitializer that registers the RedisPropertySource introduced in Part 1.
Just like in the stand-alone example from Part 1, an ApplicationContext is created and initialized in order to wire up the components of the custom property source. This example uses the same property-source-context.xml configuration file from Part 1.
The ApplicationContextInitializer is registered with the Spring MVC servlet by adding a stanza to the web.xml file like this:
An alternative to adding the context-param stanza to web.xml is to implement a WebApplicationInitializer and add the ApplicationContextInitializer programmatically.
The JavaDoc for WebApplicationInitializer is a great source of documentation on programmatically configuring the servlet context. In this example, most of the servlet context configuration is in web.xml, showing that the two approaches can be combined.
The last interesting part of this example is a Controller to show the property placeholder values injected into the GreetingService from Part 1:
For the sake of simplicity, this example just returns a String without using a view. Like with the stand-alone example, the values returned from the GreetingService are resolved against a properties file included with the project. These default values can be overridden by setting operating system environment variables, setting Java command line options, or by starting a Redis server as described in Part 1.
The code for all three parts of this series 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.
Mostly how-tos and musings about software development with Java, Groovy, Spring, and Grails.
SyntaxHighlighter
Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts
Wednesday, May 9, 2012
Tuesday, March 20, 2012
Custom PropertySource in Spring 3.1 - Part 2
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.
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.
Monday, March 12, 2012
Custom PropertySource in Spring 3.1 - Part 1
One of the improvements made to the Spring Framework in the 3.1 release is in the area of property placeholders. Chris Beams explains how the new unified property management system works in a blog posting on the SpringSource community site.
Several implementations of the new PropertySource interface are provided with the framework. PropertySource implementations backed by Java system properties and operating system environment variables are registered by default. If you specify one or more properties files using the <context:property-placeholder> tag in an XML configuration file or using the @PropertySource annotation on a Java config @Configuration class, the framework registers a PropertySource implementation backed by the specified files.
As Chris described, you can also register your own custom PropertySource implementations. This would be useful if you need bean properties to be stored in an external data source so they can be controlled outside of the application deployment process, or if you need properties to be encrypted or encoded for security reasons.
I decided to develop a custom PropertySource in a sample application. This PropertySource has some non-trivial bootstrapping of its own that needs to be done before it can be used, and Spring beans and dependency injection are used to bootstrap the PropertySource. The custom PropertySource must be instantiated, configured, and registered into to the application context containing the property placeholders before the application context is refreshed to make sure the property placeholders are resolved against the custom PropertySource.
To test this, I created a trivial bean with a few String properties:
and created a Spring XML config file named "app-context.xml" to instantiate the bean and set the properties:
When the GreetingService bean is instantiated, the Spring container will resolve the ${greeting.hello} and ${greeting.welcome} property placeholders and replace them with any specified text.
I then created a very simple Java main to bootstrap a Spring application context and show the properties injected into the bean:
With all this in place, I can run the GreetingApp class and play with setting the ${greeting.hello} and ${greeting.welcome} properties in environment variables, Java system properties, and properties files.
Next comes the custom PropertySource. I decided to use Redis as a backing store for configurable properties. Since Redis is a key-value store, it is a very natural fit for this example. I also decided to use Spring Data Redis to access the Redis data store. With Spring Data Redis, the code for the custom PropertySource was very simple. The PropertySource interface expects implementations to delegate to a "source" object to encapsulate the property values, so I created a RedisPropertySource which delegates to a RedisRepository. The RedisRepository in turn uses one of the RedisTemplate classes provided by Spring Data Redis.
Here is the code for the RedisPropertySource:
and the code for the RedisRepository:
Since the PropertySource bean and all related beans must be instantiated and wired together before the application beans can be instantiated, the PropertySource configuration goes in its own Spring XML config file named property-source-context.xml:
The application bootstrapping code is changed to instantiate the PropertySource bean and register it with the application's context:
The important thing to notice in this second version of the GreetingAppXmlConfig class is in the createAppContext() method. A second parameter is passed to the ClassPathXmlApplicationContext constructor to prevent the application context from being "refreshed" when it is created. This means the XML config file will be read and validated, but the beans defined in the context will not be created yet. The custom PropertySource is then registered with the application context, and the context is manually refreshed.
Of course, a Redis server has to be running and accessible before the GreetingApp main is run. The Redis command line client can be used to set and clear "greeting.hello" and "greeting.welcome" keys in the Redis server to test the RedisPropertySource. This example assumes the Redis server is running on "localhost" on the default port, but those values can be changed by setting properties of the JedisConnectionFactory bean in the property-source-context.xml file.
In the end, the code to make a custom RedisPropertySource work is very simple. The configuration and bootstrapping is also simple once the right sequence of events is understood.
I also worked on registering a custom PropertySource in a JUnit test case, which also took some figuring to get it right. Since this post has gotten pretty long, I'm going to continue that in a Part 2 post.
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.
Several implementations of the new PropertySource interface are provided with the framework. PropertySource implementations backed by Java system properties and operating system environment variables are registered by default. If you specify one or more properties files using the <context:property-placeholder> tag in an XML configuration file or using the @PropertySource annotation on a Java config @Configuration class, the framework registers a PropertySource implementation backed by the specified files.
As Chris described, you can also register your own custom PropertySource implementations. This would be useful if you need bean properties to be stored in an external data source so they can be controlled outside of the application deployment process, or if you need properties to be encrypted or encoded for security reasons.
I decided to develop a custom PropertySource in a sample application. This PropertySource has some non-trivial bootstrapping of its own that needs to be done before it can be used, and Spring beans and dependency injection are used to bootstrap the PropertySource. The custom PropertySource must be instantiated, configured, and registered into to the application context containing the property placeholders before the application context is refreshed to make sure the property placeholders are resolved against the custom PropertySource.
To test this, I created a trivial bean with a few String properties:
and created a Spring XML config file named "app-context.xml" to instantiate the bean and set the properties:
When the GreetingService bean is instantiated, the Spring container will resolve the ${greeting.hello} and ${greeting.welcome} property placeholders and replace them with any specified text.
I then created a very simple Java main to bootstrap a Spring application context and show the properties injected into the bean:
With all this in place, I can run the GreetingApp class and play with setting the ${greeting.hello} and ${greeting.welcome} properties in environment variables, Java system properties, and properties files.
Next comes the custom PropertySource. I decided to use Redis as a backing store for configurable properties. Since Redis is a key-value store, it is a very natural fit for this example. I also decided to use Spring Data Redis to access the Redis data store. With Spring Data Redis, the code for the custom PropertySource was very simple. The PropertySource interface expects implementations to delegate to a "source" object to encapsulate the property values, so I created a RedisPropertySource which delegates to a RedisRepository. The RedisRepository in turn uses one of the RedisTemplate classes provided by Spring Data Redis.
Here is the code for the RedisPropertySource:
and the code for the RedisRepository:
Since the PropertySource bean and all related beans must be instantiated and wired together before the application beans can be instantiated, the PropertySource configuration goes in its own Spring XML config file named property-source-context.xml:
The application bootstrapping code is changed to instantiate the PropertySource bean and register it with the application's context:
The important thing to notice in this second version of the GreetingAppXmlConfig class is in the createAppContext() method. A second parameter is passed to the ClassPathXmlApplicationContext constructor to prevent the application context from being "refreshed" when it is created. This means the XML config file will be read and validated, but the beans defined in the context will not be created yet. The custom PropertySource is then registered with the application context, and the context is manually refreshed.
Of course, a Redis server has to be running and accessible before the GreetingApp main is run. The Redis command line client can be used to set and clear "greeting.hello" and "greeting.welcome" keys in the Redis server to test the RedisPropertySource. This example assumes the Redis server is running on "localhost" on the default port, but those values can be changed by setting properties of the JedisConnectionFactory bean in the property-source-context.xml file.
In the end, the code to make a custom RedisPropertySource work is very simple. The configuration and bootstrapping is also simple once the right sequence of events is understood.
I also worked on registering a custom PropertySource in a JUnit test case, which also took some figuring to get it right. Since this post has gotten pretty long, I'm going to continue that in a Part 2 post.
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.
Friday, April 30, 2010
Introducing SpringDoclet
As the Spring Framework evolves, one of the areas that gets better with each release is annotation-based application configuration and wiring. Using Spring annotations in Java classes along with component scanning helps fight the XML bloat that can make some applications difficult to work with.
However, one downside to annotation-based configuration is that there is no central place to find all Spring-managed beans in an application. With XML Spring configuration, all the bean definitions and their injected dependencies can be seen in one or more XML files (if you have the patience to wade through all the XML required for a larger system).
Reducing the XML bloat and moving the wiring closer to the code is worth the loss of visibility in my opinion.
IDEs can help with the visibility issue. SpringSource Tool Suite (or STS, available as a stand-alone Eclipse distribution or as a set of Eclipse plugins) provides a Spring Explorer view which shows components, MVC request mappings, AOP advices, auto-wired dependencies, and more. IntelliJ IDEA has some nice Spring-related features, including navigation between beans and their auto-wired dependencies via gutter icons, but (as far as I know) it doesn't have one view to show all Spring-managed components and mappings in an application.
On the Spring Framework community forums, the user @petrp suggested a tool to generate documentation for controllers and request mappings in a Spring MVC application. The more I thought about this idea the more I liked it. Generating an HTML report from the source code would be another good way to mitigate the visibility issue.
And so, SpringDoclet was born. SpringDoclet is a Javadoc doclet designed to generate an HTML report as part of a project's build process. The report lists all classes decorated with any of the annotations from the org.springframework.stereotype package (@Component, @Service, @Repository, @Controller). It also lists all @RequestMappings with the HTTP method, URL template, and implementing class. Classes listed on the report can be cross-linked to standard Javadoc HTML reports or other source code reports like JXR.
I decided to implement this as doclet so I could get the source code scanning for free, along with integration with Maven, Ant, and other tools that already support Javadoc.
I also chose to implement the doclet in Groovy. I knew the code would need to generate HTML, and Groovy's MarkupBuilder makes that chore a breeze compared to Java. I'm still fairly new to Groovy, and using a new language on a real project (even if it is a small one) is the best way for me to really learn it. I tried to do everything the Groovy way, learned a few tricks along the way, and became much more comfortable with the language.
The code for SpringDoclet is at http://github.com/scottfrederick/springdoclet. For now, you will have to build the doclet before using it. Instructions for building and using SpringDoclet are in the README file on GitHub.
Give it a try, and let me know what you think. Please comment on this post with any feedback, suggestions for enhancements, or (gasp!) bugs.
However, one downside to annotation-based configuration is that there is no central place to find all Spring-managed beans in an application. With XML Spring configuration, all the bean definitions and their injected dependencies can be seen in one or more XML files (if you have the patience to wade through all the XML required for a larger system).
Reducing the XML bloat and moving the wiring closer to the code is worth the loss of visibility in my opinion.
IDEs can help with the visibility issue. SpringSource Tool Suite (or STS, available as a stand-alone Eclipse distribution or as a set of Eclipse plugins) provides a Spring Explorer view which shows components, MVC request mappings, AOP advices, auto-wired dependencies, and more. IntelliJ IDEA has some nice Spring-related features, including navigation between beans and their auto-wired dependencies via gutter icons, but (as far as I know) it doesn't have one view to show all Spring-managed components and mappings in an application.
On the Spring Framework community forums, the user @petrp suggested a tool to generate documentation for controllers and request mappings in a Spring MVC application. The more I thought about this idea the more I liked it. Generating an HTML report from the source code would be another good way to mitigate the visibility issue.
And so, SpringDoclet was born. SpringDoclet is a Javadoc doclet designed to generate an HTML report as part of a project's build process. The report lists all classes decorated with any of the annotations from the org.springframework.stereotype package (@Component, @Service, @Repository, @Controller). It also lists all @RequestMappings with the HTTP method, URL template, and implementing class. Classes listed on the report can be cross-linked to standard Javadoc HTML reports or other source code reports like JXR.
I decided to implement this as doclet so I could get the source code scanning for free, along with integration with Maven, Ant, and other tools that already support Javadoc.
I also chose to implement the doclet in Groovy. I knew the code would need to generate HTML, and Groovy's MarkupBuilder makes that chore a breeze compared to Java. I'm still fairly new to Groovy, and using a new language on a real project (even if it is a small one) is the best way for me to really learn it. I tried to do everything the Groovy way, learned a few tricks along the way, and became much more comfortable with the language.
The code for SpringDoclet is at http://github.com/scottfrederick/springdoclet. For now, you will have to build the doclet before using it. Instructions for building and using SpringDoclet are in the README file on GitHub.
Give it a try, and let me know what you think. Please comment on this post with any feedback, suggestions for enhancements, or (gasp!) bugs.
Subscribe to:
Posts (Atom)