Common Constraints
Jakarta Bean Validation ships a rich set of built-in constraint annotations that cover the vast majority of input rules — required fields, length limits, numeric ranges, formats, and dates. This page is a practical reference: what each annotation does, the types it applies to, and a worked example on a record DTO. All imports come from jakarta.validation.constraints.
Constraints reference
| Annotation | Applies to | Passes when |
|---|---|---|
@NotNull | any type | value is not null |
@NotEmpty | String, Collection, Map, array | not null and size/length > 0 |
@NotBlank | CharSequence | not null and contains at least one non-whitespace char |
@Size(min, max) | String, Collection, Map, array | length/size within [min, max] |
@Min(v) / @Max(v) | integral numbers | value >= v / <= v |
@Positive / @PositiveOrZero | numbers | value > 0 / >= 0 |
@Negative / @NegativeOrZero | numbers | value < 0 / <= 0 |
@DecimalMin / @DecimalMax | numbers, String | within a BigDecimal bound |
@Digits(integer, fraction) | numbers, String | digit counts within limits |
@Email | CharSequence | well-formed email address |
@Pattern(regexp) | CharSequence | matches the regular expression |
@Past / @PastOrPresent | date/time types | in the past / not in the future |
@Future / @FutureOrPresent | date/time types | in the future / not in the past |
@AssertTrue / @AssertFalse | boolean | value is true / false |
Note: Every constraint (except
@NotNull) treatsnullas valid.@Size,@Patternand friends pass on a null value — combine them with@NotNull(or@NotBlank) when the field is also required.
@NotNull vs @NotEmpty vs @NotBlank
These three are the most commonly confused. The distinction matters:
@NotNull String a; // rejects null only; "" and " " are OK
@NotEmpty String b; // rejects null and ""; " " is OK
@NotBlank String c; // rejects null, "", and " " (whitespace-only)
| Input | @NotNull | @NotEmpty | @NotBlank |
|---|---|---|---|
null | fail | fail | fail |
"" | pass | fail | fail |
" " | pass | pass | fail |
"hi" | pass | pass | pass |
Use @NotBlank for required text fields, @NotEmpty for required collections, and @NotNull for objects, numbers, and booleans.
A worked example
Here is a realistic registration DTO using a record, combining several constraints:
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
public record RegistrationRequest(
@NotBlank
@Size(min = 2, max = 50)
String fullName,
@NotBlank
@Email
String email,
@NotBlank
@Pattern(regexp = "^\\+?[0-9]{7,15}$", message = "invalid phone number")
String phone,
@Min(18) @Max(120)
int age,
@NotNull
@Past
LocalDate dateOfBirth,
@NotNull
@PositiveOrZero
@Digits(integer = 6, fraction = 2)
BigDecimal accountBalance,
@NotEmpty
@Size(max = 5)
List<@NotBlank String> roles,
@AssertTrue(message = "you must accept the terms")
boolean termsAccepted
) {}
A few things worth noting:
@Size(max = 50)onfullNamecaps the length;@Min/@Maxbound the numericage.@Patternuses a regex — double the backslashes in Java string literals.@Digits(integer = 6, fraction = 2)allows up to six digits before and two after the decimal point.List<@NotBlank String>validates each element of the collection, not just the list itself.- Each annotation accepts a
messageattribute to override the default text.
Custom messages and placeholders
Constraint defaults are usable but generic. Override message, and reference the constraint’s own attributes with {} placeholders:
@Size(min = 8, max = 64, message = "password must be between {min} and {max} characters")
String password;
You can also externalize messages to a ValidationMessages.properties file on the classpath:
# ValidationMessages.properties
user.email.invalid=Please provide a valid email address
@Email(message = "{user.email.invalid}")
String email;
Tip: Keep regular expressions readable. For an email field, prefer
@Pattern— Hibernate Validator’s implementation handles the tricky edge cases of the address grammar for you.
Composing constraints
Multiple annotations on one field are combined with logical AND — all must pass. Validation does not short-circuit by default, so a single field can report several violations at once (e.g. both @NotBlank and @Size). You can build a reusable composed constraint for common combinations; see Custom Validators.