Custom Type Converter in Spring MVC

In this post of Spring MVC, we will look creating a custom type converter in Spring MVC. By default, Spring only knows how to convert simple types. This means if we pass simple type in our request, Spring MVC type converter will automatically bind them to correct Java types.

 

Introduction

In the real world application, we may come across use cases when we need to bind complex object as part of the request data. In this post, we will create a custom type converter in Spring MVC that can convert the request parameter into Java 8 LocalDate and LocalDateTime objects.

 

1. Creating a Custom Type Converter in Spring MVC

To create a custom type converter, we need to implement the Converter<S,T> interface.While implementing this interface we need to pass following 2 parameters to the method.

  • S – The source object type.
  • T –  The Target object type 

In this post, we will create two custom converter for LocaleDate and LocaleDateTime. We will use Spring Boot for this post as it provides an automatic registration of Converter beans but the core logic will remain same if you are working on a simple Spring MVC application.

 

2. Maven Setup

We will create a simple Spring Boot based web application. You can create the application either through the IDE or can use Spring Initializr. This is how our pom.xml look like:

<?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 http://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>2.2.0.M4</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>
    <groupId>com.javadevjournal</groupId>
    <artifactId>custom-type-converter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>custom-type-converter</name>
    <description>How to create custom type converter in Soring MVC</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

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

 

3. Creating Custom LocalDateConverter

To create the custom converter, we will create a custom class LocalDateConverter and implement the Convert  method in the Converter interface.

package com.javadevjournal.converter;

import org.springframework.core.convert.converter.Converter;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Component
public class LocalDateConverter implements Converter<String, LocalDate> {

    /**
     * Override the convert method
     * @param date
     * @return
     */
    @Override
    public LocalDate convert(String date) {
        return LocalDate.parse(date, DateTimeFormatter.BASIC_ISO_DATE);
    }
}

You may have to add null check if working with Spring version 4.0 or the older one. We have annotated our class with @Component annotation.Spring Boot will automatically register this converter. We don’t need any additional configurations to register the custom converter.

 

4. Testing Custom Converter

To test our custom converter, let’s create a simple REST controller to get order information based on the date. This is how our REST Controller look like:

package com.javadevjournal.controller;

import com.javadevjournal.data.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

@RestController
@RequestMapping("/orders")
public class OrderController {

    private static final Logger LOG = LoggerFactory.getLogger(OrderController.class);

    @GetMapping("/order/{date}")
    public Order getOrderByDate(@PathVariable("date") LocalDate date) {

        LOG.info("Sending order for the request date {} ", date);
        return new Order(300.40, "1234", date);
    }
}

Let’s build and deploy our application to see things in action:

Custom Type Converters With Spring MVC

We are passing date in BASIC_ISO_DATE format since we are using this formatter to parse the request data.If we change the format of the request, we will get an error back from the API.

Type Converters

 

5. Configuration Spring MVC Application

If you are not using Spring Boot, you may not use the auto-registration feature of the Spring Boot. We need to register the custom type converter in Spring MVC application. This is how we can register our custom converter:

@Configuration
public class WebConfig implements WebMvcConfigurer {
 
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new LocalDateConverter());
    }
}

 

Summary

In this post, we saw how to create a custom type converter in Spring MVC. We look at creating custom converter in both Spring MVC as well Spring Boot based application. As always, the source code for this post is available on the GitHub.

Leave a Reply

avatar

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of