Spring MVC - Creating a new Custom Formatter Annotation

[Updated: Nov 19, 2016, Created: Feb 27, 2016]

Spring 3 formatter API provides a facility to bind an Annotation to a org.springframework.format.Formatter implementation. When creating a custom Formatter, we can define a corresponding annotation and bind that annotation to our formatter.

In this example we are going to define our own formatter annotation.

To bind an Annotation to a formatter, we have to implement AnnotationFormatterFactory

package org.springframework.format;
public interface AnnotationFormatterFactory<A extends Annotation> {

    Set<Class<?>> getFieldTypes();

    Printer<?> getPrinter(A annotation, Class<?> fieldType);

    Parser<?> getParser(A annotation, Class<?> fieldType);

In our last example we created a new formatter AddressFormatter by extending Formatter interface. Here we are going to bind the same formatter to a new annotation @AddressFormat. Doing so will enable us to declare formatting on field level.

Creating Backing object classes

public class Customer {
    private Long id;
    private String name;
    private Address address;

   //getters and setters

public class Address {
    private String street;
    private String city;
    private String county;
    private String zipCode;

    //getters and setters

Creating our Formatter

import org.springframework.format.Formatter;
import java.text.ParseException;
import java.util.Locale;

public class AddressFormatter implements Formatter<Address> {
    private Style style = Style.FULL;

    public void setStyle (Style style) {
        this.style = style;

    public Address parse (String text, Locale locale) throws ParseException {
        return address;

    public String print (Address a, Locale l) {
        return addressString;

    public enum Style {

Creating Annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface AddressFormat {

    AddressFormatter.Style style () default AddressFormatter.Style.FULL;

Using annotation in our backing object class

package com.logicbig.example;

public class Customer {
    private Long id;
    private String name;
    @AddressFormat(style = AddressFormatter.Style.FULL)
    private Address address;

    //getters and setters

Binding our Annotation by implementing AnnotationFormatterFactory

import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.Parser;
import org.springframework.format.Printer;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class AddressFormatAnnotationFormatterFactory implements
                    AnnotationFormatterFactory<AddressFormat> {
    public Set<Class<?>> getFieldTypes () {
        return new HashSet<>(Arrays.asList(Address.class));

    public Printer<?> getPrinter (AddressFormat annotation, Class<?> fieldType) {
        return getAddressFormatter(annotation, fieldType);

    public Parser<?> getParser (AddressFormat annotation, Class<?> fieldType) {
        return getAddressFormatter(annotation, fieldType);

    private AddressFormatter getAddressFormatter (AddressFormat annotation,
                                                               Class<?> fieldType) {
        AddressFormatter formatter = new AddressFormatter();
        return formatter;

Registering The AnnotationFormatterFactory

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

public class MyWebConfig extends WebMvcConfigurerAdapter {
    public void addFormatters (FormatterRegistry registry) {

        AddressFormatAnnotationFormatterFactory factory = new


Creating Controller

public class CustomerController {
    private CustomerDataService customerDataService;

    @RequestMapping(method = RequestMethod.GET)
    private String handleRequest (Model model) {
        model.addAttribute("customerList", customerDataService.getAllUsers());
        return "customers";


<%@ page language="java"
    contentType="text/html; charset=ISO-8859-1"
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<h3>Customer List </h3>
<table style="width:100%">
<c:forEach var="customer" items="${customerList}" varStatus="status">
    <spring:eval expression="customer.id" />
    <spring:eval expression="customer.name" />
   <spring:eval expression="customer.address" />

Example Project

Run the web application by using embedded tomcat:

mvn  clean install tomcat7:run-war

Dependencies and Technologies Used :

  • Spring Web MVC 4.2.4.RELEASE: Spring Web MVC.
  • Spring TestContext Framework 4.2.4.RELEASE: Spring TestContext Framework.
  • Java Servlet API 3.0.1
  • javax.servlet:jstl 1.2
  • JUnit 4.12: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
  • DataFactory 0.8: Library to generate data for testing.
  • JDK 1.8
  • Maven 3.0.4

Spring Custom Formatter Annotation Select All Download
  • spring-custom-formatter-annotation
    • src
      • main
        • java
          • com
            • logicbig
              • example
        • webapp
          • WEB-INF
            • views
      • test
        • java
          • com
            • logicbig
              • example

See Also