Total Pageviews

2018/02/07

Java Bean Validation example

Add dependencies to your pom.xml
    <!-- validation start  -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.0.Final</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.2.Final</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.1-b08</version>
    </dependency>
    <!-- validation end -->
        
    <!-- DI start -->
    <dependency>
        <groupId>com.google.inject</groupId>
        <artifactId>guice</artifactId>
        <version>4.1.0</version>
    </dependency>
    <!-- DI end -->
        
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>$1.16.18</version>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>21.0</version>
    </dependency>


Scenario
Assume I have a Customer bean, it have 6 attributes which include id, name, gender, age, email and dateOfBirth.
These attributes have its validation rules:

  1. id should not be null
  2. name should not by null or empty
  3. gender should not be null
  4. age should be between 18 and 60
  5. email should not be null or empty and should have valid format
  6. dateOfBirth should be before today


The Java bean with bean validation annotation looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package albert.practice.validation;

import java.util.Date;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;

import org.hibernate.validator.constraints.Range;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@AllArgsConstructor
@NoArgsConstructor
@ToString
@Data
public class Customer {
    public static enum Gender {
        MALE, FEMALE;
    }

    @NotNull(message = "顧客編號不可為 null")
    private Long id;

    @NotEmpty(message = "姓名不可為空")
    private String name;

    @NotNull(message = "性別不可為空")
    private Gender gender;

    @Range(min = 18, max = 60, message = "年齡必須介於 18 到 60 歲之間")
    private Integer age;

    @NotEmpty(message = "Email 不可為空")
    @Email(message = "Email 格式不合法")
    private String email;
    
    @Past(message = "生日必須要今天以前")
    private Date dateOfBirth;
}


Assume I have a CustomerService class to create Customer, it should validate Customer Java Bean before do insert. The main validate logic will be in validate method (line 25 ~ 38).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package albert.practice.validation;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.inject.Singleton;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Singleton
public class CustomerService {

    public void create(Customer customer) {
        validate(customer);
    }

    public static void validate(Object obj) {
        List<String> errors = new ArrayList<>();

        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<Object>> violations = validator.validate(obj);
        for (ConstraintViolation<Object> violation : violations) {
            errors.add(violation.getMessage());
        }

        String completeErrorMsg = Joiner.on("\n").join(errors);
        if (!Strings.isNullOrEmpty(completeErrorMsg)) {
            throw new IllegalArgumentException(completeErrorMsg);
        }
    }

}



The resource class will prepare Customer Object and invoke create method which provide by CustomerService
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package albert.practice.validation;

import com.google.inject.Guice;
import com.google.inject.Inject;

public class CustomerResource {

 @Inject
 private CustomerService service;
 
 public static void main(String[] args) {
    Customer customer = new Customer();
    customer.setId(null);
    customer.setAge(12);
    customer.setEmail("test@gmail.");
  
    new CustomerResource().createCustomer(customer);
 }
 
 public void createCustomer(Customer customer){
    service = Guice.createInjector().getInstance(CustomerService.class);
    service.create(customer);
 }
 
}


Execution message in console:
1
2
3
4
5
6
7
8
9
Exception in thread "main" java.lang.IllegalArgumentException: 性別不可為空
年齡必須介於 18  60 歲之間
Email 格式不合法
顧客編號不可為 null
姓名不可為空
 at albert.practice.validation.CustomerService.validate(CustomerService.java:35)
 at albert.practice.validation.CustomerService.create(CustomerService.java:20)
 at albert.practice.validation.CustomerResource.createCustomer(CustomerResource.java:22)
 at albert.practice.validation.CustomerResource.main(CustomerResource.java:17)



No comments: