Skip to content

Tạo annotation validator để kiểm tra Entity

1. Giới thiệu

Bản thân Hibenate và Java đã cung cấp cho chúng ta rất nhiều phương thức để validate model như: @Size, @NotNull, @NotEmpty, @NotBlank, @Email, @Min, @Max, …

Tuy nhiên trên project thực tế có rất nhiều yêu cầu đặt ra, tuỳ thuộc vào business và quy mo project.

Ví dụ như một đối tượng Book có thuộc tính là code để quản lý mã của sách đó trong hệ thống của nhà sách. Một book code hợp lệ phài bắt đầu bằng “BK_”.

2. Setup

Thêm dependency vào pom.xml

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

3. Create Model & Controller

package com.example.demo.LearnController;

public class BookRequest {

    private String title;
    private String code;
    private String author;

}
@RestController
public class BookController {

    @PostMapping("/book")
    public String postRequest(@Valid @RequestBody BookRequest bookRequest) {

        return bookRequest.toString();
    }
}

4. Create Annotation

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = BookCodeValidator.class)
public @interface BookCodeVerify {

    String message() default "Invalid book code.";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

5. Create Validator

import javax.validation.ConstraintValidatorContext;

public class ConstraintValidatorUtils {

    private ConstraintValidatorUtils() { }

    public static void createConstraintViolation(ConstraintValidatorContext context, String errorCode) {
        // Disable nhung tham so constraint violation mac dinh
        context.disableDefaultConstraintViolation();

        // Them nhung tham so constraint violation duoc truyen vao thong qua method nay
        addConstraintViolation(context, errorCode);
    }

    public static void addConstraintViolation(ConstraintValidatorContext context, String errorCode) {
        ConstraintValidatorContext.ConstraintViolationBuilder builder = context.buildConstraintViolationWithTemplate(errorCode);
        builder.addConstraintViolation();
    }
}
import org.springframework.util.StringUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class BookCodeValidator implements ConstraintValidator<BookCodeVerify, String> {

    private static final String BOOK_CODE_PREFIX = "BK_";

    @Override
    public boolean isValid(String code, ConstraintValidatorContext context) {

        if(!StringUtils.hasText(code)) {
            ConstraintValidatorUtils.createConstraintViolation(context, "Please enter book code.");
            return false;
        }

        if (!code.startsWith(BOOK_CODE_PREFIX)) {
            ConstraintValidatorUtils.createConstraintViolation(context,"Book code must be start with BK_");
            return false;
        }

        return true;
    }
}

6. Applying Validation Annotation

Gắn @BookCodeVerify vào thuộc tính muốn validate

import com.example.demo.Validator.BookCodeVerify;

public class BookRequest {

    private String title;

    @BookCodeVerify
    private String code;

    private String author;

}

7. Test with API

7.1 Attribute valid

7.2 Attribute blank

{
    "timestamp": "2021-06-01T11:06:33.225+00:00",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "BookCodeVerify.bookRequest.code",
                "BookCodeVerify.code",
                "BookCodeVerify.java.lang.String",
                "BookCodeVerify"
            ],
            "arguments": [
                {
                    "codes": [
                        "bookRequest.code",
                        "code"
                    ],
                    "arguments": null,
                    "defaultMessage": "code",
                    "code": "code"
                }
            ],
            "defaultMessage": "Please enter book code.",
            "objectName": "bookRequest",
            "field": "code",
            "rejectedValue": "",
            "bindingFailure": false,
            "code": "BookCodeVerify"
        }
    ],
    "path": "/book"
}

7.3 Attribute invalid

{
    "timestamp": "2021-06-01T11:02:18.152+00:00",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "BookCodeVerify.bookRequest.code",
                "BookCodeVerify.code",
                "BookCodeVerify.java.lang.String",
                "BookCodeVerify"
            ],
            "arguments": [
                {
                    "codes": [
                        "bookRequest.code",
                        "code"
                    ],
                    "arguments": null,
                    "defaultMessage": "code",
                    "code": "code"
                }
            ],
            "defaultMessage": "Book code must be start with BK_",
            "objectName": "bookRequest",
            "field": "code",
            "rejectedValue": "cleancode",
            "bindingFailure": false,
            "code": "BookCodeVerify"
        }
    ],
    "path": "/book"
}
Published inSpring Framework

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *