One model, many validations

It is not unusual a application has more than one html form that should be bound with the same model. Think about this situation: you have a form to register a new user with just a few fields, like name, email and password. After that, you need this same user completes his registration with other fields.

This common situation puts you in a problem. How to partially apply a validation rule in the same model. Below we have the User class:

    package models;

    @Entity
    public class User {

    	private String id;

    	@Required
    	private String name;

    	@Required
    	private String email;

    	@Required
    	private String password;

    	@Valid
    	private Address address = new Address();

    	@Required
    	private String facebookId;

    	//getters and setters
    }

There are a lot of validations! In the first situation, you only need to validate three fields. Let’s see the code:

    public static Result create(){
    	Form<User> filledForm = newUserForm.bindFromRequest("name","email","password");
    	if(filledForm.hasErrors()){
    		return badRequest(views.html.new_user_form.render(filledForm));
    	}
    	User user = filledForm.get();
    	//Ebean.save(user);
    	return redirect(routes.UsersController.form());
    }

Here we allow only the name, email and password are linked to the model. I already commented this in other post. The problem is when we invoke hasErrors method. This method will return true, because our model has other validations. Here we can use a feature provided for Bean Validation that allow us to split validation in different groups.

    package groups;

    public interface ValidationGroups {

    	public interface SocialInformation {}
    	public interface UpdateInformation{}
    	public interface BasicInformation{}

    }

The nice thing about this is that Play’s validation follows Bean Validation spec. We can take advantage of this! We only need to pass the group when we create the Form object.

         private static Form<User> newUserForm = Form.form(User.class,ValidationGroups.BasicInformation.class);

That is it! You can have a lot of groups and use them in specific situations. You still can use multiple groups to perform a validation :).

    @Required(groups={ValidationGroups.BasicInformation.class,ValidationGroups.SocialInformation.class})
    private String email;
    @Required(groups={ValidationGroups.BasicInformation.class,ValidationGroups.SocialInformation.class})
    private String password;
    @Required(groups=ValidationGroups.SocialInformation.class)
    private String facebookId;

And now you pass a different group to form method.

    private static Form<User> newUserForm = Form.form(User.class,ValidationGroups.SocialInformation.class);

Name and email will be validated when a validation is performed with one group or another.

Another alternative, that I try to avoid, is to create a new class that represents your html form. You can use it to bind input values and after that, create your Model. This approach is better when you have a form that is not bound with any model. For example, a form to log in your user. In this case, you can use DynamicForm or a Class that represents login information.

If you have any doubt about PlayFramework, fell free to get in touch. My contact informations is here.

 

Advertisements

One thought on “One model, many validations

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