web-dev-qa-db-ger.com

Umgang mit Ressourcenprüfung in REST Internetdienste?

Ich baue einen REST Webservice in Java mit Spring, Jersey und Hibernate (JPA).

Jetzt versuche ich in meinen Ressourcen Unterstützung für die Validierung hinzuzufügen. JSR-303 (Bean-Validierung) erschien natürlich als geeignete Wahl (ich verwende Hibernate Validator, die Referenzimplementierung von JSR-303). Ich versuche jedoch zuerst einige Konzepte zu konsolidieren.

Es scheint mir, dass es mindestens zwei Arten von möglichen Validierungen gibt:

  • Regelmäßige Überprüfung von Feldern, z. Überprüfen Sie, ob eine Eigenschaft nicht NULL ist. Überprüfen Sie, ob eine String -Eigenschaft eine gültige E-Mail-Adresse ist. Überprüfen Sie, ob eine Integer-Eigenschaft größer als 10 ist. Ich habe einen JAX-RS ExceptionMapper registriert, der javax.validation.ConstraintViolationException's in richtigen HTTP-Antworten abbildet.
  • Datenintegritätsüberprüfung

Was ich unter "Datenintegritätsprüfung" genau verstehe, erkläre ich an einem Beispiel. Dies geschieht, wenn Beziehungen zwischen zwei oder mehr Ressourcen bestehen. Stellen Sie sich zwei Ressourcen vor: eine Product und eine Category. Eine Producthat eine Category. Wenn der Client die Repräsentation der zu erstellenden Product an den Server sendet (eine POST - HTTP-Anforderung), muss er die Category des Produkts informieren. Natürlich muss der Kunde die Kategorien vorher kennen. Stellen Sie sich in JSON so etwas vor:

{
   "quantity": "10",
   "state": "PRODUCED",
   "category": {
      "id": "123"
   }
}

Nun, die Kategorie mit der ID 123 existiert möglicherweise nicht. Wenn wir versuchen, dies in die Datenbank einzufügen, wird offensichtlich eine fremdschlüsselbezogene Ausnahme angezeigt. Ich gehe also davon aus, dass wir diese Probleme überprüfen und eine korrekte Nachricht an den Client senden müssen, genau wie bei den normalen Eigenschaftsüberprüfungen.


Nun sind meine Hauptfragen:

  1. Im Moment führe ich die Validierung auf Datenzugriffsebene durch die Integration von JPA mit Bean Validation durch. Sollten die Validierungen durchgeführt werden vor/nach Serialisierungsprozessen, vor/nach Datenbankoperationen oder beide?
  2. Umgang mit Data Integrity Validations? Manuell? (d. h. explizite Abfrage der Datenbank, um die Datenintegrität zu überprüfen) Oder sollten wir einfach versuchen, sie trotzdem einzufügen und dann Datenbank- (oder DAO-) Ausnahmen zu erfassen? Bean Validation hat nichts mit dieser Art von Validierung zu tun, richtig?
  3. Wenn Sie Erfahrung mit JAX-RS/REST und Bean Validation haben, würde ich mich freuen, wenn Sie mich darüber informieren. Gruppen verwenden?

Diese Fragen haben etwas mit Java zu tun, aber ich hatte auch gehofft, neue Perspektiven auf diese Fragen zu bekommen. Einige technologieunabhängige. :) Es wäre schön, wenn Sie auf Ihren REST Webservices eigene Lösungen für diese Probleme bereitstellen könnten.

20
miguelcobain

Die Lösung endete damit, Jacksons JacksonJaxbJsonProvider zu unterordnen, das ein JAX-RS MessageBodyReader und MessageBodyWriter implementiert. Ich war inspiriert von dem erstaunlichen dropwizard's approach . In diesem Provider müssen wir irgendwie eine Validator-Instanz injizieren (ich habe Spring for Injection und Hibernate Validator für die JSR-303-Implementierung verwendet). Wenn Sie Hibernate ORM verwenden, müssen Sie die Entitätsüberprüfung deaktivieren. Andernfalls überprüfen Sie dieselbe Entität zweimal. Es kann jedoch sein, was gewünscht wird.

Dann validiere ich in dieser Unterklasse MessageBodyReader das Objekt und werfe eine benutzerdefinierte InvalidEntityException mit den Fehlern des Validators. Ich habe auch einen JAX-RS ExceptionMapper<InvalidEntityException> erstellt, der jede InvalidEntityException einer richtigen HTTP-Antwort zuordnet. In meinem Fall habe ich eine ungültige Anforderung und ein JSON-Objekt mit der Fehlerbeschreibung zurückgegeben.

Beachten Sie, dass dieser MessageBodyReader nach @Valid und @Validated Anmerkungen sucht. Dies bedeutet, dass Gruppen korrekt unterstützt werden. Dies ist wichtig, da wir wahrscheinlich nicht die gleiche Art von Validierung für die gesamte Anwendung durchführen möchten. Ein Beispiel ist, wenn wir ein teilweises Update (PUT) durchführen möchten. Oder eine id-Eigenschaft muss beispielsweise in einer POST -Anforderung null sein, darf aber an keiner anderen Stelle null sein.

Datenintegritätsvalidierungen werden noch nicht vollständig behandelt. Ich plane jedoch, Datenbankausnahmen abzufangen und in meine eigenen Domain-Ausnahmen zu konvertieren (z. B. DataIntegrityException), da dies effizienter und lockerer mit mir verbunden zu sein scheint.


UPDATE:

Seit JAX-RS 2 wird empfohlen, die Bean-Validierungsunterstützung zu verwenden. Überprüfen Sie hier: https://jersey.Java.net/documentation/latest/bean-validation.html

8
miguelcobain

Sie können jetzt Jersey 2.0 zur Validierung von Ressourcenargumenten über JSR-303/JSR-349 verwenden.

https://jersey.Java.net/documentation/latest/bean-validation.html#d0e9301

6
yeforriak

Sie können jersey filters verwenden, um Ihre Anfragedaten zu validieren.

Nun, die Kategorie mit der ID 123 existiert möglicherweise nicht. Wenn wir versuchen, dies in die Datenbank einzufügen, wird offensichtlich eine fremdschlüsselbezogene Ausnahme angezeigt.

In solchen Fällen kann man sich auf die Validierungen auf Datenzugriffsebene verlassen. Wenn Sie jedoch synchron auf Ihren Client reagieren möchten, ist es normalerweise besser, diese Geschäftslogik durch eine Service-API verfügbar zu machen. Sie verfügen möglicherweise über eine API wie isValidCategory(int id), die auf einer höheren Ebene als DAO abgefragt werden kann, sodass Sie nicht wirklich warten müssen, bis auf die Datenzugriffsebene ein Fehler/eine Ausnahme auftritt. Natürlich kann dies immer noch eine Datenbanksuche (abhängig von Ihrem System) bedeuten. Die Optimierung der Reaktionszeit mit Caching oder einem anderen Mechanismus ist jedoch ein völlig anderes Problem.

Über Bean-Validatoren können Sie einen Blick auf Hibernate Validator werfen, bei dem es sich um eine JSR 303-Implementierung handelt.

1
Swapnil

Oval ist das beste Paket, um ein Objekt auszuwerten. Es ist sehr nützlich, eine Unit-Test-Assertion und einen automatisierten Test zu erstellen.

0
مصطفی