All Java templates

Jakarta Bean Validation

Validation constraints, groups, custom validators, and validating method parameters.

DevZone Tools880 copiesUpdated Feb 19, 2026Jakarta EEJava
# CLAUDE.md — Jakarta Bean Validation

## Constraint annotations

- `@NotNull` — field must be present.
- `@NotBlank` — string must be non-null and contain at least one non-whitespace character.
- `@NotEmpty` — collection or string must be non-null and have ≥1 element/character.
- `@Size(min, max)` — bounds on collections, strings, arrays.
- `@Min`, `@Max`, `@DecimalMin`, `@DecimalMax` — numeric bounds.
- `@Pattern(regexp)` — regex match. Anchor with `^` and `$` if you mean the full string.
- `@Email`, `@URL` (Hibernate Validator) — common formats.

Apply on fields of DTOs:
```java
record CreateUser(
    @NotBlank @Email String email,
    @NotBlank @Size(min = 8, max = 100) String password,
    @NotNull @Min(13) Integer age
) {}
```

## Triggering validation

- In JAX-RS / Spring MVC, add `@Valid` to the request body parameter.
- For method parameters / return types, add `@Validated` to the class (Spring) or use `@ExecutableType` (Jakarta EE) with a CDI interceptor.
- Validate manually:
  ```java
  Set<ConstraintViolation<T>> violations = validator.validate(obj);
  if (!violations.isEmpty()) throw new ConstraintViolationException(violations);
  ```

## Groups

- For different validation rules at different stages (create vs update), use validation groups:
  ```java
  interface OnCreate {}
  interface OnUpdate {}

  record User(
      @Null(groups = OnCreate.class) @NotNull(groups = OnUpdate.class) String id,
      @NotBlank @Email String email
  ) {}
  ```
- Apply with `@Validated(OnCreate.class)` or `validator.validate(obj, OnCreate.class)`.
- Don't over-design groups. Most apps need 0–2.

## Cross-field validation

- Custom constraint annotation + a `ConstraintValidator<MyAnnotation, MyClass>`.
- Apply at class level (`@Target(TYPE)`) when the rule depends on multiple fields:
  ```java
  @PasswordsMatch
  record SignupRequest(@NotBlank String password, @NotBlank String confirmPassword) {}
  ```

## Method-level validation

- Annotate method parameters and return:
  ```java
  @NotNull
  User findById(@NotBlank String id);
  ```
- Requires CDI interceptor or Spring's method validation enabled.
- Throws `ConstraintViolationException` on violation.

## Error responses

- In JAX-RS, write a `ConstraintViolationExceptionMapper` to translate to a 400 with field-level errors.
- In Spring, `@RestControllerAdvice` with `@ExceptionHandler(MethodArgumentNotValidException.class)` is the equivalent.
- Return a structured error body — clients should know which field failed.

## Localization

- `@NotNull(message = "{user.name.required}")` references a message key.
- Provide `ValidationMessages.properties` per locale.
- Don't hard-code English messages in annotations for products with i18n.

## Don't

- Don't validate inside services if the same rule applies at the request boundary. Catch invalid input early.
- Don't use Bean Validation for business rules ("user can't have more than 3 active subscriptions"). That's domain logic, not input validation.
- Don't write `@NotNull String` next to `@NotBlank String`. `@NotBlank` already implies non-null and non-empty.
- Don't put validation annotations on getters in addition to fields — they're applied twice.

Other Java templates