Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Knowing the Hibernate Validator - Part 2

This article introduces the Hibernate Validator, reference implementation of JSR 303 - Bean Validation API. This API allows you to easily validate, class objects that represent the application domain.

What is it for?

This article introduces developers to the Hibernate Validator API, which allows to incorporate data validation from the application through an easy to use and customizable API.

When this subject is useful:

Developers who want to learn how the Hibernate Validator works and how to integrate it into their applications will find detailed explanations in this article on how this API works.

The Bean Validation API, represented by the JSR 303 was released in December 2009. Hibernate Validator has emerged as the reference implementation of this API and lets you use annotations to validate data quickly and easily. The biggest advantage is that the Bean Validation API is independent of the application layer where it is used and even in the way it is coded, allowing it to be used in various scenarios. This article discusses in detail how the Hibernate Validator works.

In December 2009, the final version of JSR 303 was released. It's about the Bean Validation API that allows quickly and easily data validation through the use of annotations. The purpose of this JSR is the validation of the data present in the classes that model the application domain, which usually follow the standard JavaBeans. What's interesting is that the Bean Validation API is independent of the application layer where it is used and even the way of how we code it. It can be used in both desktop and web applications, and isn't tied to the persistence mechanism used. Thus, can be used in various scenarios.

Data validation was always present in systems that receive input from the user. Each framework implements a proprietary mechanism to validate the information, which created incompatibility problems and was harder to integrate.

With the advent of JSR 303 has established a standard API for validation, which is flexible enough to be used for many different types of frameworks. In addition, the Bean Validation API provides data validation classes in the application domain, which is simpler than when the process is done by layer. In the layer validation, it is necessary to verify the same data several times (in the presentation layer, business, persistence, etc.). In order to ensure information consistency. By validating the data directly in the domain classes, the whole process is centralized, therefore the objects of these classes typically runs thru the application layers.

The JSR 303 implementation reference is the Hibernate Validator, which will be explained in detail throughout this article.

Configuring Hibernate Validator

To work with the API you must use Java version 5 or higher, since the Hibernate Validator is not compatible with earlier versions of JDK. Setting the application to use the API is simple. The first step is to download from the project official website, which can be found in the reference section. The version available until the time of this writing is 4.1.0.

After unpacking the file (which can be downloaded in ZIP or TGZ format), simply add the following JARs in your application's classpath: hibernate-validator-4.1.0.Final.jar, log4j-1.2.14.jar, slf4j-api-1.5.6.jar, slf4j-log4j12-1.5.6.jar and validation-api-1.0.0.Ga.jar.They are all inside of the downloaded compressed file. If your application use Java 5 instead of 6, you must also add the API JAXB JARs: JAXB-api-2.2.jar and JAXB-impl-2.1.12.jar.This set of files is the minimum necessary to set the Hibernate Validator to work.

Setting constraints using annotations

The constraints are used to define rules regarding the data of an object. You can, for example, define that a particular attribute can not be null or that a value of a numeric attribute must be within a defined interval. When the data validation process is performed, a verification is made to check if the data are consistent with the established rules.

When you need to add validation constraints in the code, this is done through the use of annotations. Hibernate Validator comes with a set of annotations for common validations, although the API allows the programmer to make customizations. The creation of custom constraints will be addressed later in this article.

There are two places where constraints may apply. The first is directly in the class attribute. In this case the Java directly accesses the attribute thru reflection in order to do the validation. Listing 1 shows an example. The second form of implementation of constraints can be used when the class follows the specification of a JavaBean. In this case you can use the annotation on the getter method of the attribute.Listing 2 shows how this can be done. You must choose only one option, because if both are used the validation will be done twice.

Listing 1.Using the constraint @NotNull on the attribute.

public class Student {
 
  @NotNull
  private String name;
}

Listing 2.Using the constraint @NotNull on the getter method.

public class Student {
 
  @NotNull
  public String getName () {
    return name;
  }
}

All elements of the Hibernate Validator (classes, interfaces, annotations, etc..) Used by your code belong to the package javax.validation.

In addition to the annotation @NotNull shown in the example, which verifies that the data is not null, there are other important annotations included in Hibernate Validator. Following we are going to discuss some of them in more details. For more information about these and other annotations, refer to JSR 303 and the Hibernate Validator documentation.

@AssertFalse and @AssertTrue

These annotations validate if the data is true or false, respectively. Should be implemented in Boolean data (the primitive type Boolean and Boolean class are supported).Listing 3 shows both constraints. The attribute hasWarnings shall be false while fullAge must be true.

Listing 3. Using the annotations @AssertTrue and @AssertFalse.

public class Student {
 
  @AssertFalse
  private boolean hasWarning;
 
  @AssertTrue
  private boolean fullAge;
}

@Max and @Min

These annotations validate if in a given numeric data has a minimum or maximum value, respectively. Are applied to data types BigDecimal, BigInteger, String, byte, short, long, and their corresponding classes wrappers. Listing 4 shows an example where the attribute grade should have a minimum value equal to 70 and maximum of 100.This example shows that it is possible to use more than one constraint for the same attribute or getter method.

Listing 4.Using the annotations @Min and @Max.

public class Student {
 
  @Min (70)
  @Max (100)
  private int grade;
}

@Size

Validate if the data size is between the values ​​specified in the attributes min and max (including).This annotation can be applied to String objects, arrays and objects of type Collection and Map. Listing 5 shows an example where the attribute street (String type) must have a minimum 10 and maximum of 50 characters.

Listing 5.Using the annotation @Size.

{public class StudentAddress
 
  @Size (min = 10, max = 50)
  private String street;
}

@Pattern

This annotation allows data validation according to a regular expression, which is specified by the regexp attribute. Works with String data type. Listing 6 shows how to use it to validate a ZIP code.

Listing 6.Using the @Pattern annotation.

{public class StudentAddress
 
  @Pattern (regexp = "[0-9] {5} - [0-9] {3}")
  private String zip;
}

@Valid

It is quite common to find classes that have attributes that reference other classes. In these situations, it is often interesting to validate not only a specific object, but also all the objects referenced by it. This is the role of the @Valid annotation. When it is present, Hibernate Validator performs the necessary validations on the object being referenced. Listing 7 shows an example where, by invoking the validation of an object of the class Student, the object of the class StudentAddress will be validated also in cascade. In this case, if the attribute street from the address is null, the validation will fail.

Listing 7.Using the @Valid annotation.

public class Student {
 
  @Valid
  private StudentAddress address;
}
 
{public class StudentAddress
 
  @NotNull
  private String street;
}

Invoking the validation process

After the constraints definition in the form of annotations, the next step is to invoke the code that will actually do the data validation in accordance with the rules that were established.

For this, the first required object is an instance of ValidatorFactory, which will be used to construct an object of type Validator. The typical code to get a Validator object is shown in Listing 8.

Listing 8.Getting a Validator object.

ValidatorFactory Validation.buildDefaultValidatorFactory factory = ();
Validator validator = factory.getValidator ();

Having a reference to a validator object allows to invoke the validation. It can be done in different ways, which will be explained in detail in the sequel and will be based on the code in Listing 9.Note that the constraints are applied to the attribute name and in the method getGrade ().

Listing 9. Restrictions defined in the class Student.

public class Student {
 
  @NotNull
  @Size (max = 40)
  private String name;
 
  private int studentGrade;
 
  @Min (70)
  @Max (100)
  public int getGrade() {
    return studentGrade;
  }
}

The first option to invoke the validation process is to call the validate() method that receives as parameter the object to be validated. For an object student from the class Student, the call validator.validate(student) performs validation on the object in accordance with all constraints set.

The second option is to use the method validateProperty(). Unlike the validate() method, it allows to invoke the validation on only one object property. The property name provided is the name of the attribute (if the constraint is defined in the attribute) or the name that follows the specification of a JavaBean (if the constraint is defined in the method). By invoking the method validator.validateProperty(student, "name"), the validation will be invoked directly in the attribute name.But if invoked the method validator.validateProperty (student, "grade"), it will be invoked in the method getGrade().

The third and final option is to make a validation simulation using the method validateValue(). This way you can verify that the validation work for a property where a given value was attributed to it. To check whether the grade property of the student class could take the value 60, for example, simply invoke validator.validateValue (Student.class, "grade", 60).

When a superclass has constraints set and an object of its subclass is submitted for validation, the constraints of the superclass are also validated.

The three methods explained above (validate(), validateProperty() and validateValue()) returns a Set >. Through this collection you can see if there were validation problems and identify them. When there is none, Set returns empty.if one or more errors occur, each item stored on Set represents a validation error. Listing 10 shows an example of code that can be used to display in the command prompt window the validation errors occurred in the student object.

Listing 10. Displaying validation errors of the object in the command prompt window.

Set > errors = validator.validate(student);
 
for (ConstraintViolation error: errors) {
  String msgError = error.getMessage();
  System.out.println (msgError);
}

The getMessage() method is used to return the error message. This message is called interpolated, since it is generated based on a model (template). This article will address, next, how to work with the customization of error messages. Other useful methods are getInvalidValue() which returns the property value of the object that caused the validation problem, and getRootBean() which returns the reference of the object which validation failed.

The method validateValue() does not receive as a parameter an object to be validated.In this case the method getRootBean() returns null.

Using validation groups

Often it is desirable to separate in groups the validations that should be accomplished. This allows the validation of only part of the constraints defined in the class, and not all of them at once.

Hibernate Validator support this separation. Each group is usually represented by a marker interface, which has no methods or attributes. It is important to understand that every time the validation process is invoked, you must specify one or more groups of validation. When a group is not explicitly provided, Hibernate Validator uses the group javax.validation.groups.Default as default. Listing 11 shows the class Student and the constraints made ​​to its attributes. As the constraints do not refer to a specific group, the default is used.

Listing 11. Restrictions on Student class defined in the standard group validation.

public class Student {
 
  @NotNull
  private String name;
 
  @Min(3)
  private int age;
 
  @Size (max = 10)
  private String numEnrollment;
 
  @NotNull
  private Date dateEnrollment;
}

Validation should always be associated with one or more groups, which are passed as parameters to methods validate(), validateProperty() andvalidateValue(). To validate the default group, simply omit this information (the calls validate(student) and validate(studentjavax.validation.groups.Default.class) have exactly the same effect in this case). The invocation of the validation process takes into account only the constraints of the specified groups and ignores the rest. At this point, it is noteworthy that each constraint can belong to one or more groups.

Knowing now that every invocation of validation is done in one or more groups and that all constraints belong to at least one group, it is easy to understand the process of grouping constraints. The first step is the creation of groups, and Listing 12 shows the definition of two of them:PersonalData and EnrollmentData.

Listing 12. Definition of groups PersonalData and EnrollmentData.

public interface PersonalData {
}
 
public interface EnrollmentData {
}

Then you need to declare the constraints using the newly created groups, rather than the standard group. This is done through the attribute groupspresent in all annotations used for validation. Listing 13 shows the attributes name and age were assigned to the group PersonalData andnumEnrollment and dateEnrollment being assigned to EnrollmentData. If it is necessary to assign more than one group to a constraint, simply provide an array with the interfaces to the element groups from the annotation.If a constraint @NotNull is applied to both groups, for example, it could be declared as @NotNull (groups = {PersonalData.class, EnrollmentData.class}).

Listing 13. Organizing the constraints in groups.

public class Student {
 
  @NotNull (groups = PersonalData.class)
  private String name;
 
  @Min (value = 3, groups = PersonalData.class)
  private int age;
 
  @Size (max = 10, groups = EnrollmentData.class)
  private String numEnrollment;
 
  @NotNull (groups = EnrollmentData.class)
  private Date dateEnrollment;
}

Finally, just inform the group to be validated at the time of invoking the validation.Indeed, it is even possible to validate more than one group in one invocation. Listing 14 shows three examples of calls to the validate() method. The first two rely on validation to a group at a time, and the third for both groups. Always remember that the constraints that are not part of groups where the validation is being performed are ignored.

Listing 14. Invoking the validation per group.

validator.validate (student PersonalData.class);
validator.validate (student EnrollmentData.class);
validator.validate (student PersonalData.class, EnrollmentData.class);

Besides the separation of validation in groups, another important aspect should be considered. By default, there are no guarantees about the order of the validation of the constraints In cases where it is important to ensure the order, you can use the annotation @GroupSequence.

@GroupSequence allows to define an execution order for the groups. Suppose you want to perform validations in groups PersonalData andEnrollmentData respecting that order.For this you need to create a new group and define which groups it will check and in what order.Listing 15shows the creation of the group FullData, which defines that the first validation will be done on the group PersonalData and then in the group EnrollmentData. To validate this new group, just reference it at the time of validation. Invoking validate (student, FullData.class) will run the validation of the groups PersonalData and EnrollmentData in this order.

Listing 15. FullData group definition with an validation order set.

@GroupSequence ({PersonalData.class, EnrollmentData.class})
public interface FullData {
}

When a validation error is found in a group, the next groups are not validated.

Another function of the annotation @GroupSequence is redefining the standard group for a class, which by default is thejavax.validation.groups.Default.To change this setting, simply use @GroupSequence at class level.Listing 16 shows its use in theStudent.Now, when the validation is invoked for the default group, the groups PersonalData and EnrollmentData will be called and that order will continue to be respected. Another important point is to always add the class being annotated as a member of the group defined by@GroupSequence, as was done with the Student class in Listing 16. If this condi tion is not met, a GroupDefinitionException will be thrown.

Listing 16. Redefining the default group with the annotation @GroupSequence.

@GroupSequence ({Student.class, PersonalData.class, EnrollmentData.class})
public class Student {
  //...
}

Customizing error messages

When you use the Hibernate Validator and validation problems occur and you are faced with messages like: "may not be null", "must be greater than or equal to 70" or "size Must Be Between 2 and 10."It is evident that not always these messages, which are set by default in the API, are ideal for your application.

For this reason, Hibernate Validator allows customizations to be made in the messages. To understand how this process works, you should keep in mind that each constraint has an associated message descriptor. A message descriptor is nothing more than a template that defines how will be the resulting message.

If we consider the annotations @NotNull @Min and @Size, for example, their respectives messages descriptors are{javax.validation.constraints.NotNull.message}, {javax.validation.constraints.Min.message} and{javax.validation.constraints.Size.message}.This information can easily be obtained if the method getMessageTemplate() is invoked on aConstraintViolation (which represents a validation error, as explained earlier).Any information of the message descriptor declared between braces, in fact, is a parameter that will be replaced in the time of the final message generation, a process known as interpolation.

To perform the interpolation Hibernate Validator queries parameter value in the file org/hibernate/validator/ValidationMessages.properties, which is located within the Hibernate Validator JAR. Listing 17 shows the portion that corresponds to the messages of the annotations @NotNull,@Min and @Size. This file maps a key to a value where the key is the parameter of the message descriptor and the value is what needs to be generated as output when occurs the interpolation process.

Listing 17. Part of the file ValidationMessages.properties provided by Hibernate Validator.

javax.validation.constraints.NotNull.message = may not be null
javax.validation.constraints.Min.message = must be greater than or equal to {value}
javax.validation.constraints.Size.message = size must be between {min} and {max}

To customize the error messages, you must create an ValidationMessages.properties file and redefine the messages. It should be at the root of the classpath of your application and has read precedence over the default Hibernate Validator file.Listing 18 shows how could be theValidationMessages.properties file of your application, which changes the messages generated for constraints with null value, minimum value and size.

Listing 18.ValidationMessages.properties file of the application.

javax.validat ion.constraints.NotNull.message = The data can not be null
javax.validation.constraints.Min.message = The value must be greater than or equal to {value}
javax.validation.constraints.Size.message = The data length must be between {min} and {max}

Another possibility which the API provides is to override the message descriptor of only one constraint.This is done via the message attribute of the annotation that represents the constraint.Listing 19 shows how is the redefinition of the message descriptor of the annotation @NotNull to the student's name.As the parameter {student.nome} is used, there must be a corresponding entry in the file ValidationMessages.properties.Considering that this entry is student.name = name of student, when occurs a validation error in this attribute would be generated a message "The student's name cannot be null."

Listing 19. Redefining the message descriptor of @NotNull.

public class Student {
 
  @NotNull (message = "The {student.name} can not be null")
  private String name;
}

You can also use the attributes of the annotation itself as parameters in the message descriptor.Consider the example of the annotation @Size, where the elements min and max define the range of allowable size.Listing 20 shows how to define a message descriptor that reads these values ​​from the interval.Thus, when a validation error occurs in the size of the enroll number, that message will be thrown is "Registration should be of a size between 5 and 10."

Listing 20. Redefining the message descriptor of @Size.

public class Student {
 
  @Size (min = 5, max = 10, message = "Enrollment number should be of a size between {min} and {max}")
  private String numEnrollment;
}

When performing the interpolation process, Hibernate Validator seeks for the values to be replaced by the parameters of the message descriptor in a well defined order.First the search is made ​​in the application file ValidationMessages.properties.If the information is not found, the search will be made ​​inValidationMessages.properties file of the Hibernate Validator.If the information still is not found, the algorithm searches the elements of the annotation.

Creating custom constraints

As discussed previously, Hibernate Validator has a set of constraints that can be used to validate data (such as @NotNull , @Size, @Min, @Max,among others).But these validators are not always enough for all types of application. The solution in these cases is to create custom constraints, which is supported by the API.

To illustrate the process of creating a validation constraint, we will create the annotation @Numeric.It will validate if the contents of a string is a numeric data that can be converted to type long or double.

The first step is to create the annotation itself, as shown in Listing 21.If you already have some experience with the creation of annotations the code is simple to understand. The annotation declaration is done through the @interface, similar to the declaration of classes or interfaces.For it to be a valid constraint of Hibernate Validator, some attributes must be declared.

The first is the message(), which defines a message descriptor for the constraint, in this case {app.Numeric.Message}.Remember that the descriptor defines how the validation error message will be generated by the interpolation process.

The other attribute is the groups(), which defines the validation groups to which the constraint belongs.It is mandatory that the default value is defined as an empty string.

The payload attribute is an array of Class objects that implement the markup interface Payload .It can be used in situations where it is necessary to associate other informations with the contraintA practical example where this attribute can be useful is cited in the Bean Validation specification and takes into account the following scenario.C Consider the constraint declared as @NotNull (payload = ErrorLevel1.class).If a validation error occurs, you can retrieve the payload through the object ConstraintViolation invoking getConstraintDescriptor(). GetPayload ().Consider also that there may be other interfaces, such as ErrorLevel2 or ErrorLevel3 (each representing a error level), which may be associated to other constraints.A framework that operates in the presentation layer could read the payload associated with the constraint that caused the validation problem and show the error message to the user in different ways, according to this attribute (for each level could be adopted a different color for the message, for example). Typically, the default value used for the payload attribute in the constraint declaration is an empty array.

The attributes mentioned above are mandatory and must be declared, but other attributes can be created.In he example in Listing 21, the attributevalue() sets up a NumberType, which is an enum and indicates whether the data type expected to be validated in the string is long or double.The statement can be seen in Listing 22.

Listing 21. Definition of the annotation @Numeric.

@Target (ElementType.FIELD)
@Retention (RetentionPolicy.RUNTIME)
@Constraint (validatedBy = NumericValidator.class)
public @interface Numeric {
  String message() default "{app.Numeric.message}";
  CLASS [] Groups() default {};
  CLASS [] payload() default {};
  NumberType value();
}

Listing 22. Defininition of the enum NumberType.

public enum NumberType {
  LONG,
  DOUBLE
}

In addition of the attributes, you can see that the @Numeric annotation itself is noted.@Target (ElementType.FIELD) indicates that @Numericcan be used only on attributes.@Retention (RetentionPolicy.RUNTIME) indicates that the JVM can, at runtime, to identify the presence of the annotation in an attribute.This is essential, since Hibernate Validator needs to identify it by using reflection. The @Constraint(validatedBy = NumericValidator.class) indicates that the class is NumericValidator implements the logic that will validate the constraint.

Once this first step is done, we must now implement the class NumericValidator, which can be seen in Listing 23.This class must implement the interface ConstraintValidator.The first data type used in generics is the annotation that represents the constraint that the class will validate, in this case, @Numeric.The second parameter is the data type of the attribute that the constraint is able to validate. Since the intent is to validate whether a string has numeric type long or double, the parameter is a String.

If the constraint applies to several data types, it is necessary to implement a ConstraintValidator for each.In situations like these is needed to provide an array of Class objects for the attribute validatedBy of the annotation@Constraint.

Listing 23. NumericValidator class implementation.

public class NumericValidator implements ConstraintValidator {
  private Numeric constraint;
 
  public void initialize (Numeric numeric) {
    this.constraint = numeric;
  }
 
  public boolean isValid(String str, ConstraintValidatorContext ctx) {
    if (str == null) {
      return true;
    }
   
    boolean isOk = true;
   
    if (constraint.value() == NumberType.LONG) {
      try {
        Long.parseLong(str);
      } Catch (NumberFormatException e) {
        isOk = false;
      }
    } Else if (constraint.value () == NumberType.DOUBLE) {
      try {
        Double.parseDouble(str);
      } Catch (NumberFormatException e) {
        isOk = false;
      }
    }
   
    return isOk;
  }
 
}

When creating the class, you must implement two methods: initialize() and isValid().The initialize() is invoked when the class object is initialized.This method receives as parameter a reference to the corresponding annotation, which is typically copied to an attribute for future use in the method isValid().The method isValid () is where the implementation logic of the validation is invoked when the data must be validated.The return is a boolean, where true indicates that there was no validation errors and false indicates that the data is not valid, considering the established rules.As a parameter, the method isValid () receives the data to be validated (in this case an object of the class String) and aConstraintValidatorContext, which allows to override the message descriptor set for the constraint.

The algorithm in Listing 23 is very simple.It uses the attribute value() of the annotation @Numeric indicating the numeric type expected in the string and tries to make the conversion to the corresponding data type (long or double).If successful, the algorithm returns true.If not, returnsfalse.Note that if the string is null, the algorithm considers that the string is valid. This is a recommendation of the the Bean Validation API specification itself, which says that validation should not fail when the values ​​are nulls (to validate if data is null, just use the constraint in conjunction with @NotNull).

The last step before the new constraint can be used is to add to the file ValidationMessages.properties the key app.Numeric.message associated with an error message.This key has been set as the default message attribute of the @Numeric.As seen previouly, this file should be created at the root of the application classpath.

Now the new constraint @Numeric ready for use.Observe an example of usage in Listing 24. It validates the student's Enrollment number, stored in a string, if it is a valid number of type long.

Listing 24. Example of using the annotation @Numeric.

public class Student {
 
  @Numeric (NumberType.LONG)
  private String numEnrollment;
}

Composing constraints

To understand the purpose of constraints composition, note the code in Listing 25.In this example, the attribute numEnrollment, to be valid, it must pass thru three validations: @NotNull, @Size and @Numeric.Now imagine that your application has other enrollment numbers on other objects, which must be validated in the same way. Would have to add the three constraints in several different places, which can cause maintenance difficulties in the future.

Listing 25. Application of multiple constraints on an attribute.

public class Student {
 
  @NotNull
  @Size (min = 5, max = 10)
  @Numeric (value = NumberType.LONG)
  private String numEnrollment;
}

The solution to this problem is to create a constraint composed by the other three. This makes it much easier to validate the enrollment number.

The creation of a new constraint that encompasses other follows the same process of creating the constraint discussed earlier. Listing 26 shows the annotation @Matricula which groups the constraint @NotNull, @Size and @Numeric.The only difference in this case is that the attribute@validatedBy of @Constraint is defined as an empty array.The reason to not use a class with validation logic, is that @Enrollment reuses the already existing validations of the constraints which it compose

Listing 26. @Enrollment constraint definition

@NotNull
@Size (min = 5, max = 10)
@Numeric (value = NumberType.LONG)
@Target (ElementType.FIELD)
@Retention (RetentionPolicy.RUNTIME)
@Constraint (validatedBy = {})
public @interface Enrollment {
 
String message () default "{app.Enrollment.message} ";
  Class[] Groups() default {};
  Class[] payload() default {};
}

You need to make a small change in the annotation @Numeric definition for that @Enrollment can be defined this way.In @Target, you must use FIELD and ANNOTATION_TYPE to allow that @Numeric can be used to annotate an annotation (before it could annotate only attributes).The configuration is then this way:@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}).

When Trying to validate the enrollment "12345-67890", Hibernate Validator returns two validation errors: one saying that the enrollment can not be longer than 10 characters (@Size) and another saying that the enrollment is not a valid number (@Numeric).However, it is possible to configure the@Enrollment for the validation error to be generated from the constraints themselves, and not for each constraints of the composition.To do this,simply annotate the @Enrollment with @ReportAsSingleViolation.From now on only a validation error will be reported, and this error refers to the message descriptor {app.Enrollment.message}, which was defined for the constraint @Matricula (This message could be configured as "invalid enrollment", for example).

Conclusions

This article discussed in details how the Hibernate Validator works, which is the reference implementation of JSR 303 - Bean Validation API, and allows to easily validate data contained in objects. Besides having several constraints already available, Hibernate Validator also allows an extensive customization, so that new constraints can be created and all the error messages can be customized. The article also shown other interesting features, such as creating groups to validate data separately, and the constraints composition to avoid repetitive use of annotations.

A major advantage of the Bean Validation API, and consequently Hibernate Validator, is the complete independence from the application layer where it can be applied, the programming model (can be used in desktop or web applications, for example) and the persistence mechanism.Several frameworks and APIs that work in various fronts are already integrated with the Bean Validation API such as Hibernate, JPA and JSF, which shows the importance and the high degree of flexibility of the API.



MrBool is a totally free website made for software developers. Our articles and courses are totally free with focus on useful techniques and best practices

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login