Home > API and Patterns, Fluent interfaces > Using annotations for validation

Using annotations for validation

There is one common case I often come across and that’s validation of parameters. There are different situations in which you like to validate parameters, the most common case is validation of method parameters, usually performed with guard-clauses and assertions. This is not what I’d like to write about in this blog. I may come across this later. This time it’s all about annotation driven validation on fields.
In my last blog I’ve written on how to deal with long constructors, which are common if you fancy immutable objects. I’ve proposed a builder-pattern to create a fluent API for object initialization, which gives you the ability to check all fields upon construction. Let me just repeat the source code to get you up to date:

@Immutable
public final class Address{

 private final String street;
 private final String zipcode;
 private final String town;
 private final String country;

 private Address(final AddressBuilder b){
  street=b.street;
  zipcode=b.zipcode;
  town=b.town;
  country=b.country;
 }

 public String getStreet(){
  return street;
 }
 //..

 public static AddressBuilder build(){
  return new AddressBuilder();
 }
 //..

 public static class AddressBuilder{
  private final SingleThreadBarrier barrier
   = new SingleThreadBarrier(getClass());
  private String street;
  private String zipcode
  //..
  public AddressBuilder withStreet(final String street){
   barrier.pass();
   this.street=street;
   return this;
  }

  //..

  public Address noNullPropertyAllowed(){
   barrier.pass();
   if(Arrays.asList(street, zipcode, town, country).contains(null)){
     throw new NullPointerException();
   }
   return new Address(this);
  }

 }
}

Now, the last method was pretty interesting. I wrote a very short method to keep the example small, alas that method won’t deliver a rather useless error message. If you really want to make things more concise in terms of debugging, the naive approach could look a little something like this:

  public Address noNullPropertyAllowed(){
   barrier.pass();
   if(street==null){throw new IllegalArgumentException(“street is null“);}
   if(zipcode==null){throw new IllegalArgumentException(“zipcode is null“);}
   if(town==null){throw new IllegalArgumentException(“town is null“);}
   if(country==null){throw new IllegalArgumentException(“ country is null“);}
   return new Address(this);
  }

This code is repetitive and as soon as the validation involves more than just a little check like this, it will become the coleslaw-and-beer equivalent for method bodies: it expands and expands and expands and at some point you will wish your co-workers away, so nobody will notice when you release the stink. Time to build a better tool to do the job, really! Why not chose annotations?

A basic annotation based validation mechanism

Update (March 24, 2010): After reading a blog about the JSR 303 for bean validation, I’m pretty amazed that my idea was not that dumb at all. I do like the idea of binding the validator to its annotation woth a @Constraint-annotation and I initially thought of something similar. There was just one sole reason why I didn’t do it: I had no idea how to retrofit any of the the NotNull annotations around. But I’m thinking about changing my code accordingly and just have a special Mapping for @NotNull.

Lets start with defining an interface for checking an object’s field against an annotation:

interface AnnotationCheck<A extends Annotation> {
 void check(final Object o,final Field field,final A annotationType) 
           throws IllegalAccessException;
}

And implement that for the NotNull annotation:

class NotNullCheck implements AnnotationCheck<NotNull> {
 @Override
 public void check(Object o,Field field,NotNull annotationType) 
                   throws IllegalAccessException {
  if ( field.get( o ) == null ) {
   throw new IllegalArgumentException(
   "Field "+o.getClass().getName()+'#'+field.getName()+" must not be null");
  }	
 }
}

To have something a little more sophisticated, let’s create a Range annotation to check numbers:

@Target(ElementType.FIELD)
@Retention(RUNTIME)
public @interface Range {
 double from()  default Double.NEGATIVE_INFINITY ;
 double to()  default Double.POSITIVE_INFINITY;
}

Here’s a simple check against a number range. Note that this won’t work perfectly with BigDecimals and doesn’t care for Double.NaN, but let’s keep things simple:

class RangeCheck implements AnnotationCheck<Range>{
 
 private static int LESS=-1;
 private static int EQUAL=0;
 private static int GREATER=1;
 
 @Override
 public void check(final Object o,final Field field,final Range range)
                   throws IllegalAccessException{
  final Object value=field.get(o);
  if(value != null){ //null-checks are @NotNull's business.
   if(value instanceof Number){
    final Double number=((Number)value).doubleValue();
    final int lowerBound
     =compareTolerant(range.from(),number,Math.ulp(number));
    if(lowerBound == GREATER){
     throw new IllegalArgumentException(message(o,field,
      "must be greater or equal "+range.from()+" but is: "+value));
    }
    final int upperBound
      =compareTolerant(range.to(),number,Math.ulp(number));
    if(upperBound == LESS){
     throw new IllegalArgumentException(message(o,field,
      "must be less or equal "+range.to() + " but is: "+value));
    }
   }else{
    throw new IllegalArgumentException(message(o,field,
     "must reference a number. Found: "+value.getClass()+": "+value));
   }
  }
 }
 
 private static String message(final Object o,final Field field,final String details){
  return "Field "+o.getClass().getName()+'#'+field.getName() + " "+details;
 }
 
 private static int compareTolerant(final double a,final double b,final double tolerance){
  return a == b ? EQUAL //
    : a == Double.POSITIVE_INFINITY ? GREATER
    : b == Double.NEGATIVE_INFINITY ? GREATER
    : b == Double.POSITIVE_INFINITY ? LESS
    : a == Double.NEGATIVE_INFINITY ? LESS
    : b - tolerance <= a && b + tolerance >= a ? EQUAL
    : a < b - tolerance ? LESS : GREATER;
 }
}

Now as we have the checks ready for action, it’s time to implement an API to use these checkers in a concise way:

public final class Check{
 
 @SuppressWarnings("unchecked")
 private static Map<Class<? extends Annotation>,AnnotationCheck> strategies 
 =new HashMap<Class<? extends Annotation>,AnnotationCheck>();
 
 static{
  strategies.put(NotNull.class,new NotNullCheck());
  strategies.put(Range.class,new RangeCheck());
 }
 
 private Check(){
  // utility class
 }
 
 public static void declaredFieldsOf(final Object o){
  for(final Field field:o.getClass().getDeclaredFields()){
   for(final Annotation annotation:field.getAnnotations()){
    checkField(o,field,annotation);
   }
  }
 }
 
 private static void checkField(final Object o,final Field field,final Annotation annotation){
  final Class<? extends Annotation> annotationType=annotation.annotationType();
  @SuppressWarnings("unchecked")
  final AnnotationCheck<Annotation> checkStrategy=strategies.get(annotationType);
  if(checkStrategy != null){
   final boolean acs=field.isAccessible();
   try{
    field.setAccessible(true);
    checkStrategy.check(o,field,annotation);
   }catch(final IllegalAccessException e){
    throw new RuntimeException(e); // not expected to happen
   }finally{
    field.setAccessible(acs);
   }
  }
 }
 
}

Voilà, c’est prêt à l’emploi! Now using this thing becomes a breeze:
Let’s take a look at an immutable class with it’s builder, which used this new tool:

@Immutable
public final class Position{

 private final Article article;
 private final int amount;

 private Position(final OrderBuilder b){
  article=b.article;
  amount=b.amount;
 }

 public String getAmout(){
  return amount;
 }
 //..

 public static OrderBuilder order(){
  return new OrderBuilder();
 }

 //..

 public static class OrderBuilder{
  private final SingleThreadBarrier barrier
   = new SingleThreadBarrier(getClass());

  @NotNull
  private Article account;
  @Range(from=1)
  private int amount;
  //..
  public OrderBuilder ofArticle(final Article article){
   barrier.pass();
   this.article=article;
   return this;
  }

  //..

  public Position received(){
   barrier.pass();
   Check.declaredFieldsOf(this);
   return new OrderPosition(this);
  }

 }
}

The methods may have some rather odd names, as they don’t seem to do what they’re called, but this is the programmers perspective from inside the API. Actually you should write a decent javadoc to accompany this. If you leave the inside-view and start looking at the API from the user’s perspective, you may notice that writing code against an API like this is a bit cumbersome, as the methods don’t do what they’re called. But remember: Code is read more often than written and just look how beautiful this one reads:

Position pos=Position().order() //get a builder object
 .ofArticle(kermitTheFrog) //initialize the builder
 .withAmount(10)
 .received(); //check and construct the object

Now the reason why I validate the builder and not the built object is that I don’t want to lose flexibility. I could well design another builder for a return shipment, which builds a position with a negative amount only:

public static class ReturnShipmentBuilder{
   //..
  @NotNull
  private Article account;
  @Range(to=-1)
  private int amount;
  //..

And it would still look good:

Position pos=Position().returnShipment() 
 .ofArticle(kermitTheFrog) 
 .withAmount(10) //boom! This should be negative!
 .received(); 

Alas, setting up multiple builders which just have some differently annotated fields stinks. Here we could create one common builder and just let it use another internal mutable class to hold the data, just what a C++-programmer would call a struct. One builder, but different structs with different annotations. The common builder would run the check against its struct and everything is honkey dory. But I’m gonna leave you that as a little homework. Right now my mind fills with ideas for a flexible validation mechanism, where a validator nothing more than some annotated fields and a method which fills those from a model and calls the checker. I’m not sure yet, whether I want to write about that or find something different to fiddle with. We will see. Stay tuned!

Advertisements
  1. javafinanceguy
    April 11, 2010 at 07:05

    Pretty neat. I have created custom annotations for all sorts of things but more importantly binding objects to rules. it pretty much follows what you did, only thing is it uses jboss drools to verify.
    one quick question, this might sound dumb, but how the hell did you get the syntaxhighlighter working.
    fill me in!

  2. April 11, 2010 at 10:07

    the syntax highligher works amazingly simple:
    http://en.support.wordpress.com/code/posting-source-code/

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: