Labs ICT
โญ Pro Login

Validation

Validating user input with annotations.

Validation

So you want to make sure users actually send good data to your API? Validation is your best friend here. Nobody wants a database full of garbage โ€” and Spring Boot makes it dead simple to prevent that.

Think of validation like a bouncer at a club. It checks every piece of data coming in and says "you're good" or "get out." No bad data gets past the velvet rope.

The @Valid Annotation

The magic starts with @Valid. You slap this on a request body parameter, and Spring Boot automatically runs all the validation rules you've defined on that object. It's like telling Spring "hey, check this before you use it."

Without @Valid, your validation annotations are just decorations sitting there doing nothing. With it, they actually enforce the rules.

@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
    User saved = userService.save(user);
    return ResponseEntity.ok(saved);
}

Common Validation Annotations

Spring Boot gives you a bunch of annotations out of the box. @NotNull ensures a value isn't null, @NotBlank makes sure a string isn't empty or just whitespace, and @Size controls the length of strings or the size of collections.

For numbers, you've got @Min and @Max to set boundaries. @Email checks that a string looks like a proper email address. These are your bread and butter for everyday validation.

public class User {
    @NotBlank(message = "Name is required")
    @Size(min = 2, max = 50, message = "Name must be 2-50 characters")
    private String name;

    @NotNull(message = "Email is required")
    @Email(message = "Please provide a valid email")
    private String email;

    @Min(value = 18, message = "Must be at least 18")
    @Max(value = 120, message = "Age cannot exceed 120")
    private int age;
}

Custom Validators

Sometimes the built-in annotations aren't enough. Maybe you need to check that a phone number follows a specific format, or that a username is unique in your database. That's where custom validators come in.

You create a custom annotation and a validator class that implements ConstraintValidator. It's like teaching the bouncer a new trick โ€” suddenly it can handle any rule you throw at it.

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
    String message() default "Invalid phone number";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class PhoneValidator implements ConstraintValidator<Phone, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.matches("^\\+?[0-9]{10,13}$");
    }
}

Just remember to handle validation errors properly โ€” either with @ControllerAdvice or by catching MethodArgumentNotValidException. Otherwise your users will just see cryptic 500 errors instead of helpful messages.

๐Ÿงช Quick Quiz

What is @Valid used for?