Spring Boot Tutorial

Spring Boot - Software Setup and Configuration (STS/Eclipse/IntelliJ)

Prerequisite (Spring Core Concepts)

Spring Boot Core

Spring Boot with REST API

Spring Boot with Database and Data JPA

Spring Boot with Kafka

Spring Boot with AOP

Validation in Spring Boot

Validation is a crucial aspect of any application. In Spring Boot, validation is often accomplished using the Java Bean Validation standard (JSR 380) with its reference implementation Hibernate Validator.

Here's a step-by-step guide to adding validation in a Spring Boot application:

1. Add Dependencies

First, you'll need to add the necessary dependencies to your pom.xml:

<!-- Spring Boot Starter Web includes Hibernate Validator for validation -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. Annotate Your Model

Use validation annotations on the fields of your model (or DTO) class:

public class User {
    
    @NotNull(message = "Name cannot be null")
    @Size(min = 2, max = 30, message = "Name should be between 2 and 30 characters")
    private String name;
    
    @Email(message = "Email should be valid")
    private String email;

    // getters, setters...
}

3. Validate in Controller

In your controller, annotate the model parameter with @Valid to trigger validation. Also, add an Errors or BindingResult parameter immediately after the model parameter to capture any validation errors:

@RestController
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<?> createUser(@Valid @RequestBody User user, BindingResult result) {
        if (result.hasErrors()) {
            // Handle validation errors, e.g., return a bad request response with error details
            return ResponseEntity.badRequest().body("Validation errors");
        }

        // Process the valid user data
        return ResponseEntity.ok("User created successfully");
    }
}

4. Exception Handling

Spring Boot provides an @ControllerAdvice annotation that you can use to handle exceptions globally. For validation, the MethodArgumentNotValidException is thrown when the validation fails:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return ResponseEntity.badRequest().body(errors);
    }
}

With the above exception handler, validation errors will be returned in a map format with field names as keys and their respective error messages as values.

5. Custom Validations

For cases where built-in validation annotations aren't enough, you can create custom validators:

  • Define an annotation for the validation:
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CustomValidator.class)
public @interface CustomValidation {
    String message() default "Custom validation failed";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
  • Implement the validator:
public class CustomValidator implements ConstraintValidator<CustomValidation, String> {

    @Override
    public void initialize(CustomValidation constraintAnnotation) {
        // Initialization code, if necessary
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true; // Use @NotNull separately to validate non-null
        }
        // Custom validation logic
        return value.startsWith("custom-");
    }
}
  • Use the custom validation in your model:
public class User {
    @CustomValidation
    private String customField;
}

By integrating validation into your Spring Boot application, you can ensure that data integrity and business rules are enforced. This leads to a more robust and reliable system.

1. Form validation in Spring Boot:

Form validation ensures that user input meets certain criteria before processing. In Spring Boot, this is achieved through validation annotations.

// Controller method with form validation
@PostMapping("/submitForm")
public String submitForm(@Valid @ModelAttribute("user") User user, BindingResult result) {
    if (result.hasErrors()) {
        return "errorPage";
    }
    // Process the form data
    userService.processForm(user);
    return "successPage";
}

2. Validation annotations in Spring Boot:

Spring Boot provides built-in validation annotations like @NotNull, @Size, etc., to express constraints on the form fields.

public class User {
    @NotNull
    private String username;

    @Size(min = 6, max = 12)
    private String password;

    // Getters and setters
}

3. Custom validation in Spring Boot:

Custom validations can be created by implementing Validator interface or using custom annotations.

// Custom validator
public class CustomValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return User.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        User user = (User) target;
        // Custom validation logic
        if (user.getPassword().contains(user.getUsername())) {
            errors.rejectValue("password", "password.invalid", "Password cannot contain username");
        }
    }
}

4. Using Hibernate Validator in Spring Boot:

Hibernate Validator is a popular choice for validation in Spring Boot, providing additional features.

<!-- Maven dependency -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>
// Using Hibernate Validator annotations
public class User {
    @Email
    private String email;

    @Pattern(regexp = "\\d{10}")
    private String phoneNumber;

    // Getters and setters
}

5. Validating RESTful APIs in Spring Boot:

For validating RESTful APIs, you can use validation annotations in combination with @RestController and @Validated.

@RestController
@Validated
public class ApiController {
    @GetMapping("/api/data")
    public ResponseEntity<String> getData(@RequestParam @Positive int id) {
        // API logic
        return ResponseEntity.ok("Data fetched successfully");
    }
}

6. Error handling and validation in Spring Boot:

Spring Boot automatically handles validation errors. You can customize error responses using @ExceptionHandler.

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> handleValidationException(MethodArgumentNotValidException ex) {
        return ResponseEntity.badRequest().body("Validation error: " + ex.getMessage());
    }
}

7. Spring Boot validation with Thymeleaf:

Thymeleaf templates can be integrated with Spring Boot for server-side rendering with validation support.

<!-- Thymeleaf template with validation error display -->
<form action="/submitForm" method="post" th:object="${user}">
    <input type="text" th:field="*{username}" />
    <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></span>

    <input type="password" th:field="*{password}" />
    <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>

    <button type="submit">Submit</button>
</form>

8. Validating request parameters in Spring Boot:

You can validate request parameters in Spring Boot controllers using validation annotations.

@GetMapping("/getData")
public ResponseEntity<String> getData(@RequestParam @NotBlank String name) {
    // Controller logic
    return ResponseEntity.ok("Hello, " + name);
}