Gibt es schon Ansätze zur gemeinsamen Validierung von Java und JavaScript?

Bei einer Web-Anwendung hat man Validierungen, die man nur im Frostend machen möchte (z.B: illegale Zeichen in Textfeldern abfangen), in Frontend und Backend machen möchte (Gültigkeit eines Bezeichners), nur im Backend machen kann (Vorhandensein in der DB) oder auch vom Frontend ans Backend delegieren möchte. Ich würde mir wünschen, dass es einen einzigen “Punkt der Wahrheit” gibt, damit Frontend und Backend nicht divergieren.

Ich könnte mir sowas in der Art vorstellen, dass ein Annotation-Prozessor das entsprechende Daten-Objekt oder so einliest, und sowohl eine Java-Klasse wie auch eine Datei mit JavaScript-Funktionen zur Validierung (inklusive eventueller Call-Backs zum Frontend) erzeugt.

Gibt es sowas schon? Ist mein Ansatz over-engineered?

Das Thema ist schlecht googelbar, aber ich bin doch sicher nicht der Erste, der sowas machen möchte…

@Landei alte Socke, das mache ich auch gerade. Und bin in der vorteiligen Lage, sowohl Backend als auch Frontend. Aber mir ist aufgefallen (vielleicht hast du dich verschrieben): Das Backend muss auch validieren. Zumindest alles, was einen bestimmten Wertebereich oder eine Beziehung zu einer anderen Entität/Tabelle in der Datenbank hat. Bei tausenden von Benutzern könnte die Datenbank sonst fehlerhaft sein. Beidseitig validieren heißt auch Fehlerbehandlung auf beiden Seiten, leider. Beim Backend gibt’s noch einen ErrorHandler, andererseits dürfen Fehler nicht nach außen, sonst sind die Benutzer irritiert. Also kurz: Nur auf Seite des 'Frostend’s darfst/kannst du nicht sicherstellen, das es nur ‘vernünftigen’ Input gibt.


Also normalerweise habn Datenbank, Backend, Middleware und Frontend nix miteinander zu tun… d. h. auch, dass es ‘oft’ doppelten Code (also Redundanzen) gibt, leider, wollte ich damit sagen.
Aber beschreib bitte nochmal, wie diese Web-Anwendung aufgebaut ist.

Nope, da muss ich @CyborgBeta zustimmen, im Backend muss alles geprüft werden. Javascript kann die Benutzbarkeit steigern aber nicht die eigentliche Prüfung übernehmen. D.h. dein „punkt der Wahrheit“ ist irgendwo in der Business Logik, also typischerweise Layer 2 der klassischen Ansicht.

Ich dopple meist die Validierung. In der UI gibt es eine Validierung, die das Feld entsprechend markiert und Hinweise zum Beheben des Fehlers aufzeigt.
Die Fehler vom Server sorgen einfach für einen generellen Fehler.

Sicher muss das Backend „alles“ validieren, aber wenn ich z.B. bei jedem einzelnen Keystroke auf Gültigkeit überprüfe, brauche ich das trotzdem nur im Frontend zu machen (und dann den Bezeichner als ganzes im Backend). Gerade bei sowas will ich verhindern, dass beide Prüfungen divergieren (wenn z.B. sowas wie Case-Sensitivität geändert wird). Deshalb die Idee, den Validationscode für beides an einer Stelle (z.B. an Hand einer Annotation) zu erzeugen.

Und Du generierst dann einen Java- und einen Javascript-Validator über die Annotation? Ich kann mir noch nicht ganz vorstellen, was genau Deine Idee ist.

Das JSON-Schema könnte sich hierfür eignen. Frontend und Backend müssen dann bloß jeweils die Angaben gegen das Schema validieren.

Ich habe schon mal Code geschrieben, der so ähnlich gearbeitet hat: Ein Datenobjekt hatte ein paar Annotations, und ein Annotationprozessor hat dazu einen Controller mit Rest-Endpoint (für CRUD-Operationen auf dieser Klasse) erzeugt, sowie den JavaScript-Code, um darauf zuzugreifen.

Validierung ist doch keine Raketenwissenschaft, Annotation-Prozessing auch nicht, also mich wundert wirklich, dass es da anscheinend noch nichts „fertiges“ in der Richtung gibt.

Interessant, das könnte hilfreich sein.

Es gibt sowas in der Art schon. Einen Guide mit Spring und Thymeleaf findest du hier:

Hibernate bspw. kann für das Datenbankschema die selben Validation-Annotationen verwenden (JSR 303/349) (siehe hier). Auch Spring validiert übergebene Formulardaten transparent und stellt dem Controller ein Error-Objekt bereit, welches für die Ausgabe von Fehlermeldungen verwendet werden kan. Siehe auch hier.
Edit: dass das auch implizit mit Methodenargumenten der Controllermethoden geht, steht hier: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-arguments (drittletzter Punkt, Errors und BindingResult).

Die Validierung im Browser erfolgt allerdings nicht mit JavaScript, sondern mit den entsprechenden HTML5-Tags.

Diese Lösungen finde ich immer besonders schrecklich. Das sorgt häufig für viel oder komplexe Dokumentation der Services.

Validatoren auch für JavaScript zu generieren ist sicherlich etwas, das man tun kann. Bisher war mir der Aufwand dafür immer zu hoch. Gerade weil ich in der UI manchmal nicht so restriktiv bin.

Kannst du das weiter ausführen? Meinst du grundsätzlich Validierungen unter Zuhilfenahme der JSR 349-Annotationen? Oder meinst du transparente Validierung? Wenn du das meinst - wo liegt der Unterschied zum expliziten Aufruf des Validators? Dass man nicht sofort sieht, welche Constraints gelten sollen?

Ich meine damit, dass ein Fehlerobjekt als Rückgabe schnell komplex und unübersichtlich wird.

Einige Fragen:

  • Liefert der Endoint auch den Fehlertext? Wenn ja, wie läuft ggf. die Lokalisierung?
  • Wie geschieht das Mapping zum Feld in der UI? Liefert der Server hier die Info, welches Feld konkret fehlerhaft ist?

Der Client muss dann darauf reagieren können. Das muss natürlich auch dokumentiert sein. Häufig werden die Felder selbst markiert, das muss aus der Antwort des Services irgendwie hervorgehen. Da ist es meist einfach, wenn im Fehlerfall einfach ein Text oder Errorcode übermittelt wird.

Ich war da jedenfalls bisher immer ziemlich schnell bei “keine Lust mehr”. Die Lösungen von Spring sind auch meist an SpringMVC oder Thymeleaf gekoppelt (das ist jedenfalls mein aktueller Stand).

Da hast du Recht. Die benötigten Informationen sind Feldname und Fehlercode, das sinnvoll zu kapseln ist nicht ganz übersichtlich. Das ist allerdings ein grundsätzliches Problem, wenn man mit einem Validator arbeitet.

Wie zentralisierst du denn in der Regel die Überprüfung, ohne derartige Datenstrukturen zu erhalten?

Ab Spring 5 dann auch Spring WebFlux, aber das stimmt schon. Wenn man nicht sowieso mit Spring und Thymeleaf arbeitet, bringt einem das nichts. Ggf. gibt es zwar auch andere Templateengines, die das unterstützen. Prinzipiell aber, um auf diesen Thread zurück zu kommen: ja, sowas in der Art gibt es schon :wink: