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.
Scott Frederick's Blog
Mostly how-tos and musings about software development with Java, Groovy, Spring, and Grails.
SyntaxHighlighter
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.
Tuesday, November 29, 2011
Groovy-DDLUtils
Apache DDLUtils is a small but very useful library for migrating data and translating SQL schemas from one SQL database to another. DDLUtils includes support for an impressive list of SQL dialects, including all the major commercial and open-source RDBMS products.
The DDLUtils project provides a jar file containing the library code and a set of Ant tasks that use the library to perform common tasks - exporting a schema from a live database to a text file, and importing a schema from a text file to a live database. I haven't written an Ant XML build file for several years, and after some time away I find the Ant XML very verbose and cumbersome to work with.
Looking for an easier and more accessible way harness the power of DDLUtils, I turned to Groovy. Groovy scripts are a great way to leverage Java APIs in an expressive way, often with just a few lines of code. After using a few special-purpose Groovy scripts with DDLUtils, I decided to generalize the script to make it more configuration-driven and therefore more usable. The result is the Groovy-DDLUtils project.
The Groovy-DDLUtils project page on GitHub includes documentation on using and customizing the Groovy script, so I won't repeat that here. Take a look, give it a try, and send any feedback or enhancements suggestions via issues on GitHub, or comments on this blog.
The DDLUtils project provides a jar file containing the library code and a set of Ant tasks that use the library to perform common tasks - exporting a schema from a live database to a text file, and importing a schema from a text file to a live database. I haven't written an Ant XML build file for several years, and after some time away I find the Ant XML very verbose and cumbersome to work with.
Looking for an easier and more accessible way harness the power of DDLUtils, I turned to Groovy. Groovy scripts are a great way to leverage Java APIs in an expressive way, often with just a few lines of code. After using a few special-purpose Groovy scripts with DDLUtils, I decided to generalize the script to make it more configuration-driven and therefore more usable. The result is the Groovy-DDLUtils project.
The Groovy-DDLUtils project page on GitHub includes documentation on using and customizing the Groovy script, so I won't repeat that here. Take a look, give it a try, and send any feedback or enhancements suggestions via issues on GitHub, or comments on this blog.
Friday, November 11, 2011
Wrapping a Groovy script with Gradle
Groovy is great for scripting Java APIs in a very simple and expressive way. Providing utilities written in Groovy can sometimes be met with resistance, as any user of such a script first needs to download the appropriate version of Groovy and any other jar file dependencies. Grape helps with the dependency problem, but relies on all jar file dependencies being in a dependency repository, and the user of the script having access to a repository.
The Cookbook section of the Groovy site includes a script called WrappingGroovyScript that solves the Groovy and external jar dependency problems. As the page says, WrappingGroovyScript creates a self-contained jar file with your Groovy script, the Groovy runtime, and all other dependencies nicely bundled together. A user of your utility can then just run the generated jar using "java -jar". Very nice.
Then I got started thinking that Gradle should be able to do the same type of bundling for Groovy scripts. Here is a Gradle script that accomplishes that goal.
To use the script, just copy the contents of the Gist into your own build.gradle file, change the mainClassName, and add your dependencies.
That's it! Very simple and elegant, even smaller than the WrappingGroovyScript solution.
The Cookbook section of the Groovy site includes a script called WrappingGroovyScript that solves the Groovy and external jar dependency problems. As the page says, WrappingGroovyScript creates a self-contained jar file with your Groovy script, the Groovy runtime, and all other dependencies nicely bundled together. A user of your utility can then just run the generated jar using "java -jar". Very nice.
Then I got started thinking that Gradle should be able to do the same type of bundling for Groovy scripts. Here is a Gradle script that accomplishes that goal.
To use the script, just copy the contents of the Gist into your own build.gradle file, change the mainClassName, and add your dependencies.
That's it! Very simple and elegant, even smaller than the WrappingGroovyScript solution.
Monday, October 24, 2011
SQLFire and Spring Roo
SQLFire is an exciting new member of the VMware vFabric family, joining the likes of tc Server, GemFire, Hyperic, and RabbitMQ. SQLFire provides an in-memory high-performance data fabric with a familiar SQL interface.
Chris Harris wrote a series of blog entries about getting starting with SQLFire, using Grails to quickly generate a test application. In the same spirit as Chris' articles, this posting will show the steps for creating a simple Spring Roo application that uses SQLFire for data persistence.
The Roo reference docs contain a great tutorial for building a "pizza shop" application with Roo. This article will use the pizza shop tutorial application as a starting point. If you want to get familiar with Roo you can go through the full tutorial first, and then come back to this article. If you just want to jump into SQLFire, everything you need to get the application running is contained here. This article assumes that you already have Roo and all of its dependencies installed and working, and that you have some understanding of how to use the Roo shell.
Step 1: Create the Pizza Shop application
If you already have the Pizza Shop Roo application running, you can skip this step and go on to Step 2. If you haven't followed the Roo tutorial to create the Pizza Shop application, you can quickly create the app now.
First, copy the text in the box below and paste it into a file named "pizza.roo". This is the same set of Roo commands used in the tutorial, which will be run as a script.
pizza.roo
Use your favorite browser and navigate to the address "http://localhost:8080/pizzashop/". You should see the Roo application home screen. You can test the app by creating and listing bases, toppings, pizzas, pizza orders, etc.
Step 2: Introducing SQLFire
If you haven't already, download SQLFire from the download site. Installation is very simple. Assuming the installer package is in the root of the user home directory, run the following command.
You can use the "sqlf" command to make sure SQLFire is up and running.
Step 3: Modifying the application for SQLFire
Now that the Pizza Shop application is created and SQLFire is running, we can modify the app to use SQLFire as the database instead of the Hypersonic database suggested by the Roo tutorial. This requires editing two configuration files and making the SQLFire JDBC driver available to the application via Maven.
First, edit the file "persistence.xml", which is in the directory "/src/main/resources/META-INF" under the project root directory. Change the line containing the "hibernate.dialect" property to use the Apache Derby dialect instead of the Hypersonic (HSQL) dialect. In the example below, line 6 has been changed to use the Derby dialect. This is the only line in the file that needs to be changed (comments are omitted from the Roo-generated file for clarity).
/src/main/resources/META-INF/persistence.xml
/src/main/resources/META-INF/spring/database.properties
/pom.xml
From here, you can set up a more complex SQLFire data fabric with multiple nodes, using a peer-to-peer or locator topology, as described in the SQLFire documentation and in Chris Harris' Grails + SQLFire series.
You can also use Maven to package the application into a war file and run it in Tomcat, tc Server, or another web server.
Chris Harris wrote a series of blog entries about getting starting with SQLFire, using Grails to quickly generate a test application. In the same spirit as Chris' articles, this posting will show the steps for creating a simple Spring Roo application that uses SQLFire for data persistence.
The Roo reference docs contain a great tutorial for building a "pizza shop" application with Roo. This article will use the pizza shop tutorial application as a starting point. If you want to get familiar with Roo you can go through the full tutorial first, and then come back to this article. If you just want to jump into SQLFire, everything you need to get the application running is contained here. This article assumes that you already have Roo and all of its dependencies installed and working, and that you have some understanding of how to use the Roo shell.
Step 1: Create the Pizza Shop application
If you already have the Pizza Shop Roo application running, you can skip this step and go on to Step 2. If you haven't followed the Roo tutorial to create the Pizza Shop application, you can quickly create the app now.
First, copy the text in the box below and paste it into a file named "pizza.roo". This is the same set of Roo commands used in the tutorial, which will be run as a script.
pizza.roo
project --topLevelPackage com.springsource.roo.pizzashop persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY entity --class ~.domain.Topping field string --fieldName name --notNull --sizeMin 2 entity --class ~.domain.Base --testAutomatically field string --fieldName name --notNull --sizeMin 2 entity --class ~.domain.Pizza --testAutomatically field string --fieldName name --notNull --sizeMin 2 field number --fieldName price --type java.lang.Float field set --fieldName toppings --type ~.domain.Topping field reference --fieldName base --type ~.domain.Base entity --class ~.domain.PizzaOrder --testAutomatically field string --fieldName name --notNull --sizeMin 2 field string --fieldName address --sizeMax 30 field number --fieldName total --type java.lang.Float field date --fieldName deliveryDate --type java.util.Date field set --fieldName pizzas --type ~.domain.Pizza controller all --package ~.webNext, execute the following list of operating system and Roo commands to create a project root directory, make the project root the current directory, start the Roo shell, run the script to create the tutorial application, and run the application.
~/projects> mkdir roo-pizza ~/projects> cd roo-pizza ~/projects/roo-pizza> roo roo> script /path/to/pizza.roo Created ... (long list of Roo messages omitted) Script required 8 second(s) to execute ~.web roo> quit ~/projects/roo-pizza> mvn tomcat:runThe last command uses Maven to build the project and run the application in an embedded Tomcat server. The first time you run Maven, it may take a while to download all the dependencies for Roo and the application.
Use your favorite browser and navigate to the address "http://localhost:8080/pizzashop/". You should see the Roo application home screen. You can test the app by creating and listing bases, toppings, pizzas, pizza orders, etc.
Step 2: Introducing SQLFire
If you haven't already, download SQLFire from the download site. Installation is very simple. Assuming the installer package is in the root of the user home directory, run the following command.
~> java -jar SQLFire10Beta_Installer.jarThis will create a "SQLFire10Beta" directory under the directory the installer was run from. The "bin" directory under the install directory contains a script that is used to stop, start, and control SQLFire. Run the following commands to start a new SQLFire instance.
~/SQLFire10Beta> mkdir server1 ~/SQLFire10Beta> bin/sqlf server start -dir=server1 &The "server start" command will start a SQLFire server node with default options, using the specified directory to store state. SQLFire will be listening for JDBC connections from "localhost" only on port 1527.
You can use the "sqlf" command to make sure SQLFire is up and running.
~/SQLFire10Beta> bin/sqlf sqlf> connect client 'localhost:1527'; sqlf> show tables in sys; sqlf> quit;SQLFire should display a list of system tables that are created in each new database.
Step 3: Modifying the application for SQLFire
Now that the Pizza Shop application is created and SQLFire is running, we can modify the app to use SQLFire as the database instead of the Hypersonic database suggested by the Roo tutorial. This requires editing two configuration files and making the SQLFire JDBC driver available to the application via Maven.
First, edit the file "persistence.xml", which is in the directory "/src/main/resources/META-INF" under the project root directory. Change the line containing the "hibernate.dialect" property to use the Apache Derby dialect instead of the Hypersonic (HSQL) dialect. In the example below, line 6 has been changed to use the Derby dialect. This is the only line in the file that needs to be changed (comments are omitted from the Roo-generated file for clarity).
/src/main/resources/META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/> <property name="hibernate.hbm2ddl.auto" value="create"/> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/> <property name="hibernate.connection.charSet" value="UTF-8"/> </properties> </persistence-unit> </persistence>Next, change the "database.properties" file in the directory "/src/main/resources/META-INF/spring". All four properties in this file should be changed to match the example below.
/src/main/resources/META-INF/spring/database.properties
database.url=jdbc:sqlfire://localhost:1527/ database.driverClassName=com.vmware.sqlfire.jdbc.ClientDriver database.username=pizza database.password=pizzaThe jar file containing the SQLFire thin-client JDBC driver must be made available to the application at run-time. Since Roo uses Maven to build and package the application, we can add the SQLFire jar files as dependencies to the Pizza Shop project. To do this, edit the "pom.xml" file in the project root directory and add the following to the "<dependencies>" section of the file. At the time of this posting, SQLFire is still in beta so we will use "1.0-beta" as the version.
/pom.xml
<dependency> <groupId>com.vmware.sqlfire</groupId> <artifactId>sqlfireclient</artifactId> <version>1.0-beta</version> </dependency>The beta release of the SQLFire client jar file is not available in any public Maven repositories. The jar file is included in the SQLFire distribution, and can be installed to your local Maven repository. From the "lib" directory under the SQLFire installation directory, run the following Maven command.
~/SQLFire10Beta/lib> mvn install:install-file -DgroupId=com.vmware.sqlfire / -DartifactId=sqlfireclient -Dversion=1.0-beta / -Dpackaging=jar -Dfile=sqlfireclient.jarFinally, re-run the Maven command to start the application in an embedded Tomcat server.
~/projects/roo-pizza> mvn tomcat:runOnce again, point your browser at http://localhost:8080/pizzashop and verify that the application is running. Try creating a few entities (bases, toppings, pizzas) and use the "sqlf" client to verify that the data is being stored in SQLFire.
~/SQLFire10Beta> bin/sqlf sqlf> connect client 'localhost:1527'; sqlf> show tables in pizza; sqlf> set schema pizza; sqlf> select * from base;Next Steps
From here, you can set up a more complex SQLFire data fabric with multiple nodes, using a peer-to-peer or locator topology, as described in the SQLFire documentation and in Chris Harris' Grails + SQLFire series.
You can also use Maven to package the application into a war file and run it in Tomcat, tc Server, or another web server.
~/projects/roo-pizza> mvn package
Friday, March 11, 2011
Customizing Spring 3 mvc:annotation-driven
In Spring 3, it is very easy to configure an application with all the basic MVC components using the mvc:annotation-driven tag.
The default configuration can be customized with arguments to the mvc:annotation-driven tag (such as "validator" and "conversion-service") and other tags in the mvc: namespace. In Spring 3.0.0 the set of customization options was somewhat limited, but it has grown with each Spring release. Spring 3.1 adds a mvc:message-converters to address one of the more common customization needs.
A very common mistake developers make when they need to customize the annotation-driven configuration is to use mvc:annotation-driven and also manually define a AnnotationMethodHandlerAdapter bean with customized properties, like this:
This does not work as expected. With this configuration, you end up with two AnnotationMethodHandlerAdapter beans in your application context - one created by mvc:annotation-driven and the one created manually. The one created by the framework is used, and the one created manually is ignored.
One working solution to this problem is to remove the mvc:annotation-driven tag and instead manually define all the annotation support beans. This is not ideal, as there is not a good way to keep up with all the beans defined automatically by mvc:annotation-driven as the annotation support evolves in the framework.
The preferred solution to the customization problem is to implement a BeanPostProcessor to modify properties of the AnnotationMethodHandlerAdapter bean created by mvc:annotation-driven in-place, instead of replacing it. This is not hard to do, and provides all the flexibility needed to customize the annotation support.
Here is an example of what this solution can look like. This solution uses a very flexible class that has all the same properties as AnnotationMethodHandlerAdapter, but configures an existing HandlerAdapter instead of creating a second one. Usage of this solution would look like this:
Look closely at line 3 in the second example, since this is the only line that is different from the first example. The bean being created is a AnnotationMethodHandlerAdapterConfigurer instead of a AnnotationMethodHandlerAdapter. The Configurer class manipulates the HandlerAdapter already created by the framework, but is configured just like AnnotationMethodHandlerAdapter. The "init-method" argument to the bean definition is important, as it causes the configuration to happen after the application context is up and running.
Here is what the Configurer looks like:
There is one property of the Configurer class that does not correspond directly to a property of AnnotationMethodHandlerAdapter: "replaceMessageConverters". By default this is false, which causes any configured MessageConverters to be added to the converters already configured into the AnnotationMethodHandlerAdapter. If this property is set to true, then the automatically-configured MessageConverters are thrown away and only those injected into the Configurer will be used.
This approach will become less and less interesting as Spring 3.1 is released and mvc:annotation-driven continues to evolve. Until then, it solves a problem that a lot of developers have spent time figuring out the hard way.
The default configuration can be customized with arguments to the mvc:annotation-driven tag (such as "validator" and "conversion-service") and other tags in the mvc: namespace. In Spring 3.0.0 the set of customization options was somewhat limited, but it has grown with each Spring release. Spring 3.1 adds a mvc:message-converters to address one of the more common customization needs.
A very common mistake developers make when they need to customize the annotation-driven configuration is to use mvc:annotation-driven and also manually define a AnnotationMethodHandlerAdapter bean with customized properties, like this:
<mvc:annotation-driven/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="customArgumentResolver"> <bean class="com.example.ExampleArgumentResolver" /> </property> <property name="messageConverters"> <list> <bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter" p:marshaller-ref="marshaller" p:unmarshaller-ref="marshaller"/> </list> </property> </bean>
This does not work as expected. With this configuration, you end up with two AnnotationMethodHandlerAdapter beans in your application context - one created by mvc:annotation-driven and the one created manually. The one created by the framework is used, and the one created manually is ignored.
One working solution to this problem is to remove the mvc:annotation-driven tag and instead manually define all the annotation support beans. This is not ideal, as there is not a good way to keep up with all the beans defined automatically by mvc:annotation-driven as the annotation support evolves in the framework.
The preferred solution to the customization problem is to implement a BeanPostProcessor to modify properties of the AnnotationMethodHandlerAdapter bean created by mvc:annotation-driven in-place, instead of replacing it. This is not hard to do, and provides all the flexibility needed to customize the annotation support.
Here is an example of what this solution can look like. This solution uses a very flexible class that has all the same properties as AnnotationMethodHandlerAdapter, but configures an existing HandlerAdapter instead of creating a second one. Usage of this solution would look like this:
<mvc:annotation-driven/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterConfigurer" init-method="init"> <property name="customArgumentResolver"> <bean class="com.example.ExampleArgumentResolver" /> </property> <property name="messageConverters"> <list> <bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter" p:marshaller-ref="marshaller" p:unmarshaller-ref="marshaller"/> </list> </property> </bean>
Look closely at line 3 in the second example, since this is the only line that is different from the first example. The bean being created is a AnnotationMethodHandlerAdapterConfigurer instead of a AnnotationMethodHandlerAdapter. The Configurer class manipulates the HandlerAdapter already created by the framework, but is configured just like AnnotationMethodHandlerAdapter. The "init-method" argument to the bean definition is important, as it causes the configuration to happen after the application context is up and running.
Here is what the Configurer looks like:
public class AnnotationMethodHandlerAdapterConfigurer { @Autowired private AnnotationMethodHandlerAdapter adapter; private WebBindingInitializer webBindingInitializer; private HttpMessageConverter[] messageConverters; private PathMatcher pathMatcher; private UrlPathHelper urlPathHelper; private MethodNameResolver methodNameResolver; private WebArgumentResolver[] customArgumentResolvers; private ModelAndViewResolver[] customModelAndViewResolvers; private boolean replaceMessageConverters = false; public void init() { if (webBindingInitializer != null) { adapter.setWebBindingInitializer(webBindingInitializer); } if (messageConverters != null) { if (replaceMessageConverters) { adapter.setMessageConverters(messageConverters); } else { adapter.setMessageConverters(mergeMessageConverters()); } } if (pathMatcher != null) { adapter.setPathMatcher(pathMatcher); } if (urlPathHelper != null) { adapter.setUrlPathHelper(urlPathHelper); } if (methodNameResolver != null) { adapter.setMethodNameResolver(methodNameResolver); } if (customArgumentResolvers != null) { adapter.setCustomArgumentResolvers(customArgumentResolvers); } if (customModelAndViewResolvers != null) { adapter.setCustomModelAndViewResolvers(customModelAndViewResolvers); } } private HttpMessageConverter[] mergeMessageConverters() { return (HttpMessageConverter[]) ArrayUtils.addAll(messageConverters, adapter.getMessageConverters()); } public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) { this.webBindingInitializer = webBindingInitializer; } public void setPathMatcher(PathMatcher pathMatcher) { this.pathMatcher = pathMatcher; } public void setUrlPathHelper(UrlPathHelper urlPathHelper) { this.urlPathHelper = urlPathHelper; } public void setMethodNameResolver(MethodNameResolver methodNameResolver) { this.methodNameResolver = methodNameResolver; } public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) { this.customArgumentResolvers = new WebArgumentResolver[] {argumentResolver}; } public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) { this.customArgumentResolvers = argumentResolvers; } public void setCustomModelAndViewResolver(ModelAndViewResolver customModelAndViewResolver) { this.customModelAndViewResolvers = new ModelAndViewResolver[] {customModelAndViewResolver}; } public void setCustomModelAndViewResolvers(ModelAndViewResolver[] customModelAndViewResolvers) { this.customModelAndViewResolvers = customModelAndViewResolvers; } public void setMessageConverters(HttpMessageConverter[] messageConverters) { this.messageConverters = messageConverters; } public void setReplaceMessageConverters(boolean replaceMessageConverters) { this.replaceMessageConverters = replaceMessageConverters; } }
There is one property of the Configurer class that does not correspond directly to a property of AnnotationMethodHandlerAdapter: "replaceMessageConverters". By default this is false, which causes any configured MessageConverters to be added to the converters already configured into the AnnotationMethodHandlerAdapter. If this property is set to true, then the automatically-configured MessageConverters are thrown away and only those injected into the Configurer will be used.
This approach will become less and less interesting as Spring 3.1 is released and mvc:annotation-driven continues to evolve. Until then, it solves a problem that a lot of developers have spent time figuring out the hard way.
Subscribe to:
Posts (Atom)