REST webservice in Java Spring、Jersey、およびHibernate(JPA)を使用して)を構築しています。
現在、私のリソースに検証のサポートを追加しようとしています。 JSR-303(Bean validation)は適切な選択肢として自然に登場しました(私はJSR-303のリファレンス実装であるHibernate Validatorを使用しています)。ただし、最初にいくつかの概念を統合しようとしています。
少なくとも2種類の可能な検証があるように思えます。
String
プロパティが有効な電子メールであるかどうかを確認し、Integer
プロパティが10
より大きいかどうかを確認します。これは機能しています予想通り。 javax.validation.ConstraintViolationException
を適切なHTTP応答にマップするJAX-RS ExceptionMapperを登録しました。「データ整合性検証」の意味を具体的に例を挙げて説明します。これは、2つ以上のリソース間に関係がある場合に発生します。 2つのリソースを想像してください:Product
とCategory
。 A Product
has a Category
。クライアントがサーバーにProduct
の表現を送信して作成する場合(POST HTTPリクエスト))、クライアントはCategory
に製品を通知する必要があります。もちろん、クライアントは事前にカテゴリを知っている必要があります。JSONで次のようなものを想像してください。
{
"quantity": "10",
"state": "PRODUCED",
"category": {
"id": "123"
}
}
まあ、ID 123
のカテゴリは存在しないかもしれません。これをデータベースに挿入しようとすると、明らかに外部キー関連の例外が発生します。したがって、通常のプロパティの検証と同様に、これらの問題を検証して適切なメッセージをクライアントに返す必要があると思います。
今、私の主な質問は次のとおりです。
これらの質問はJavaに多少関連していますが、これらの問題についていくつかの新しい視点を得ることも期待していました。テクノロジーに依存しないものもあります。 :) REST webservices。でこれらの問題に対する独自のソリューションを提供できれば素晴らしいと思います
解決策は、JAX-RS JacksonJaxbJsonProvider
とMessageBodyReader
を実装するJacksonのMessageBodyWriter
をサブクラス化することになった。私は素晴らしい dropwizardのアプローチ に触発されました。このプロバイダーでは、なんとかしてValidatorインスタンスを挿入する必要があります(私はSpringを注入に、Hibernate ValidatorをJSR-303実装に使用しました)。 Hibernate ORMを使用する場合は、エンティティの検証を無効にすることを忘れないでください。そうしないと、同じエンティティを2回検証することになります。しかし、それは望ましいことかもしれません。
次に、このサブクラス化されたMessageBodyReader
でオブジェクトを検証し、バリデーターのエラーを含むカスタムInvalidEntityException
をスローします。 JAX-RSも作成しましたExceptionMapper<InvalidEntityException>
すべてのInvalidEntityException
を適切なHTTP応答にマップします。私の場合、私はBad Requestとエラーの説明を含むJSONオブジェクトを返しました。
このMessageBodyReaderが@Valid
および@Validated
アノテーション。つまり、グループを正しくサポートします。アプリケーション全体で同じ種類の検証を実行したくないので、これは重要です。例は、部分更新(PUT)を実行する場合です。または、たとえば、POSTリクエストではidプロパティはnullでなければなりませんが、それ以外の場所ではnull以外にする必要があります。
データの整合性の検証はまだ完全には扱われていません。しかし、データベースの例外をキャッチして自分のドメインの例外(DataIntegrityException
など)に変換することを計画しています。
UPDATE:
JAX-RS 2以降、これを行うための推奨される方法は、Bean検証サポートを使用することです。ここを確認してください: https://jersey.Java.net/documentation/latest/bean-validation.html
JSR-303/JSR-349を介したリソース引数の検証にJersey 2.0を使用できるようになりました。
https://jersey.Java.net/documentation/latest/bean-validation.html#d0e9301
_jersey filters
_を使用して、リクエストデータの検証を行うことができます。
まあ、ID 123のカテゴリは存在しないかもしれません。これをデータベースに挿入しようとすると、明らかに外部キー関連の例外が発生します。
このような場合、データアクセスレベルの検証に依存できます。ただし、クライアントに同期的に応答する場合は、通常、このビジネスロジックをサービスAPIで公開することをお勧めします。つまり、isValidCategory(int id)
のようなAPIがあり、DAOよりも高いレベルでクエリできるため、データアクセスレイヤーでエラー/例外が発生するまで実際に待機する必要はありません。明らかに、これは依然としてデータベースルックアップを意味する場合があります(システムによって異なります)が、キャッシュやその他のメカニズムを使用して応答時間を改善するように最適化することは、まったく別の問題です。
Beanバリデーターについて言えば、JSR 303実装である Hibernate Validator を見ることができます。
Oval は、オブジェクトを評価するのに最適なパッケージです。単体テストのアサーションと自動テストを生成すると非常に便利です。