Bean Validation constraint tester

Which constraints let null through, and where @NotEmpty stops and@NotBlank begins. The grid below is generated by running each constraint against each value, so it is the behaviour rather than a description of it.

The comparison

passes   fails   would not compile on that type

Test your own value

The rule behind most of the surprises

Every constraint except @NotNull, @NotEmpty and@NotBlank treats null as valid. A field annotated only@Size(min = 8) accepts a missing value. @Email accepts a missing value. @AssertTrue on a Boolean accepts a missing value.

This is deliberate: it lets one annotation express the format and another express whether the field is required, so an optional field can still be checked when present. It means a required field usually needs two:

@NotNull
@Size(min = 8, max = 64)
private String password;

Choosing between the three

ConstraintApplies toUse when
@NotNullAnythingThe field must be present. Numbers, booleans, objects, dates.
@NotEmptyString, Collection, Map, arrayA list must have at least one element.
@NotBlankString onlyAlmost every required text field a user types into.

For a text field submitted from a form, @NotBlank is nearly always the one you want. @NotEmpty accepts a string of spaces, which passes validation and then reaches the database as meaningless data.

Two more that catch people out

  • @Email accepts the empty string. An untouched email input posts "", which passes. Add @NotBlank when the address is required.
  • @Pattern anchors at both ends — the regex must match the whole value, not a part of it. It does test the empty string, unlike @Email.

Making it actually run

Annotations do nothing on their own. In a controller the parameter needs@Valid, and for nested objects each field needs it too:

@PostMapping("/orders")
ResponseEntity<Void> create(@Valid @RequestBody OrderRequest request) { ... }

record OrderRequest(
    @NotBlank String customer,
    @Valid @NotNull Address address   // @Valid recurses into Address
) {}

On a Spring bean method, validation needs @Validated on the class. Without one of these, the constraints are inert and everything passes.

Which package

Spring Boot 3 moved to Jakarta EE, so the import isjakarta.validation.constraints.*. Spring Boot 2 usedjavax.validation.constraints.*. Mixing them means the annotations compile and are then ignored, which looks exactly like validation not being switched on.