Master java skills

Form validation with Springboot validators

Spring mvc validators are used to validate the form data. It ensures that correct data is sent and in proper format.

Create a ‘spring starter project’ in STS. Project structure should look like below

pom.xml

<?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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>form-validation-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>form-validation-app</name>
	<description>Demo project for Spring Boot</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</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-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.properties

spring.application.name=form-validation-app


# Thymeleaf configuration
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false

# Server configuration (optional)
server.port=8080

# Logging configuration (optional)
logging.level.org.springframework=INFO
logging.level.com.example=DEBUG

User.java

package com.sks.model;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;

public class User {
	
    @NotEmpty(message = "Name cannot be null")
    @Size(min = 4, max = 50, message = "Name should be between 4 and 50 characters")
    private String name;

    @NotEmpty(message = "Email is required")
    @Email(message = "Email should be valid")
    private String email;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
}

UserValidator.java

package com.sks.validator;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.sks.model.User;

@Component
public class UserValidator 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;

        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "NotEmpty.user.name");
        if (user.getName().length() < 4 || user.getName().length() > 50) {
            errors.rejectValue("name", "Size.user.name");
        }

        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "NotEmpty.user.email");
        if (!user.getEmail().contains("@")) {
            errors.rejectValue("email", "Email.user.email");
        }
    }
}

UserController.java

package com.sks.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.sks.model.User;
import com.sks.validator.UserValidator;

@Controller
public class UserController {
	
	@Autowired
    private UserValidator userValidator;

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

    @PostMapping("/register")
    public String submitForm(@ModelAttribute("user") User user, BindingResult bindingResult) {
        userValidator.validate(user, bindingResult);
        if (bindingResult.hasErrors()) {
            return "register";
        }
        return "success";
    }
}

messages.properties file. Create a file under src/main/resources folder with name messages.properties

NotEmpty.user.name=Name cannot be null
Size.user.name=Name should be between 4 and 50 characters
NotEmpty.user.email=Email is required
Email.user.email=Email should be valid

Create html files under the templates folder under src/main/resources package

register.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Register</title>
</head>
<body>
<h3>Welcome to Registration form</h3>
    <form th:action="@{/register}" th:object="${user}" method="post">
        <div>
            <label>Name:</label>
            <input type="text" th:field="*{name}"/>
            <div th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</div>
        </div><br>
        <div>
            <label>Email:</label>
            <input type="text" th:field="*{email}"/>
            <div th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</div>
        </div>
        <br>
        <div>
            <button type="submit">Register</button>
        </div>
    </form>
</body>
</html>

success.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Success</title>
</head>
<body>
    <h1>Registration Successful!</h1>
</body>
</html>

Run the application the test the below url

When click on Register without any values for name and email, error will be displayed