11_Validation
Code-Dateien
| Dateiname | Aktion |
|---|---|
| CODECode_Bank.zip | Download |
| CODECode_Pizza.zip | Download |
| CODECode_Urlaub.zip | Download |
Videos
| Dateiname | Aktion |
|---|---|
| VIDEOVideo_Bank_D | Abspielen |
| VIDEOVideo_Pizza_E | Abspielen |
| VIDEOVideo_Urlaub_D | Abspielen |
Lernmaterialien
Validation
set Validation
public void setPrice(Double price) throws PizzaOrderException {
if (price < 8)
throw new PizzaOrderException("The min. price is 8.0 Eur");
if (price > 30)
throw new PizzaOrderException("The max. price is 30.0 Eur");
this.price = price;
}
public void setSize(String size) throws PizzaOrderException {
if (Arrays.asList(sizes).contains(size) == false)
throw new PizzaOrderException("Wrong size must be: " + sizes.toString());
this.size = size;
}The problem is:
- Spring does not automatically know this is your validation rule
- Vaadin Binder does not automatically know it
- JPA/Hibernate does not automatically use it as Bean Validation metadata
So you must remember to call that logic yourself everywhere, or catch exceptions everywhere.
Jakarta Bean Validation
Jakarta Bean Validation is the standard Java validation API for declaring rules on objects and having them checked automatically or programmatically. The Jakarta specification describes it as a facility for validating objects, object members, methods, and constructors, plus a metadata/query API for constraints.
PizzaOrder.java
public class PizzaOrder {
@NotNull(message = "Price is required")
@DecimalMin(value = "8.0", message = "The min. price is 8.0 Eur")
@DecimalMax(value = "30.0", message = "The max. price is 30.0 Eur")
private Double price;
When you use Bean Validation annotations like
@NotNull, @DecimalMin, or @Email,
many Java frameworks can see those rules and run them
automatically.
So instead of writing validation manually in every setter, controller, form, or save method, you declare the rule once on the field, and the framework uses it.
Of course — here it is again, now with custom error messages.
Most important constraints
Required value
@NotNull
Value must not be null.
@NotNull(message = "Price is required")
private Double price;@NotEmpty
For strings, collections, arrays: must not be null and
not empty.
@NotEmpty(message = "The list must not be empty")
private List<String> toppings;@NotBlank
For strings: must not be null, empty, or only
spaces.
@NotBlank(message = "Name must not be blank")
private String customerName;Length / size
@Size
Checks the length of a string or size of a collection.
@Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters")
private String customerName;Numeric ranges
@Min / @Max
Mostly for integer values.
@Min(value = 1, message = "Quantity must be at least 1")
@Max(value = 10, message = "Quantity must not be greater than 10")
private Integer quantity;@DecimalMin /
@DecimalMax
Best for decimal values like prices.
@DecimalMin(value = "8.0", message = "The min. price is 8.0 Eur")
@DecimalMax(value = "30.0", message = "The max. price is 30.0 Eur")
private Double price;Format constraints
@Email
Checks whether a string looks like an email address.
@Email(message = "Please enter a valid email address")
private String email;@Pattern
Checks a value with a regular expression.
@Pattern(regexp = "\\d{4}", message = "PIN must contain exactly 4 digits")
private String pin;Boolean constraint
@AssertTrue
Must be true.
@AssertTrue(message = "You must accept the terms")
private boolean termsAccepted;Date constraints
@Past
Date must be in the past.
@Past(message = "Birth date must be in the past")
private LocalDate birthDate;@Future
Date must be in the future.
@Future(message = "Appointment date must be in the future")
private LocalDate appointmentDate;PizzaOrder
PizzaOrder.java
public class PizzaOrder implements Cloneable {
@Id
private Long orderId;
@NotNull(message = "Order date is required")
@Past(message = "Order date must be in the past")
private LocalDate orderDate;
@NotBlank(message = "Pizza is required")
private String pizza;
@NotBlank(message = "Size is required")
@Pattern(
regexp = "Small|Medium|Large|Family",
message = "Size must be Small, Medium, Large, or Family"
)
private String size;
@DecimalMin(value = "8.0", message = "The min. price is 8.0 Eur")
@DecimalMax(value = "30.0", message = "The max. price is 30.0 Eur")
private Double price;
@NotNull(message = "Quantity is required")
@Min(value = 1, message = "At least 1 pizza must be ordered")
@Max(value = 20, message = "You cannot order more than 20 pizzas")
private Integer quantity;
@NotNull(message = "Garlic is required")
private Boolean garlic;TestPizzaOrder.java
@Test
public void testSetSize() {
PizzaOrder o1 = new PizzaOrder();
PizzaOrder o2 = new PizzaOrder(LocalDate.now(), "Pepperoni", "Slice", 15.0, 1, true);
o1.setSize("Slice");
System.out.println(o1);
System.out.println(o2);
}Bean Validation does not run automatically just by calling
setSize().
The most important ones to remember
These are the core ones:
@NotNull@NotBlank@Size@Min/@Max@DecimalMin/@DecimalMax@Email@Valid
For forms, @NotBlank, @Size,
@Email, and range constraints are the ones you use most
often.
Einheitlicher Mechanismus für Frameworks
Bean Validation wird von vielen Frameworks automatisch unterstützt:
- Spring Boot prüft REST-Requests bei @Valid automatisch.
- Vaadin Binder kann die Annotations direkt auswerten.
- Hibernate/JPA prüft Entities beim Persistieren.
Wenn du Validierung nur in den Settern machst, weiß Spring/Vaadin davon nichts → du musst die Logik selbst an jeder Stelle aufrufen.
Flexibler Umgang mit Validierung
Mit Bean Validation kannst du Gruppen definieren:
@NotNull(groups = Create.class)
@Null(groups = Update.class)
private Long id;
Damit kannst du sagen: „Beim Erstellen muss id null sein, beim Ändern nicht.“
Mit Settern geht das kaum elegant.
Bessere Wiederverwendung & Lesbarkeit
Bean Validation ist deklarativ → jeder sieht sofort an der Klasse, welche Regeln gelten.
Settermethoden mit Validierung können unübersichtlich werden.
Standardisiert & erweiterbar
Jakarta Bean Validation ist ein Standard (JSR 380 / Jakarta EE) → in allen großen Frameworks gleich.
Du kannst eigene Annotations bauen (@UsernameOrEmail, @StrongPassword, …).
Bei Settern müsstest du die Logik jedes Mal neu schreiben.
Kurz gesagt
Setter-Validierung = geht, aber unflexibel, nicht wiederverwendbar, keine Framework-Unterstützung.
Bean Validation = deklarativ, lesbarer, automatisch von Spring/Vaadin/JPA unterstützt.
Deshalb: Bean Validation ist die bessere Wahl, gerade in Projekten mit Frameworks.
Grundidee
Du annotierst Felder oder Methoden deiner Klassen mit Constraints wie @NotNull, @Size, @Min, @Email …
Ein Validator prüft dann automatisch, ob diese Regeln erfüllt sind.
Wird eine Regel verletzt, bekommst du eine ConstraintViolation zurück.
Das ist praktisch für:
- Formulareingaben (z. B. Vaadin, JSF, REST-Requests)
- Datenbank-Entities (z. B. mit JPA/Hibernate)
- DTOs (Data Transfer Objects)
Wichtigsten Constraints
Allgemeine Constraints
- @Null → Wert muss null sein
- @NotNull → Wert darf nicht null sein (leerer String oder leere Liste ist aber erlaubt)
- @NotEmpty → String/Collection/Array darf nicht null und nicht leer sein
- @NotBlank → String darf nicht null, leer oder nur Whitespace sein
String / Collections
- @Size(min, max) → prüft Länge (String) oder Anzahl (Collection, Array, Map)
- @Pattern(regexp, flags) → String muss Regex entsprechen
- @Email → prüft E-Mail-Adresse (einfaches Pattern)
Zahlen
- @Min(value) → Zahl ≥ value
- @Max(value) → Zahl ≤ value
- @Positive → Zahl > 0
- @PositiveOrZero → Zahl ≥ 0
- @Negative → Zahl < 0
- @NegativeOrZero → Zahl ≤ 0
- @DecimalMin(value, inclusive) → wie @Min, aber für BigDecimal/String
- @DecimalMax(value, inclusive) → wie @Max, aber für BigDecimal/String
- @Digits(integer, fraction) → maximale Anzahl von Stellen vor/nach dem Komma
Datum/Zeit
- @Past → muss in der Vergangenheit liegen
- @PastOrPresent → muss heute oder früher sein
- @Future → muss in der Zukunft liegen
- @FutureOrPresent → muss heute oder später sein
Booleans
- @AssertTrue → Wert muss true sein
- @AssertFalse → Wert muss false sein
Beispiele
import jakarta.validation.constraints.*;
public class User {
@NotBlank(message = "Der Benutzername darf nicht leer sein")
private String username;
@Size(min = 8, max = 20, message = "Das Passwort muss zwischen 8 und 20 Zeichen lang sein")
private String password;
@Email(message = "Bitte eine gültige E-Mail-Adresse angeben")
private String email;
}