This time, I would like to explain the input check method using Bean Validation
.
validate
method of Validator
and execute the input check.Add the required libraries to the dependencies.
javax.el
is also added as it is needed for message resolution of hibernate-validator
.
The Bean Validation library (groupId: javax.validation, artifactId: validation-api
) is not described, but it is automatically added to the dependency because it has a dependency.
pom.xml
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.9.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b09</version>
</dependency>
Define the model class to be checked. At this time, annotate according to each check is added. The following three types of annotations can be added.
Some checks require a limit, such as @ Max
, which limits the maximum number, but this is set as an annotation attribute. The attributes that can be set differ for each annotation.
If you want to change the message displayed when the check fails, override it with the message
attribute. The message set in the message
attribute has the highest priority.
Book.java
package com.example.beanvalidation.app;
import java.io.Serializable;
import java.util.Date;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull
// @Pattern(regexp = "[0-9,-]+")
@Pattern(regexp = "[0-9,-]+", message = "Value entered${validatedValue}Is incorrect. Please enter in ISBM format.")
private String isbn;
@NotNull
@Size(max = 200)
private String title;
@Max(9999)
@Min(1)
private int pageCount;
@NotNull
@Past
private Date publishedDate;
// constructor, setter, getter omitted
}
Bean Validation
is an implementation library-dependent error message for the specification. In this case, the message defined by hibernate-validator
will be the default.
If you want to change this default message, you can override it with ValidationMessages.properties
located directly under the classpath.
This time I would like to change the default message of @ Past
.
Validation Messages directly under the classpath_ja.properties (for Japanese)
# javax.validation.constraints.Past.message=Date entered${validatedValue}Is incorrect. Please enter a past date.
javax.validation.constraints.Past.message=\u5165\u529B\u3055\u308C\u305F\u65E5\u4ED8 ${validatedValue} \u306F\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093\u3002\u904E\u53BB\u65E5\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
(Caution)
$ {validatedValue}
.ValidationMessages.properties
is multilingual and will be ValidationMessages_ja.properties
for Japanese.I would like to set various values for the Book
class defined above and actually perform an input check.
It is common to inject Validator
when using a DI container, but this time we will use a normal Java application with a main
method.
However, the usage of Validator
is the same.
ValidationDemo.java
package com.example.beanvalidation.app;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
public class ValidationDemo {
public static void main(String[] args) {
// 1. create validator
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
// 2. create target object
Book book = createBook();
// 3. validate
Set<ConstraintViolation<Book>> constraintViolations = validator
.validate(book);
// 4. check result
int errorCount = constraintViolations.size();
System.out.println("validate error count : " + errorCount);
if (errorCount > 0) {
showErrorDetails(constraintViolations);
}
System.out.println("=== demo : validate error ===");
// 2. create target object
book = createNgBook();
// 3. validate
constraintViolations = validator.validate(book);
// 4. check result
errorCount = constraintViolations.size();
System.out.println("validate error count : " + errorCount);
if (errorCount > 0) {
showErrorDetails(constraintViolations);
}
}
private static <T> void showErrorDetails(
Set<ConstraintViolation<T>> constraintViolations) {
for (ConstraintViolation<T> violation : constraintViolations) {
System.out.println("----------");
System.out.println(
"MessageTemplate : " + violation.getMessageTemplate());
System.out.println("Message : " + violation.getMessage());
System.out.println("InvalidValue : " + violation.getInvalidValue());
System.out.println("PropertyPath : " + violation.getPropertyPath());
System.out.println("RootBeanClass : " + violation.getRootBeanClass());
System.out.println("RootBean : " + violation.getRootBean());
}
}
private static Book createBook() {
Date publishedDate = Date.from(LocalDateTime.of(2017, 7, 21, 0, 0, 0)
.toInstant(ZoneOffset.ofHours(9)));
return new Book("978-4798142470",
"Thorough introduction to Spring Java application development with Spring Framework", 744,
publishedDate);
}
private static Book createNgBook() {
Date publishedDate = Date.from(LocalDateTime.of(2999, 7, 21, 0, 0, 0)
.toInstant(ZoneOffset.ofHours(9)));
return new Book("ERROR-ISBN-9999", null, 0, publishedDate);
}
}
For reference, the result of executing the above program is shown below.
Execution result
validate error count : 0
=== demo : validate error ===
validate error count : 4
----------
MessageTemplate : {javax.validation.constraints.Min.message}
Message : must be greater than or equal to 1
InvalidValue : 0
PropertyPath : pageCount
RootBeanClass : class com.example.beanvalidation.app.Book
RootBean : Book [isbn=ERROR-ISBN-9999, title=null, pageCount=0, publishedDate=Sun Jul 21 00:00:00 JST 2999]
----------
MessageTemplate : {javax.validation.constraints.Past.message}
Message :Date entered Sun Jul 21 00:00:00 JST 2999 is incorrect. Please enter a past date.
InvalidValue : Sun Jul 21 00:00:00 JST 2999
PropertyPath : publishedDate
RootBeanClass : class com.example.beanvalidation.app.Book
RootBean : Book [isbn=ERROR-ISBN-9999, title=null, pageCount=0, publishedDate=Sun Jul 21 00:00:00 JST 2999]
----------
MessageTemplate : {javax.validation.constraints.NotNull.message}
Message : must not be null
InvalidValue : null
PropertyPath : title
RootBeanClass : class com.example.beanvalidation.app.Book
RootBean : Book [isbn=ERROR-ISBN-9999, title=null, pageCount=0, publishedDate=Sun Jul 21 00:00:00 JST 2999]
----------
MessageTemplate :Value entered${validatedValue}Is incorrect. Please enter in ISBM format.
Message :Entered value ERROR-ISBN-9999 is incorrect. Please enter in ISBM format.
InvalidValue : ERROR-ISBN-9999
PropertyPath : isbn
RootBeanClass : class com.example.beanvalidation.app.Book
RootBean : Book [isbn=ERROR-ISBN-9999, title=null, pageCount=0, publishedDate=Sun Jul 21 00:00:00 JST 2999]
This time, I explained how to check the input by Bean Validation
.
I think it's simple and easy to understand because you can define the input check specifications just by adding the check annotation.
Recommended Posts