1概要

2.0バージョンの

Java Bean Validation

仕様には、いくつかの新機能が追加されています。その中には、コンテナの要素を検証する機能もあります。

この新しい機能は、Java 8で導入された型注釈を利用します。したがって、機能するにはJavaバージョン8以降が必要です。

  • バリデーションアノテーションは、コレクション、

    Optional

    オブジェクト、その他の組み込みおよびカスタムコンテナなどのコンテナに追加できます。


Java Beanの検証

の概要と必要な

Maven

の依存関係の設定方法については、リンク:/javax-validation[前の記事]を参照してください。

次のセクションでは、各種類のコンテナの要素の検証に焦点を当てます。


2コレクション要素


java.util.Iterable



java.util.List

、および

java.util.Map

型のコレクションの要素に検証アノテーションを追加できます。

リストの要素を検証する例を見てみましょう。

public class Customer {
     List<@NotBlank(message="Address must not be blank") String> addresses;

   //standard getters, setters
}

上記の例では、

Customer

クラスの

addresses

プロパティを定義しました。このクラスには、空にできない要素

Strings

が含まれています。


  • @ NotBlank

    検証は

    String

    要素に適用され、コレクション全体には適用されません** 。コレクションが空の場合、検証は適用されません。

空の

String



addresses

リストに追加しようとすると、検証フレームワークが

ConstraintViolation

を返すことを確認しましょう。

@Test
public void whenEmptyAddress__thenValidationFails() {
    Customer customer = new Customer();
    customer.setName("John");

    customer.setAddresses(Collections.singletonList(" "));
    Set<ConstraintViolation<Customer>> violations =
      validator.validate(customer);

    assertEquals(1, violations.size());
    assertEquals("Address must not be blank",
      violations.iterator().next().getMessage());
}

次に、

Map

型のコレクションの要素を検証する方法を見てみましょう。

public class CustomerMap {

    private Map<@Email String, @NotNull Customer> customers;

   //standard getters, setters
}


Map

要素のキーと値の両方に検証アノテーションを追加できることに注意してください。

無効な電子メールを含むエントリを追加すると検証エラーが発生することを確認しましょう。

@Test
public void whenInvalidEmail__thenValidationFails() {
    CustomerMap map = new CustomerMap();
    map.setCustomers(Collections.singletonMap("john", new Customer()));
    Set<ConstraintViolation<CustomerMap>> violations
      = validator.validate(map);

    assertEquals(1, violations.size());
    assertEquals(
      "Must be a valid email",
      violations.iterator().next().getMessage());
}


3 __オプションの値

検証制約は、

Optional

値にも適用できます。

private Integer age;

public Optional<@Min(18) Integer> getAge() {
    return Optional.ofNullable(age);
}

年齢が低すぎる

Customer

を作成し、検証エラーになることを確認します。

@Test
public void whenAgeTooLow__thenValidationFails() {
    Customer customer = new Customer();
    customer.setName("John");
    customer.setAge(15);
    Set<ConstraintViolation<Customer>> violations
      = validator.validate(customer);

    assertEquals(1, violations.size());
}

一方、

age

がnullの場合、

Optional

値は検証されません。

@Test
public void whenAgeNull__thenValidationSucceeds() {
    Customer customer = new Customer();
    customer.setName("John");
    Set<ConstraintViolation<Customer>> violations
      = validator.validate(customer);

    assertEquals(0, violations.size());
}


4非汎用コンテナ要素

型引数に注釈を追加する以外に、

@ UnwrapByDefault

注釈を持つ型の値抽出プログラムがある限り、非汎用コンテナに検証を適用することもできます。

値抽出プログラムは、検証のためにコンテナから値を抽出するクラスです。

  • リファレンス実装には、

    OptionalInt



    OptionalLong

    、および

    OptionalDouble

    ** の値エクストラクタが含まれています。

@Min(1)
private OptionalInt numberOfOrders;

この場合、

@ Min

アノテーションはラップされた

Integer

値に適用され、コンテナーには適用されません。


5カスタムコンテナエレメント

組み込みの値エクストラクタに加えて、独自のものを定義し、それらをコンテナ型で登録することもできます。

このようにして、カスタムコンテナの要素に検証アノテーションを追加することができます。


companyName

プロパティを含む新しい

Profile

クラスを追加しましょう。

public class Profile {
    private String companyName;

   //standard getters, setters
}

次に、

Customer

クラスに

@ NotBlank

アノテーションを使用して

Profile

プロパティを追加します。これにより、

companyName

が空の

String

ではないことを確認します。

@NotBlank
private Profile profile;

これが機能するには、プロファイルオブジェクトではなく

companyName

プロパティに適用される検証を決定する値抽出プログラムが必要です。


ValueExtractor

インターフェイスを実装し、

extractValue()メソッドをオーバーライドする

ProfileValueExtractor__クラスを追加しましょう。

@UnwrapByDefault
public class ProfileValueExtractor
  implements ValueExtractor<@ExtractedValue(type = String.class) Profile> {

    @Override
    public void extractValues(Profile originalValue,
      ValueExtractor.ValueReceiver receiver) {
        receiver.value(null, originalValue.getCompanyName());
    }
}

このクラスは、

@ ExtractedValue

アノテーションを使用して抽出された値の型も指定する必要があります。

また、検証をコンテナではなくラップされていない値に適用するように指定する

@ UnwrapByDefault

アノテーションを追加しました** 。

最後に、

javax.validation.valueextraction.ValueExtractor

というファイルを

ProfileValueExtractor

クラスのフルネームを含む

META-INF/services

ディレクトリに追加して、クラスを登録する必要があります。

org.baeldung.valueextractors.ProfileValueExtractor

空の

companyName

を持つ

profile

プロパティで

Customer

オブジェクトを検証すると、検証エラーが発生します。

@Test
public void whenProfileCompanyNameBlank__thenValidationFails() {
    Customer customer = new Customer();
    customer.setName("John");
    Profile profile = new Profile();
    profile.setCompanyName(" ");
    customer.setProfile(profile);
    Set<ConstraintViolation<Customer>> violations
     = validator.validate(customer);

    assertEquals(1, violations.size());
}


hibernate-validator-annotation-processor

を使用している場合、カスタムコンテナクラスに検証アノテーションを追加すると、

@ UnwrapByDefault

とマークされていると、バージョン6.0.2でコンパイルエラーになります。

これはhttp://docs.jboss.org/hibernate/stable/validator/reference/en-US/html__single/#validator-annotationprocessor-known-issues[既知の問題]であり、将来のバージョンで解決される可能性があります。


6. 結論

この記事では、__Java Bean Validation 2.0を使っていくつかのタイプのコンテナ要素を検証する方法を説明しました。


over on GitHub

の例の完全なソースコードを見つけることができます。