SyntaxHighlighter

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.

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.

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
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 ~.web
Next, 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:run
The 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.jar
This 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=pizza
The 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.jar
Finally, re-run the Maven command to start the application in an embedded Tomcat server.
~/projects/roo-pizza> mvn tomcat:run
Once 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:
<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.

A Better Spring Meta-validator

Spring MVC 3 has a very rich set of features for binding and validating input data to command objects, including class-based validation and annotation-based validation.

Custom class-based validators can be registered with Spring MVC in one of two ways (as described in the documentation): configured in each @Controller class using the @InitBinder method, or configured at the application level using the "mvc:annotation-driven" tag with a "validator" argument. Using the per-controller approach gives lots of control when each Controller needs its own validators, but adding all those @InitBinder methods can become tedious (and therefore error-prone).

In a previous post, I showed a method for creating a meta-validator that could be configured as the global application-level validator, and would in turn delegate to other configured validators as appropriate for the command object type. This post is a refinement if that idea, giving more control over which validators are automatically discovered and globally available.

This flexibility is achieved by using annotations on the validators that should be globally available through the meta-validator, as in this example (stolen from the Spring documentation):


The first line is the part that is new - the @ValidatorComponent annotation. I don't love the name, but "Validator" was already taken and having the interface and annotation share a name would be confusing.

With the supporting code below, any classes that extend org.springframework.validation.Validator and also have the @ValidatorComponent annotation on them are automatically detected by the meta-validator and called when appropriate. Validators without the annotation are ignored by the meta-validator, and can be configured individually in @InitBinder methods if required.

Here is the code that makes this work. First, the annotation itself:


This annotation is annotated with @Component, which means validators using this annotation are also eligible for component scanning.

And, at last, the meta-validator class:


Using @Autowired with a collection as a way to get all beans of a certain type was a fairly recent discovery for me, and I like it much better than the older method of extending ApplicationContextAware and asking the ApplicationContext for "beansOfType". Otherwise this code is pretty straight-forward - it just scans the list of injected Validator beans and remembers any that have the annotation on them.

The setValidators() method is provided for the case where third-party validators also need to be registered with the meta-validator, such as the LocalValidatorFactoryBean needed to configure JSR-303 bean validation support.

Here is an example of a Spring XML configuration file that wires all this together:


That's it! Now all you have to do is write your validator classes (and their unit tests), annotate them with @ValidatorComponent, and let the framework do the rest.