--- title: Validation --- # Validation VRaptor validation uses Bean Validation, spec present in Java EE 7, that allow us to validate our beans based on annotations. With this you can use embedded constraints or create your custom constraint. ~~~ #!java public class Client { // validates if name is not null and size between 10 and 50 @NotNull @Size(min=10, max=50) private String name; // validates if birth date is past @Past private Date birth; } ~~~ And in your controller: ~~~ #!java public class ClientController { private final Validator validation; /** * @deprecated CDI eyes only */ protected ClientController() { this(null); } @Inject public ClientController(Validator validation) { this.validation = validation; } public void form() { } public void store(@NotNull @Valid Client client) { // if client is not valid, redirect to form page validation.onErrorForwardTo(this).form(); } } ~~~ **Note**: If your application uses Hibernate or JPA and you have your entities annotated with Bean Validation constraints, you need to call `Session.flush()` or `EntityManager.flush()` to validate your model before redirect or forward. The method `flush` synchronizes state from your objects to database. So Bean Validation constraint will only validate when `flush` is triggered. ##Creating your custom constraints With Bean validation you can create your own custom validations. If you want to validate if phone number is in `(00) 0000-0000` pattern, you can do something like this: ~~~ #!java @Documented @Constraint(validatedBy = {}) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @ReportAsSingleViolation @Pattern(regexp = "\\((\\d{2})\\) (\\d{4})-(\\d{4})") public @interface PhoneNumber { String message() default "{br.com.caelum.vraptor.validations.phonenumber.message}"; Class[] groups() default {}; Class[] payload() default {}; } ~~~ The message's value with `{}` will be fetched from `ResourceBundle`. Or you can put a fixed message, just like this: ~~~ #!java String message() default "Invalid number"; ~~~ You can create complex constraints that access database or uses any managed component. If you want, as example, check if the user already exists in the database, ou can write a code like this: ~~~ #!java @Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = { LoginAvailableValidator.class }) @Documented public @interface LoginAvailable { String message() default "{login_already_exists}"; Class[] groups() default {}; Class[] payload() default {}; } ~~~ And `LoginAvailableValidator` that checks the constraint: ~~~ #!java public class LoginAvailableValidator implements ConstraintValidator { @Inject private UserDao userDao; public boolean isValid(User user, ConstraintValidatorContext context) { return !userDao.containsUserWithLogin(user.getLogin()); } } ~~~ ##Using custom messages If you prefer, you can use custom messages with Bean Validation. For this you need to add the file `ValidationMessages.properties` in your _classpath_. In a Mavem project, the location is `/src/main/resources`. Considering the previous example, the file might have the following content to customize the default messages: ~~~ #!properties client.name.empty = The client name may not be empty client.name.size = The client name size must be between 10 and 50 client.birth.past = The birth must be in the future ~~~ And the class: ~~~ #!java public class Client { @NotNull(message="{client.name.empty}") @Size(min=10, max=50, message="{client.name.size}") private String name; @Past(message="{client.birth.past}") private Date birth; } ~~~ The value `{}` present in annotations indicates that the message comes from the `ResourceBundle`. See that was added parameters in order to let our most dynamic and reusable messages. The possibilities are currently: * attribute values ​​of the restriction mapped with the attribute names, like `{min}` and `{max}` for `@Size` * the current value to be validated with the name `${validatedValue}` * a ternary operation like: `${value > 1 ? 's' : ''}` * a bean mapped with the name `formatter` exposing a var-arg method `format(String format, Object... args)` which behaves like `java.util.Formatter.format(String format, Object... args)`. Example: `${formatter.format('%1$.2f', validatedValue)}` ## Validation using Validator class methods If you don't want to use Bean Validation, you can use other methods located at `Validator` class. Below an example with `add` method: ~~~ #!java if (client.getName() == null) { //an hard-coded message validator.add(new SimpleMessage("name", "The name is mandatory")); //i18n message validator.add(new I18nMessage("name", "name.mandatory")); } ~~~ You can use another methods like `addIf`, that only adds the message if a precondition is `true`, and `ensure` that only adds the message if the precondition is `false`: ~~~ #!java validator.addIf(client.getName() == null, new SimpleMessage("name", "The name is mandatory")); validator.ensure(client.getName() != null, new SimpleMessage("name", "The name is mandatory")); ~~~ ##Redirecting when a constraint error occurs When a constraint error occurs, you can redirect or forward the user to another page. You can see below some of the possible actions: ~~~ #!java validator.onErrorForwardTo(MusicController.class).list() ==> validator.onErrorUse(logic()).forwardTo(MusicController.class).list(); validator.onErrorRedirectTo(MusicController.class).list() ==> validator.onErrorUse(logic()).redirectTo(MusicController.class).list(); validator.onErrorUsePageOf(MusicController.class).list() ==> validator.onErrorUse(page()).of(MusicController.class).list(); validator.onErrorSendBadRequest() ==> validator.onErrorUse(status()).badRequest(errors); ~~~ If you want to redirect to the same controller, you can use: ~~~ #!java validator.onErrorForwardTo(this).list() ==> validator.onErrorUse(logic()).forwardTo(this.getClass()).list(); validator.onErrorRedirectTo(this).list() ==> validator.onErrorUse(logic()).redirectTo(this.getClass()).list(); validator.onErrorUsePageOf(this).list() ==> validator.onErrorUse(page()).of(this.getClass()).list(); ~~~ ##Print the errors in the view When an error exists, VRaptor puts an attribute named `errors` in the request scope, that contains a list with all constraint errors. This list contains a key-value object that represents: - `category`: represents the full path of the attribute like `object.attribute` - `message`: represents the error message like: "must be in the future", "may not be empty", and so on. In the view you can do something like this: ~~~ #!jsp ${error.category} - ${error.message}
~~~ You can search for an error for a specific category, that can be useful to display constraint the messages beside the field. ~~~ #!jsp ${errors.from('client.name')} ~~~ It will print "may not be empty, size must be between 10 and 50". You can also use the join method if you want to use another separator, just like this: ~~~ #!jsp ${errors.from('client.name').join(' - ')} ~~~ That will print "may not be empty - size must be between 10 and 50". ##Adding more messages When you add a message, the framework will add as an error. But its possible to add the message as success, info or warning. In this case you can simple use available attributes from `Severity` enum as you can see below: ~~~ #!java validator.add(new SimpleMessage("client.name", "name field have accents", Severity.WARN)); ~~~ And in the view you can use `vmessages` attribute: ~~~ #!jsp ${vmessages.warnings.from('client.name')} ~~~ This code will print "name field have accents" beside the input text. ## Programmatic validation If you want, you can use the [vraptor-simple-validator](/en/docs/plugins/#vraptor-simple-validator) plugin to do your validations in a fluent way. It provide us a diversity of defaults validations that you may want to use.