Badboy Software

Stripes ImportProperties Annotation

Stripes is one of my favorite web frameworks. In my opinion, it demonstrates one of the best examples of simplicity combined with power in the Java space. Stripes is used heavily in a key Badboy Software product, Wave Test Manager.

However Stripes does have one aspect that rubs me the wrong way, which is that it forces all validation information to be declared directly on the view class, which, while certainly having some arguments in favour of it, also has a very problematic downside in that it is very difficult to reuse sets of common validation parameters across action beans. There are workarounds: for example, you can use inheritance to share common validations between separate action beans by giving them all a common base class. However this is a distasteful use of inheritance and quickly becomes problematic once you identify more than a few sets of common fields that you need to validate, particularly as and mixing and matching is not possible due to Java's support of only single inheritance.

I also run into another similar problem very frequently with Stripes, which is how to map parameters more cleanly either for my own set of aesthetics, or to a fixed external specification that doesn't match Stripes expectations. For example, I have a number of actions that should accept a set of OAuth parameters. To do this, I create a common Java Bean class called OAuthParameters and I embed it in each action that needs to support OAuth. However to access that bean Stripes insists that I prefix it with a field name in Java Bean property format, which is incompatible with the OAuth specification. If I call my bean oauthParams then Stripes wants to see parameters in the form 'oauthParams.oauth_token=...', etc., whereas the OAuth specification wants to send just 'oauth_token=...'. For this too, there is a workaround: I can declare getters and setters directly on my ActionBean class that "pass through" values to the internal OAuth bean. It works - but it's ugly, time consuming and error prone.

ImportProperties Annotation

Neither of these problems is crippling, but both leave a bad taste in my mouth, which is not something I've come to expect when using Stripes! So much so, that I decided to scratch this itch myself and made a patch to Stripes to fix both problems in one go with a new annotation: ImportProperties. You can apply it to a field and Stripes then "imports" all the properties from that field into the "namespace" of the action bean. These then behave exactly as if they were declared directly on the top level action bean. The import also brings with it any validations that are declared on the child bean, and these can be nested recursively.

Example

This example is in Groovy, for brevity:

  class FooActionBean implements ActionBean {
    @ImportProperties
    Person person;
  }
 
  class Person {
    @Validate(required=true,minvalue=0)
    int age;
 
    @ImportProperties
    Name name;
  }
 
  class Name {
    @Validate(required=true,maxlength=60)
    String firstName;
 
    @Validate(required=false,maxlength=60)
    String middleName;
    
    @Validate(required=true,maxlength=60)
    String lastName;
  }

Here FooActionBean is importing properties from a bean (Person) which in turn is importing properties from another bean (Name). The imports allow all the parameters to be bound at the top level using their names without any prefixes to navigate the bean path. So a query string such as this will work:

  ?age=30&firstName=John&lastName=Smith

The validations are imported too, so the following will fail (because lastName is required):

  ?age=30&firstName=John

The concept here is analogous to how imports work in the Java language itself: without an import you access a class by spelling out its fully qualified name, but with an import you can reference it without qualification.

Using this annotation we have solved both of the above problems: we no longer have a problem in reusing validations and we have also enabled a much cleaner and simpler mapping of the URL or POST parameters that will interact with our Stripes action.

Links

Note: these are created against the Stripes trunk as of Wed Mar 10, 2010. This roughly corresponds to Stripes 1.5.3.


Badboy Website Copyright Badboy Software, 2011