Quantcast
Channel: Java Team at Kentor » Frameworks
Viewing all articles
Browse latest Browse all 26

Data validation made simple using Bean Validator

$
0
0

There are many validation frameworks out there. But the one that we are going talk about is Bean Validation API (JSR 303).  With Annotations and a simple API it is quite straight forward to express constraints on data; objects. The implementation’s that I have come across are from Apache and Hibernate. An example say’s more than 1000 words as mentioned on Hiberate Validator site.

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...(@See Hibernate Validator documentation)
}

It is worth checking out Hibernate Validation’s documentation with examples. Some clear pointers for me to use Bean Validator were

  • reduced amount of boiler plate code that we write for validation.
  • code is more readable and looks good without if-else blocks
  • it’s more expressible with the use of annotations.
  • easy to write custom constraints.
  • run validation routine when it’s required.

The one thing it was missing that I wanted, was to assign an error code to every invalid field in my webservice. Here is an example of my implementation.

 @XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
 public class SearchReportRequest {
 final String ALPHA_NUMERIC_DATA = "^([a-zA-Z0-9])";
 @NotNull
 @Pattern(regexp = ALPHA_NUMERIC_DATA +"{1,8}$", message = "Invalid id,  accepts a string with max 8 chars")
 @ALErrorCode(code = "3001")
 @XmlElement(required=true) //in the soap request
 private String id; 

 @NotNull
 @Pattern(regexp = ALPHA_NUMERIC_DATA +"{1,50}$", message = "Invalid name,  accepts a string with max 50 chars")
 @ALErrorCode(code = "3002")
 @XmlElement(required=true) //in the soap request
 private String name;
 ....

// @interface ALErrorCode
@Target({java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ALErrorCode {
    String code();
}

This error code and message was then packed in the thrown exception and sent back to the client.

Set<ConstraintViolation<Object>> cViolations = validator.validate(obj_to_be_validated);
if (!constraintViolations.isEmpty()) {
    ConstraintViolation<Object> violation = cViolations.iterator().next();
    try {
        Field f = cv.getRootBeanClass().getDeclaredField(cv.getPropertyPath().toString());
        ALErrorCode errorCode = f.getAnnotation(ALErrorCode.class);
        String errorText = cv.getMessage();
....

If there are similar data constraints specific to the project then creating custom constraints could be the way to avoid boiler plate code and easy to maintain the code.  Check out date validation, @Email and @Notblank which are widely used in the applicaitons. Some useful links for more details

http://beanvalidation.org/

http://java.dzone.com/articles/bean-validation-made-simple

Built in constraints in Hibernate Validator



Viewing all articles
Browse latest Browse all 26

Latest Images

Trending Articles





Latest Images