Skip to content

Validations for the Play Framework

17 July 2011

It can be very easy to add validations to the play framework. Just adding annotations to the objects will usually do the trick, but these are for the values of one field only, like @Required or @Email. If you want to check if some combined properties are valid, then you can use the @CheckWith annotation. With this annotation you have to define a class that will be used for the validation and optionally a message if this fails. For instance, a check on multiple fields for uniqueness in the database can be handled this way. The checkwith class must extend Check. An example will make it more clear

@Entity
public class User extends Model {
   @CheckWith(value = UniqueUserCheck.class, message = "error.not.unique")
   @Required
   @NotNull
   public String name;

   @Required
   @Email
   public String email;

   @NoBinding
   public boolean admin;

   private class UniqueUserCheck extends UniqueObjectCheck<User> {
      @Override
      protected List loadExistingUniqueObjects(final User user) {
         return User.find("byNameAndEmail", user.name, user.email).fetch(2);
      }
   }
}

Some explanations, @Required tells us that the field is required. If not filled an error will be added to the validations. @CheckWith will check this object using the defined class. I have added the class that checks if there already exists a user with this name and email in the user class itself. This class extends the UniqueObjectCheck which consists of :

public abstract class UniqueObjectCheck<T extends Model> extends Check {

   @Override
   @SuppressWarnings("unchecked")
   public boolean isSatisfied(final Object validatedObject, final Object value) {
      boolean checkOk = true;
      Class modelType = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
      if (validatedObject != null && modelType.isAssignableFrom(validatedObject.getClass())) {
         T item = (T) validatedObject;
         List existingObjects = loadExistingUniqueObjects(item);
         checkOk = existingObjects.size() == 0;
         if (existingObjects.size() == 1) {
            if (item.id != null) {
               T existingClass = existingObjects.get(0);
               if (existingClass.getId().equals(item.id)) {
                  checkOk = true;
               }
            }
         }
      }
      return checkOk;
   }

   protected abstract List loadExistingUniqueObjects(final T item);
}

So this class loads the existing objects as defined by the extending class. If it finds one or more items then it checks the item for an id. If the id is not the same as the given id then an object with these unique fields already exists and thus this object should not be saved.

Another important annotation is the @NoBinding annotation. This tells the playframework to not bind any incoming http parameters to the admin field. This prevents some smart user from adding the parameter admin=true to the request. The @NoBinding annotation can also take values if needed to tell when the binding is allowed to happen or not. If a value is set on the @NoBinding, then that value should also be used in the notation of the method to indicate that in this case there should be no binding, e.g.

@NoBinding("editUser")
public boolean admin

and in the controller

public void saveUser(@As('editUser') User user)

will prevent the admin field of being set. If you have a special admin method which does allow it, then the As can be skipped and the admin field will be updated, e.g.

@Secure.isAdmin
public void saveUser(User user)

Now that all the plumbing for the validations are in place, its time to validate your object. This can be doen by:

public void saveUser(@As('editUser') @Valid User user)

That’s it. You almost didnt notice it, but just adding the @Valid for the object to be validated will call all the validation rules. It’s that simple with the playframework.

Now that you have validated its time to check the validations but more on that subject in a next blog

Advertisements
5 Comments
  1. opensas permalink

    great article, looking fordward for more articles on validations…

  2. Rene permalink

    This does not work for me, I get the following error:
    The file /app/validation/UniqueObjectCheck.java could not be compiled. Error raised is : T cannot be resolved to a type

    • This means that you didn’t define the type of the UniqueObjectCheck, so you should have something like the following:

      	private static class YourModelUniqueCheck extends UniqueObjectCheck<YourModel>  {
      

      and you probably did it like this:

      	private static class YourModelUniqueCheck extends UniqueObjectCheck {
      

      Which was a typo in my post I see now because wordpress saw the ‘<User>’ as an invalid html tag, so it wasnt shown correctly

      Thx for the reply, I will fix the post as well

  3. Rene permalink

    Yes, this was the error. Works perfectly now.

Trackbacks & Pingbacks

  1. Playframework: handling of validated objects « Ronald Haring's Blog

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: