Open In App

Customizing Data Binding in Spring MVC

Last Updated : 16 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Data binding in Spring MVC is mapping HTTP request parameters to Java objects. It allows us to automatically populate model objects with form input data, simplifying development. Sometimes, the default binding behavior may not suffice, and customizing the data binding process becomes essential for handling complex mappings or validations. This article will guide you through customizing data binding in Spring MVC with examples and code snippets.

In Spring MVC, data binding occurs via the @ModelAttribute annotation, which maps form data to Java model objects. However, custom data conversion is often needed, such as converting a string to a date, formatting numbers, or managing complex relationships. Spring provides several tools for customization:

  • PropertyEditors: Convert string values into complex types like Date, BigDecimal, etc.
  • Custom Formatter: Spring Formatters allow for more advanced formatting.
  • @InitBinder: This annotation allows registering custom editors or formatters to handle complex types during binding.

Implementation to Customize Data Binding in Spring MVC

This example demonstrates how to customize data binding by creating a Spring MVC project that uses Thymeleaf for the frontend. The project includes a registration form with custom data binding for converting date inputs.

Step 1: Create a New Spring Boot Project

Create a new Spring Boot project using IntelliJ IDEA. Choose the following options:

  • Name: spring-mvc-data-binding-example
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

Project Metadata

Step 2: Add Dependencies

Add the following dependencies to your pom.xml file:

  • Spring Web
  • Lombok
  • Spring DevTools
  • Thymeleaf

Click on the Create button.

Add Dependencies

Project Structure

After project creation done, the folder structure will look like the below image:

Project Folder Structure

Step 3: Configure Application Properties

In the application.properties file, add the following configuration for the Spring MVC project:

spring.application.name=spring-mvc-data-binding-example
# Thymeleaf view configuration
spring.mvc.view.suffix=.html

The application name is set, and Spring MVC is configured to use Thymeleaf templates with the .html suffix for view rendering.

Step 4: Create the User Class

The User class defines the model for user registration.

Java
package com.gfg.springmvcdatabindingexample;

import java.util.Date;

public class User {
    // Field to hold user's name
    private String name;

    // Field to hold user's date of birth
    private Date dateOfBirth;

    // Getter and setter for name
    public String getName() {
        return name;
    }

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

    // Getter and setter for dateOfBirth
    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }
}

This class is a simple POJO that represents a User. It contains two fields: name (a String) and dateOfBirth (a Date).

Step 5: Create the Custom PropertyEditor

The CustomDateEditor is used to convert string inputs (from the form) into Date objects.

Java
package com.gfg.springmvcdatabindingexample;

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class CustomDateEditor extends PropertyEditorSupport {
    // Define the date format for parsing date strings
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        try {
            // Convert text to Date
            setValue(dateFormat.parse(text));
        } catch (ParseException e) {
            // In case of parse exception, set null as the value
            setValue(null);
        }
    }
}

This CustomDateEditor class is a PropertyEditor that converts a string in the format yyyy-MM-dd into a Date object. If the parsing fails, it sets the value to null.

Step 6: Create the UserController Class

The UserController handles the registration form and user submission.

Java
package com.gfg.springmvcdatabindingexample;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

@Controller
public class UserController {

    // Register custom editor for Date class
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor());
    }

    // Show registration form
    @RequestMapping("/register")
    public String showForm(Model model) {
        model.addAttribute("user", new User()); // Initialize user object for the form
        return "register"; // Return the Thymeleaf template 'register.html'
    }

    // Handle form submission
    @PostMapping("/register")
    public String submitForm(@ModelAttribute("user") User user, Model model) {
        model.addAttribute("user", user); // Bind the submitted user data
        return "result"; // Return the Thymeleaf template 'result.html'
    }
}

The UserController defines two endpoints:

  • /register: Displays the registration form.
  • /register (POST): Handles form submissions and binds the user input to the User model.

The @InitBinder method registers the CustomDateEditor to handle date conversions.

Step 7: Main Class

No changes are required in the main class. This class simply runs the Spring Boot application.

Java
package com.gfg.springmvcdatabindingexample;

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

@SpringBootApplication
public class SpringMvcDataBindingExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringMvcDataBindingExampleApplication.class, args);
    }
}

Step 8: Create the Register HTML Form

Create a register.html form to collect user data.

HTML
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Register</title>
    <style>
        /* Styling for the form */
        body { font-family: Arial, sans-serif; background-color: #f4f9f4; }
        .container { max-width: 600px; margin: 50px auto; padding: 20px; background-color: #fff; }
        h1 { color: #4caf50; text-align: center; }
        label { display: block; margin-bottom: 8px; }
        input[type="text"], input[type="submit"] { width: 100%; padding: 10px; margin-bottom: 20px; }
    </style>
</head>
<body>
<div class="container">
    <h1>User Registration</h1>
    <form th:action="@{/register}" th:object="${user}" method="post">
        <!-- Name input field -->
        <label for="name">Name:</label>
        <input type="text" th:field="*{name}" id="name" placeholder="Enter your name" />

        <!-- Date of birth input field -->
        <label for="dateOfBirth">Date of Birth (yyyy-MM-dd):</label>
        <input type="text" th:field="*{dateOfBirth}" id="dateOfBirth" placeholder="Enter your birth date" />

        <!-- Submit button -->
        <input type="submit" value="Submit" />
    </form>
</div>
</body>
</html>

The HTML form collects the user's name and date of birth. It uses Thymeleaf expressions (th:object, th:field) to bind the form fields to the User object.

Step 9: Create the Result Page

Create a result.html page to display the submitted data.

HTML
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Registration Result</title>
</head>
<body>
    <h1>Registration Success</h1>
    <p th:text="'Name: ' + ${user.name}"></p>
    <p th:text="'Date of Birth: ' + ${user.dateOfBirth}"></p>
</body>
</html>

The result.html page displays the submitted user data (name and date of birth).

pom.xml File:

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.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gfg</groupId>
    <artifactId>spring-mvc-data-binding-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-mvc-data-binding-example</name>
    <description>spring-mvc-data-binding-example</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

The pom.xml file defines the project dependencies and the build configuration. Spring Web is used for building the web application, Thymeleaf is used for rendering views, and Lombok reduces boilerplate code.

Step 10: Run the Application

After all the steps, now run the project, and it will start at port 8080.

Application Starts

Step 11: Test the Application

Now, open the below URL into the browser. It will show the following page.

http://localhost:8080/register

Output:

Browser Output


After entering the data, it will show this in result page.

Registration Result

Conclusion

In this article, we learned how to customize data binding in Spring MVC. By using the @InitBinder annotation and creating a CustomDateEditor, we can easily convert and bind form inputs to complex types such as Date. This flexibility in Spring MVC makes it suitable for a wide range of web applications.


Next Article
Article Tags :

Similar Reads