Logo

dev-resources.site

for different kinds of informations.

Implement data validation in Spring Boot

Published at
8/26/2024
Categories
validation
springboot
Author
stackpuz
Categories
2 categories in total
validation
open
springboot
open
Author
8 person written this
stackpuz
open
Implement data validation in Spring Boot

data validation in spring boot

Data validation is a crucial aspect of software development, ensuring that input data is accurate and meets requirements before it’s processed or stored. Spring Boot offers a simple and flexible approach to data validation.

This guide will show you how to implement data validation in Spring Boot, helping you build secure and reliable applications. You’ll learn how to leverage built-in validation annotations to making validation logic.

Prerequisites

  • JAVA 17
  • Maven

Project structure

β”œβ”€ pom.xml
└─ src
   └─ main
      β”œβ”€ java
      β”‚  └─ com
      β”‚     └─ stackpuz
      β”‚        └─ example
      β”‚           β”œβ”€ App.java
      β”‚           β”œβ”€ controller
      β”‚           β”‚  └─ UserController.java
      β”‚           └─ entity
      β”‚              └─ User.java
      └─ resources
         └─ templates
            └─ index.html
Enter fullscreen mode Exit fullscreen mode

Project files

pom.xml

This file contains the configuration settings and dependencies for the Maven project.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.stackpuz</groupId>
    <artifactId>example-validation</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>example-validation</name>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.10</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
       </dependencies>
</project>

Enter fullscreen mode Exit fullscreen mode

App.java

This file is the main entry point for the Spring Boot application.

package com.stackpuz.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Since this sample project does not use a database, we disable the database configuration by excluding DataSourceAutoConfiguration.class

User.java

The User class is used for testing validation in the application. It includes data annotations to enforce validation rules:

package com.stackpuz.example.entity;

import jakarta.persistence.Entity;
import jakarta.validation.constraints.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDate;

import org.springframework.format.annotation.DateTimeFormat;

@Entity
@Getter
@Setter
@NoArgsConstructor
public class User {

    @NotNull
    private Integer id;

    @Size(max = 10)
    private String name;

    @Pattern(regexp = "^\\S+@\\S+\\.\\S+$", message = "Invalid email address")
    private String email;

    @Min(1)
    @Max(100)
    private Integer age;

    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private LocalDate birthDate;
}
Enter fullscreen mode Exit fullscreen mode

UserController.cs

This file handles incoming requests and validates user input data.

package com.stackpuz.example.controller;

import com.stackpuz.example.entity.User;
import jakarta.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

@Controller
public class UserController {

    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("user", new User());
        return "index";
    }

    @PostMapping("/submit")
    public String submit(@Valid @ModelAttribute("user") User user, BindingResult result, Model model) {
        if (!result.hasErrors()) {
            model.addAttribute("pass", true);
        }
        return "index";
    }
}
Enter fullscreen mode Exit fullscreen mode

@GetMapping("/") will returns the index.html content, which typically contains a form for user input.

@PostMapping("/submit") processes form submissions and uses result.hasErrors() to indicate whether the input data is valid or not.

index.html

The HTML user input form is designed to test the validation rules applied to the User Entity. It typically includes fields that correspond to the properties of the User class.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <script>
        function fill(valid) {
            document.getElementById('id').value = (valid ? '1' : '')
            document.getElementById('name').value = (valid ? 'foo' : 'my name is foo')
            document.getElementById('email').value = (valid ? '[email protected]' : 'mail')
            document.getElementById('age').value = (valid ? '10' : '101')
            document.getElementById('birthDate').value = (valid ? '01/01/2000' : '01012000')
        }
    </script>
</head>
<body>
    <div class="container">
        <div class="row mt-3">
            <div class="col">
                <form method="post" th:action="@{/submit}" th:object="${user}">
                    <div class="mb-3 col-12">
                        <label class="form-label" for="id">ID:</label>
                        <input class="form-control form-control-sm" th:field="*{id}" />
                        <span class="text-danger" th:if="${#fields.hasErrors('id')}" th:errors="*{id}"></span>
                    </div>
                    <div class="mb-3 col-12">
                        <label class="form-label" for="name">Name:</label>
                        <input class="form-control form-control-sm" th:field="*{name}" />
                        <span class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
                    </div>
                    <div class="mb-3 col-12">
                        <label class="form-label" for="email">Email:</label>
                        <input class="form-control form-control-sm" th:field="*{email}" />
                        <span class="text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
                    </div>
                    <div class="mb-3 col-12">
                        <label class="form-label" for="age">Age:</label>
                        <input class="form-control form-control-sm" th:field="*{age}" />
                        <span class="text-danger" th:if="${#fields.hasErrors('age')}" th:errors="*{age}"></span>
                    </div>
                    <div class="mb-3 col-12">
                        <label class="form-label" for="birthDate">Birth Date:</label>
                        <input class="form-control form-control-sm" th:field="*{birthDate}" />
                        <span class="text-danger" th:if="${#fields.hasErrors('birthDate')}" th:text="${#strings.substring(#fields.errors('birthDate')[0], 0, 94)}"></span>
                    </div>
                    <div class="col-12">
                        <input type="button" class="btn btn-sm btn-danger" onclick="fill(0)" value="Fill invaid data" />
                        <input type="button" class="btn btn-sm btn-success" onclick="fill(1)" value="Fill vaid data" />
                        <button class="btn btn-sm btn-primary">Submit</button>
                    </div>
                    <div class="alert alert-success mt-3" th:if="${pass}">
                        Validation success!
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>
Enter fullscreen mode Exit fullscreen mode

In this HTML form, we use Thymeleaf attributes to dynamically render the form with data corresponding to the current user object.

Run project

mvn spring-boot:run
Enter fullscreen mode Exit fullscreen mode

Open the web browser and goto http://localhost:8080

You will find this test page.

test page

Testing

Click "Fill invalid data" and then click "Submit" to see the error messages displayed in the input form.

validation failed

Click "Fill valid data" and then "Submit" again. You should see the validation success message displayed in the input form.

validation success

Conclusion

This article has covered implementing validation from entities to views, helping you build reliable and user-friendly applications. Apply these practices to enhance both the robustness and usability of your Spring Boot projects.

Source code: https://github.com/stackpuz/Example-Validation-Spring-Boot-3

Create a CRUD Web App in Minutes: https://stackpuz.com

validation Article's
30 articles in total
Favicon
"yup" is the new extra virgin olive oil
Favicon
JavaScript Email Validation Regex: Ensuring Accuracy in User Inputs
Favicon
Simplifying JSON Validation with Ajv (Another JSON Validator)
Favicon
Dynamic string validation using go's text/template package
Favicon
Practical Email Validation Using JavaScript: Techniques for Web Developers
Favicon
Validation in Spring REST Framework (SRF)
Favicon
Terraform Validation Rules: Best Practices & Examples
Favicon
Zod for TypeScript Schema Validation: A Comprehensive Guide
Favicon
AI Image Validation Solutions: A Game-Changer for Quality Control
Favicon
Transform zod error into readable error response
Favicon
β›”Stop Excessive Validation, you are ruining my life hack!
Favicon
zod vs class-validator & class-transformer
Favicon
Animated Login Form with Validation Using HTML, CSS & JavaScript
Favicon
How to work with regular expressions
Favicon
User Form Validation in HTML CSS and JavaScript | JavaScript Form Validation
Favicon
Simplify Form Validation with FormGuardJS: A Lightweight and Flexible Solution
Favicon
moment.js Alternative - Luxon
Favicon
Validating REST requests in a NestJS application and displaying errors in Angular application forms
Favicon
Implement data validation in FastAPI
Favicon
The Definitive Guide to the Constraint Validation API
Favicon
Env-Core: An Easy Way to Validate Environment Variables in Node.js Projects
Favicon
File-Type Validation in Multer is NOT SAFEπŸ™ƒ
Favicon
Guaranteed GxP Compliance: Mastering Validation Testing Strategies
Favicon
Assuring Excellence: The Crucial Benefits of GxP Validation Testing
Favicon
7 Old-School Practices in HTML Should Be Avoided
Favicon
Implement data validation in Spring Boot
Favicon
Implement data validation in Express
Favicon
An easy way to validate DTO's using Symfony attributes
Favicon
Implement data validation in .NET
Favicon
Mastering Data Validation in NestJS: A Complete Guide with Class-Validator and Class-Transformer

Featured ones: