Friday, December 2, 2011

Bean Validation Made Simple With JSR 303

    JSR 303 (Bean Validation) is the specification of the Java API for JavaBean validation in Java EE and Java SE. Simply put it provides an easy way of ensuring that the properties of your JavaBean(s) have the right values in them. This post aims to show you how to use the Bean Validation API in your project.
    To begin, imagine that you were building the next Facebook and you would need member(s) to register to use your application. In order to successfully register, prospective member(s) have to provide the following: a last name, a first name, a gender, an email address and a date of birth. In addition, the individual who is registering must be between 18 and 150 years inclusive.
    Prior to JSR 303, you probably would have needed a bunch of if-else statements to achieve the above requirements. Thankfully, not any more.
    We will begin by creating a JavaBean named 'Member' that would hold all the properties we are interested in.
01 package validationapiblog.model;
03 import java.util.Date;
04 import validationapiblog.enums.Gender;
06 /**
07  *
08  @author Adedayo Ominiyi
09  */
10 public class Member {
12     private String lastName = null;
13     private String firstName = null;
14     private Gender gender = null;
15     private String emailAddress = null;
16     private Date dateOfBirth = null;
18     public Member() {
19     }
21     public String getFirstName() {
22         return firstName;
23     }
25     public void setFirstName(String firstName) {
26         this.firstName = firstName;
27     }
29     public Gender getGender() {
30         return gender;
31     }
33     public void setGender(Gender gender) {
34         this.gender = gender;
35     }
37     public String getLastName() {
38         return lastName;
39     }
41     public void setLastName(String lastName) {
42         this.lastName = lastName;
43     }
45     public Date getDateOfBirth() {
46         return dateOfBirth;
47     }
49     public void setDateOfBirth(Date dateOfBirth) {
50         this.dateOfBirth = dateOfBirth;
51     }
53     public Integer getAge() {
54         if (this.dateOfBirth != null) {
55             // calculate age of member here
56         }
57         return null;
58     }
60     public String getEmailAddress() {
61         return emailAddress;
62     }
64     public void setEmailAddress(String emailAddress) {
65         this.emailAddress = emailAddress;
66     }
67 }

The gender property is a simple enum and is shown below
1 package validationapiblog.enums;
3 /**
4  *
5  @author Adedayo Ominiyi
6  */
7 public enum Gender {
9 }

Now that we have the pieces to the puzzle. The next step is to download an implementation of JSR 303. For this post we would be using the reference implementation namely Hibernate Validator. The version as at the time this post was written is 4.2.0 Final. After downloading it you should add the following 4 jars to the classpath of your project:
  • hibernate-validator-4.2.0.Final.jar
  • hibernate-validator-annotation-processor-4.2.0.Final.jar
  • slf4j-api-1.6.1.jar
  • validation-api-1.0.0.GA.jar
Once this is done, you simply annotate the 'Member' JavaBean we created earlier to indicate which properties need be validated. You can annotate either the fields or the accessor (or getter) methods of the JavaBean. In this post I will be annotating the accessor methods.

01 package validationapiblog.model;
03 import java.util.Date;
04 import javax.validation.constraints.Max;
05 import javax.validation.constraints.Min;
06 import javax.validation.constraints.NotNull;
07 import javax.validation.constraints.Past;
08 import javax.validation.constraints.Pattern;
09 import org.hibernate.validator.constraints.Email;
10 import org.hibernate.validator.constraints.NotBlank;
11 import validationapiblog.enums.Gender;
13 /**
14  *
15  @author Adedayo Ominiyi
16  */
17 public class Member {
19     private String lastName = null;
20     private String firstName = null;
21     private Gender gender = null;
22     private String emailAddress = null;
23     private Date dateOfBirth = null;
25     public Member() {
26     }
28     @NotNull(message = "First name is compulsory")
29     @NotBlank(message = "First name is compulsory")
30     @Pattern(regexp = "[a-z-A-Z]*", message = "First name has invalid characters")
31     public String getFirstName() {
32         return firstName;
33     }
35     public void setFirstName(String firstName) {
36         this.firstName = firstName;
37     }
39     @NotNull(message = "Gender is compulsory")
40     public Gender getGender() {
41         return gender;
42     }
44     public void setGender(Gender gender) {
45         this.gender = gender;
46     }
48     @NotNull(message = "Last name is compulsory")
49     @NotBlank(message = "Last name is compulsory")
50     @Pattern(regexp = "[a-z-A-Z]*", message = "Last name has invalid characters")
51     public String getLastName() {
52         return lastName;
53     }
55     public void setLastName(String lastName) {
56         this.lastName = lastName;
57     }
59     @Past(message = "Date of Birth must be the past")
60     @NotNull
61     public Date getDateOfBirth() {
62         return dateOfBirth;
63     }
65     public void setDateOfBirth(Date dateOfBirth) {
66         this.dateOfBirth = dateOfBirth;
67     }
69     @Min(value = 18, message = "Age must be greater than or equal to 18")
70     @Max(value = 150, message = "Age must be less than or equal to 150")
71     public Integer getAge() {
72         if (this.dateOfBirth != null) {
73             // calculate age of member here
74         }
75         return null;
76     }
78     @NotNull(message="Email Address is compulsory")
79     @NotBlank(message="Email Address is compulsory")
80     @Email(message = "Email Address is not a valid format")
81     public String getEmailAddress() {
82         return emailAddress;
83     }
85     public void setEmailAddress(String emailAddress) {
86         this.emailAddress = emailAddress;
87     }
88 }

Please note that these are just some of the annotations available in JSR 303. In addition Hibernate Validator introduces a few of its own that are not in the specification. Feel free to study the annotations not in this post in your free time you might find something interesting. There is also the ability to create your own custom validator if the need arises. Now lets review the annotations used:
  • @NotNull - Checks that the annotated value is not null. Unfortunately it doesn't check for empty string values
  • @Pattern - Checks if the annotated string matches the regular expression given. We used it to ensure that the last name and first name properties have valid string values
  • @Past - The annotated element must be a date in the past.
  • @Min - The annotated element must be a number whose value must be greater or equal to the specified minimum
  • @Max - The annotated element must be a number whose value must be lower or equal to the specified maximum
  • @NotBlank - Checks that the annotated string is not null and the trimmed length is greater than 0. This annotation is not in JSR 303
  • @Email - Checks whether the specified string is a valid email address. This annotation is also not in JSR 303
To test the validation we could use a unit test as shown below. 

package validationapiblog.test;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import validationapiblog.model.Member;
import org.junit.Test;
import static org.junit.Assert.*;

 @author Adedayo Ominiyi
public class ValidationAPIUnitTest {

    public ValidationAPIUnitTest() {

    public void testMemberWithNoValues() {
        Member member = new Member();

        // validate the input
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<Member>> violations = validator.validate(member);
In conclusion, you should experiment with JSR 303 and see for yourself which annotations you like. Thank you and have fun.

Wednesday, September 21, 2011

Gender Equality: A Noble but Flawed Cause

Disclaimer: This post is strictly about gender equality and not about women rights. I am in no way an advocate of beating women, mutilating their genitals or any other inhumane acts against them. I love women (in a can’t live with them, can’t live without them way). In addition if the following does not apply to you or you don’t agree. Instead of bashing me with words you can kindly tell us how you or your life is different and create a learning experience for the rest of us.

The ideology behind gender equality advocacy is “It doesn’t’ matter what your gender is, we are equal in everything”. That is, no gender stereotyping. That is the ideal; now let us discuss the reality.

To start with I will make the bold claim that “In today’s world, most women are guilty of gender stereotyping”. You will see what I mean shortly.

I always thought that the goal of any anti- (such as anti-racism, anti-tribalism, anti-genderalism (if that is even a word) and so on) was to walk (or work) under the guise that the factor that gave rise to the “-ism” in the first place did not exist (such as a black man being black or a white man being white). Wouldn’t it be a cool sight when a white man can say to a black man in a truly race-equal environment “Hey black man do you want to go get a drink” and the black man replies without taking offence “Sure white boy I would love to”. Of course this kind of dialogue should have taken place before they exchange names if not it would be stupid. But I digress. Today’s write-up asks the question, why is it that when most women want to get you to do something you don’t want to do or can’t do they always use 1 of the following 2 statements (They are particularly used when money is involved):
  • You don’t love me (if you are in a relationship or trying to get into one with her)
  • Are you not a man?
The former I will skip for today. The latter is the one of interest. WTF (kids please close your ears), I thought the whole gender equality thing was so that we stop such gender stereotyping.

It is amazing how the same gender of human beings can go from saying “What a man can do a woman can do better” to saying something as contradicting as “Are you not a man?” all in the same 24 hour clock. Interesting isn’t it? In the first statement, she is strong and superhuman and in the second statement she suddenly became the weak and helpless victim. I don’t know if I should call this hypocrisy, vacuousness or mental manipulation. Wouldn’t it be a truly gender equal world when a man can say to a woman “You sleep on the couch while I sleep in the bed”. Without the man hearing a cliché “You are not even a gentleman”. More gender stereotyping in action if you ask me. Seriously what happened to my fundamental human right and free will to choose to say no or yes when I want to. I am not sure if you see where I am going with this.

My response is simple. Real men can see through this act. The only men who fall for it are babies, wankers or have less testosterone than the rest of us. Nobody is trying to disrespect you or not help out when we can. But when a man says he can’t do something, he can’t. Let it go. Well I pity the fool who falls victim of this lame act and ends up dead in a bid to please a selfish woman. I rest my case.