BeanValidationの組み込みアノテーション
【前提条件】
[参考資料]
Bean Validation1.1仕様書
The Java Community Process(SM) Program - communityprocess - final
[その他]
Validatorの生成はCDIを利用しています。
【概要】
Bean Validationで標準で用意されている
Validation用のアノテーションについてです。
Bean Validationの参照実装はHibernate Validator5系となっているため、
Hibernate Validatorと同様のアノテーションがあります。
【Validatorオブジェクトの生成】
Bean Validationを行うためには
javax.validation.Validatorクラスのオブジェクトを使用します。
Validatorクラスの生成はCDIを利用しない方法とCDIを利用する方法があります。
[CDIを利用しない方法]
final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
最初にjavax.validation.ValidationのbuildDefaultValidatorFactoryメソッドを使用し、
javax.validation.ValidatorFactoryクラスのオブジェクトを生成します。
ValidatorFactory#getValidatorメソッドを呼び出すと
Validatorクラスのオブジェクトが生成されます。
【Validationアノテーション】
サンプルでは標準で用意されているアノテーションを使用します。
Validation用のアノテーションはjavax.validation.constraintsパッケージに配置されています。
JAX-RSのパラメータBeanとして利用するため
FormParamアノテーションを使用しています。
各アノテーションにはメッセージを設定することができますが、
今回のサンプルにはメッセージを設定していません。
import java.util.Date; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Digits; import javax.validation.constraints.Future; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.Past; import javax.validation.constraints.Size; import javax.ws.rs.FormParam; public class ValidationBaseBean { @DecimalMax("100") @DecimalMin("5") @FormParam("decimalValue") private Integer decimalValue = null; @Max(20) @Min(10) @FormParam("maxMinValue") private Integer maxMinValue = null; @Size(min = 5, max = 10) @FormParam("sizeValue") private String sizeValue = null; @Digits(integer = 3, fraction = 2) @FormParam("digitValue") private Double digitValue = null; @Future private Date futureDate = null; @FormParam("futureDate") private String futureDateValue = null; @Past private Date pastDate = null; @FormParam("pastDate") private String pastDateValue = null; // アクセサメソッドは省略 }
DecimalMaxアノテーションは数値の最大値、DecimalMinアノテーションは数値の最小値を指定します。
上記のサンプルでは5〜100までが正常値として認識されます。
サポートされている型はBigDecimal、BigInteger、CharSequence、byte(Byte), short(Short), int(Integer), long(Long)です。
MaxアノテーションはDecimalMaxと同様、MinアノテーションはDecimalMinと同様です。
それぞれのvalue値はlong型を指定するようになっています。
サポートされている型はBigDecimal、BigInteger、byte(Byte), short(Short), int(Integer), long(Long)です。
Sizeアノテーションは長さの指定を行うことができます。
サンプルでは5〜10までの長さが正常値として認識されます。
サポートされている型はCharSequence、Collection、Map、Arrayです。
Digitsアノテーションは数値の桁数を指定します。
サンプルでは整数が3桁まで、少数が2桁までが正常値として認識されます。
サポートされている型はBigDecimal、BigInteger、CharSequence、byte(Byte), short(Short), int(Integer), long(Long)です。
Futureアノテーションは未来日が、Pastアノテーションは過去日が正常値として認識されます。
サポートされている型はDate、Calendarです。
【Validationを実行する】
サンプルのソースはJAX-RSのリソースクラスです。
[Validate方法]
package jp.glory.sample01.resources; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Set; import javax.inject.Inject; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.ws.rs.BeanParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; import jp.glory.sample01.bean.ValidationBaseBean; @Path("/sample01") public class ValidationBaseResource { @Inject private Validator validator = null; @POST public Response postRequest(@BeanParam final ValidationBaseBean bean) throws ParseException { // StringをDateに変換 bean.setFutureDate(convertDate(bean.getFutureDateValue())); bean.setPastDate(convertDate(bean.getPastDateValue())); final Set<ConstraintViolation<ValidationBaseBean>> result = validator.validate(bean); if (result.isEmpty()) { return createSuccessResponse(); } return createErrorResponse(result); } private Date convertDate(final String dateValue) throws ParseException { final SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd"); if (dateValue.isEmpty()) { return null; } return format.parse(dateValue); } private Response createErrorResponse(final Set <ConstraintViolation<ValidationBaseBean>> validateResult) { // 後述 } private Response createSuccessResponse() { // エラーがなかった場合のResponseを返却する } }
Validationを行うにはValidator#validateメソッドにパラメータとしてBeanを渡します。
エラーの結果はjavax.validation.ConstraintViolationクラスのオブジェクトに格納され、
Setとして返却されます。
ConstraintViolationにはチェック対象のBeanのクラスを指定します。
[ConstraintViolation]
サンプルではConstraintViolationの中身を
HTMLとして出力します。
private Response createErrorResponse(final Set <ConstraintViolation<ValidationBaseBean>> validateResult) { final StringBuilder builder = new StringBuilder(); builder.append("<html>"); builder.append("<head>"); builder.append("<meta charset=\"utf-8\">"); builder.append("<title>Validation</title>"); builder.append("</head>"); builder.append("<body>"); for (final ConstraintViolation<ValidationBaseBean> result : validateResult) { builder.append("<div>"); builder.append(result.getPropertyPath().toString()); builder.append(" : "); builder.append(result.getInvalidValue()); builder.append(" : "); builder.append(result.getMessage()); builder.append("</div>"); } builder.append("</body>"); builder.append("</html>"); return Response.ok(builder.toString()).build(); }
getPropertyPathメソッドで対象のプロパティ名が、
getInvalidValueメソッドで設定された値が、
getMessageメソッドでメッセージが取得できます。