Open-Source-Perle

Bean-Validierung mit OVal

Eric Lewis

Die Validierung von Beans und anderen Objekten gehört wohl nicht zu den Lieblingsthemen der Entwickler. OVal kann ihnen aber die Validierung immerhin einfach machen und zugleich sogar ihren Aufwand begrenzen. Mit JSR-303 ist die Validierung wieder mehr in den Fokus der Community gerückt. Neben der Referenzimplementation Hibernate Validator gibt es eine Alternative: OVal (Object Validation). Es ist JSR-303 recht ähnlich und teilweise kompatibel dazu, aber man kann die gleichen Annotationen auch für Design By Contract verwenden.

Bean-Validierung

Stellen wir uns die Validierung eines Person-Beans vor: Vorname, Nachname und Schuhgröße sollen genügen, nur der Nachname ist obligatorisch.

Listing 1
@NotBlank
private String firstName;
@NotNull
@NotBlank
private String lastName;
@Range(min=14, max=49)
private Integer shoeSize;

Wie man sieht, kann der Vorname zwar null sein, aber nicht aus Leerzeichen bestehen; die Validierung der Schuhgröße wird erst aktiv, wenn diese nicht null ist. Validierungen können auf Felder und Getter-Methoden annotiert werden, aber auch auf Klassen. Für ein Collection-Feld kann man definieren, ob die Annotation für das Collection-Objekt oder dessen Elemente gilt, bei einer Map auch für deren Schlüssel. OVal bietet sehr viele vordefinierte Annotationen, aber man kann auch selber kreativ werden:

  • Für allgemein gültige Validierungen schreibt man am besten eine eigene Annotation.
  • Klassenspezifische Validierungen schreibt man als Methode (@ValidateWithMethod) oder als eigene Check-Klasse (@CheckWith).
  • Alternativ können auch Skriptsprachen wie JavaScript, Ruby oder Groovy eingesetzt werden: @Assert(expr=“…“).
  • Wer das Java Persistence API (JPA) einsetzt, lässt OVal am einfachsten gleich dessen Annotationen interpretieren, z. B. @Column(name=“LAST_NAME“, nullable=false, length=75) .
Profile

Manchmal hängt die Validierung vom Status eines Objekts ab. Die Person sollte (hoffentlich) nur einen Ehepartner haben, wenn sie verheiratet ist, und muss dafür auch volljährig sein:

@NotNull(profiles = {"married"})
private Person spouse;
@NotNull
@CheckWith(FullAgeCheck.class, profiles = {"married"})
private Date birthday;

Außerdem gibt es oft Validierungen, die nur Sinn machen, wenn das Objekt vollständig gefüllt ist. Für all diese Fälle gibt es Profile: Die Annotation wird nur berücksichtigt, wenn eines ihrer Profile aktiv ist. Das Profil default ist immer aktiv und muss daher nicht konfiguriert werden. Wer es noch individueller möchte, kann in der Annotation mit when=“…“ und einem Skriptausdruck z. B. festlegen, dass die Schuhgröße bei Vollmond höchstens 45 sein darf.

Design By Contract

Es gibt eine Menge Frameworks für DBC und eine Menge für Validierung, aber meines Wissens beherrscht nur OVal beide Disziplinen. Annotiert man eine Klasse mit @Guarded, können mithilfe einer AOP-Implementation (z. B. AspectJ) die Methodenparameter mit den bekannten Annotationen validiert werden (Precondition):

@Guarded
public class PersonDAO {
  public Person findPersonByID(@NotNull @Min(1) Integer id) { ... }
}

Praktisch: @AssertFieldConstraints übernimmt die Annotationen eines Felds, z. B. für eine Setter-Methode. Darüber hinaus können auch Rückgabewerte (Postcondition) und der Zustand des Objekts (Invariant) validiert werden – auch in Konstruktoren.

Für GUIs gibt es den Probe-Mode: Wenn die Validierung eines Parameters fehlschlägt, wird die Methode nicht ausgeführt. Damit wird es unmöglich, einen ungültigen Wert im Objekt zu speichern.

Fazit

Es gäbe noch viel mehr zu erwähnen, aber am besten probieren Sie OVal einfach mal aus. Die Entwickler sind sehr hilfsbereit und reagieren schnell auf Fragen, Vorschläge und Bug-Meldungen.

Eric Lewis arbeitet in der Schweiz im Eidgenössischen Institut für Geistiges Eigentum. Neben der Softwareentwicklung ist er auch mit verantwortlich für den Build und Continuous Integration.
Geschrieben von
Eric Lewis
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.