Java Bean Validation With Annotation

Introduction

As you know we can validate a Java Bean or a POJO with all its fields against the values. There are many ways we can do that. In earlier days we got the complete Java Bean and we would determine each and every field and getter or setter methods to validate the values. For example to validate an email id we would obtain the Employee object and called the getter method for the email id and we validated the value against an email pattern. Currently, modern Java programming suggests use of Java annotations in the field and method levels for bean validation. The best way to validate any Java Bean is to use the Hibernate POJO validator. Before going into validation, this article provides an outline of the usage of Java annotation in a Java Bean. Using this annotation we can have full control of the validation of the Java Bean.

Technicalities

According to a Wiki, an annotation is a kind of metadata that can be applied to classes, fields, methods, parameters etcetera, that can provide a meaningful inference of the functionality to be done. As you already know, some of the commonly used annotations are @Override, @Deprecated etcetera. You have also seen that when we write Javadocs we write @Author, @Since etcetera. However all the annotations have a very specific precise meaning. In most of the cases it increases readability, reduces redundant code and provides better performance. Most of the APIs currently adhere to the principles of annotation usage. Some of the critics also argue that it increases code complexity and is another form of hard-coding. It is the developer's responsibility to have a clear and pragmatic approach of annotation in their code. However in this article I will provide a basic structure of validation of Java Bean with annotation.

You know that while forming the object model for a specific purpose, we normally validate email id, credit card, mobile number, age verification, date of birth, empty characters or blank, min value, max value etcetera. I have seen many developers write their own code to validate email ids, mobile numbers etcetera. Sometimes it becomes difficult to maintain the code structure. In a particular project you may find many Java Beans with common fields like email id and date of birth. These kinds of Java Beans are validated in various ways. In a project there will be some developers that will work for a period of time but then they leave the project. The new developers may not be able to cope with the code structure so they re-write their way. Finally we will have pile of unnecessary code structure for the same functionality. Let us learn how to use your own annotation for the validation of a Java Bean.

Let us write a small Java Bean as in the following:

public class Person1 {

 

    private String name;

    private String email;

    private String salary;

 

    // ~~ Define getter and setter methods below

}

In the above bean we have validate an email id and the salary. As you see all the data types defined here are of String type. There are certain situations where you must define all the data types of the fields to String type. Since we will define our own annotations, we must use it in the fields of a Java Bean. Let us see a code structure where I have used annotations in the fields for validation.
 

public class Person {

 

    @Validate(value = Type.MOBILE)

    private String mobilePhone;

 

    @Validate(value = Type.URL)

    private String website;

 

    @Validate(value = Type.EMAIL)

    private String email;

 

    @Validate(value = Type.AGE)

    private String age;

 

    @Validate(value = Type.BLOODGROUP)

    private String bloodGroup;

 

    @Validate(value = Type.AMOUNT_DOUBLE)

    private String salary;

 

    // ~~ All getter and setter methods below

 

    public String getMobilePhone() {

       return mobilePhone;

    }

 

    public void setMobilePhone(String mobilePhone) {

       this.mobilePhone = mobilePhone;

    }

 

    public String getWebsite() {

       return website;

    }

 

    public void setWebsite(String website) {

       this.website = website;

    }

 

    public String getEmail() {

       return email;

    }

 

    public void setEmail(String email) {

       this.email = email;

    }

 

    public String getAge() {

       return age;

    }

 

    public void setAge(String age) {

       this.age = age;

    }

 

    public String getBloodGroup() {

       return bloodGroup;

    }

 

    public void setBloodGroup(String bloodGroup) {

       this.bloodGroup = bloodGroup;

    }

 

    public String getSalary() {

       return salary;

    }

 

    public void setSalary(String salary) {

       this.salary = salary;

    }

 

}

As you see in the code above, the following things are important for the purposes of validation. The following fields have been annotated with custom annotations.

    @Validate(value = Type.MOBILE)

    private String mobilePhone;

 

    @Validate(value = Type.URL)

    private String website;

 

    @Validate(value = Type.EMAIL)

    private String email;

 

    @Validate(value = Type.AGE)

    private String age;

 

    @Validate(value = Type.BLOODGROUP)

    private String bloodGroup;

 

    @Validate(value = Type.AMOUNT_DOUBLE)

    private String salary;

 

The structure of the annotations above is "Validate the field for the type(mobile number,URL,AGE,Email …))" . The information is given to the field that, once the object is populated with data, all the data must be validated with the respective validation type. In other words the email id field needs to be validated based on the Email type Type.Email.

How to do it

To do bean validation we must focus on the following four points:

  1. Define your own annotation

  2. Define the Type for the specific validation

  3. Define the actual code logic to validate

  4. Integrate with the validator

Let us define our own annotation, as in the following. The name of the annotation is "Validate" . The code is given below.
 

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Validate {

 

    public Type value();

}


The preceding annotation can only be applied to the fields of the Java Bean since it is specified as "@Target(ElementType.FIELD)".

Let us define the type of validation. The code is given below.
 

public enum Type {

 

    AMOUNT_DOUBLE, // For amount

    EMAIL,

    URL,

    MOBILE, //For Indian mobile number (10 digit mobile number with the correct format 9845-123456

    BLOODGROUP,

    AGE; // Age of a Person can not be less than 0 and can not be greater than 100

 

}

The preceding is an "enum" type, since it suggests the meaningful name. This enum type will be applied to validate annotation. In other words what to validate.

Let us define the actual logic for the validation. Let us consider for the Indian mobile number validation. The code is given below.

public static boolean isValidMobile(String mobile) {

       // Indian mobile number

       Pattern p = Pattern.compile("^[0-9]\\d{2,4}-\\d{6,8}$");

       Matcher m = p.matcher(mobile);

       return m.matches();

    }


The code above validates a mobile number against a regular expression. The actual format of the mobile number should be "9856-123456".

Finally we must integrate it inside a generic validator. The structure of the validate method is given below.

public void validate(Object obj) throws Exception {
// Step 1. Find all the declared fields of the Java Bean
//Step 2. Determine the annotations defined for that particular field.
//Step 3. If it is our custom annotation "Validate", get the value ie type of annotation.
//Step 4. Obtain the field value through Java reflection
//Step 5. Apply the validation logic for that field value and resturn true or false.
}

The brief code for the validation of the Java Bean is given below.

public void validate(Object obj) throws Exception {

       Field[] fields = obj.getClass().getDeclaredFields();

       for (Field field : fields) {

           Annotation[] annotations = field.getAnnotations();

           for (Annotation annotation : annotations) {

              if (annotation instanceof Validate) {

                  Validate validator = (Validate) annotation;

                  if (field.getModifiers() == Modifier.PRIVATE) {

                     field.setAccessible(true);

                  }

                  boolean result = false;

                  String fieldValue = (String) field.get(obj);

                  switch (validator.value()) {

                  case AMOUNT_DOUBLE:

                     result = ValidationUtil

                           .isValidAmountDouble(fieldValue);

                     break;

                  case AGE:

                     result = ValidationUtil.isValidAge(fieldValue);

                     break;

                  }

                  if (!result) {

                     System.err.println("Validation failed due to invalid " + field.getName() + ": " + fieldValue);

                  }

              }

           }

       }

    }

The complete source code can be downloaded from the following location.

Download the zip file https://www.dropbox.com/s/qw0lrld1nziebju/beanvalidation.zip

After downloading the zip file, extract it and configure the project in the Eclipse editor. You can also choose any Java IDE of your choice. Ensure that you configure this project as a Maven project. After making the proper configuration, try to run the Java class "TestPerson.java". You will get the following output.

Validation failed due to invalid email: john.p@gmailcom

Validation failed due to invalid age: 211

Validation failed due to invalid bloodGroup: O++

Conclusion

This article is only meant for the novice developer. It gives an insight into the use of custom annotation for bean validation. In the actual project or product development it is always recommended to use the Hibernate bean validator. Follow my next article about the Hibernate bean validator. I hope you will enjoy my article.

References

I provide the following the links for your further reference:

http://en.wikipedia.org/wiki/Java_annotation
http://docs.oracle.com/javase/tutorial/java/annotations/
http://beanvalidation.org/1.0/spec/
 

Up Next
    Ebook Download
    View all
    Learn
    View all