Spring Boot @ResponseBody tutorial

In Spring Boot @ResponseBody tutorial, we are going to use the Spring @ResponseBody annotation in a controller to write data to the body of the response object.

Spring is a popular Java application framework and Spring Boot is an evolution of Spring which helps create stand-alone, production-grade Spring based applications easily.

WebJars are client-side web libraries (such as jQuery or Bootstrap) packaged into JAR files. They allow easy management of client-side dependencies in Java web applications

JQuery is a popular open source JavaScript library designed to simplify the client-side scripting of HTML.

Spring @ResponseBody

@ResponseBody is a Spring annotation which binds a method return value to the web response body. It is not interpreted as a view name. It uses HTTP Message converters to convert the return value to HTTP response body, based on the content-type in the request HTTP header.

Spring @ResponseBody example

The following example creates a Spring Boot web application which returns JSON data to the client. The home page is handled with the MVC mechanism; FreeMarker is used to create the template for the home page. The home page contains a button which sends a request to get JSON data. The Spring Boot web application sends data in JSON format with the help of the @ResponseBody annotation.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── Application.java
    │   │           ├── bean
    │   │           │   └── City.java
    │   │           ├── controller
    │   │           │   └── MyController.java
    │   │           └── service
    │   │               ├── CityService.java
    │   │               └── ICityService.java
    │   └── resources
    │       └── templates
    │           └── index.ftl
    └── test
        └── java

This is the project structure of the Spring Boot application.

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 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zetcode</groupId>
    <artifactId>SpringBootResponseBody</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>    
    
    <dependencies>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>  
        
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.2.0</version>
        </dependency>
        
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator</artifactId>
        </dependency>           
        
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>            
        </plugins>
    </build>         
    
</project>

The spring-boot-starter-freemarker is a starter for building Spring MVC web applications using FreeMarker views. We use a webjar for JQuery. The webjars-locator automatically resolves the version of any WebJars assets. The application is packaged into a JAR file and uses Tomcat as an embedded web server.

City.java
package com.zetcode.bean;

public class City {
    
    private Long id;

    private String name;
    private int population;

    public City() {
    }

    public City(Long id, String name, int population) {
        this.id = id;
        this.name = name;
        this.population = population;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    @Override
    public String toString() {
        return "City{" + "id=" + id + ", name=" + name
                + ", population=" + population + '}';
    }
}

This is the City bean.

ICityService.java
package com.zetcode.service;

import com.zetcode.bean.City;
import java.util.List;

public interface ICityService {

    public List<City> findAll();
}

The ICityService contains the contract method to get all cities.

CityService.java
package com.zetcode.service;

import com.zetcode.bean.City;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;

@Service
public class CityService implements ICityService {

    @Override
    public List<City> findAll() {

        List<City> cities = new ArrayList<>();
        
        cities.add(new City(1L, "Bratislava", 432000));
        cities.add(new City(2L, "Budapest", 1759000));
        cities.add(new City(3L, "Prague", 1280000));
        cities.add(new City(4L, "Warsaw", 1748000));
        cities.add(new City(5L, "Los Angeles", 3971000));
        cities.add(new City(6L, "New York", 8550000));
        cities.add(new City(7L, "Edinburgh", 464000));
        cities.add(new City(8L, "Berlin", 3671000));
        
        return cities;
    }
}

The CityService returns eight city objects.

MyController.java
package com.zetcode.controller;

import com.zetcode.bean.City;
import com.zetcode.service.ICityService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyController {

    @Autowired
    ICityService cityService;
    
    @RequestMapping(path = "/")
    public String index() {

        return "index";
    }    

    @RequestMapping(path = "/GetCities", produces = "application/json; charset=UTF-8")
    @ResponseBody
    public List<City> findCities() {

        List<City> cities = (List<City>) cityService.findAll();
        
        return cities;
    }
}

The controller has two methods. The index() method returns a view for the home page. The findCities() method returns a list of cities as JSON data.

@Controller
public class MyController {

The @Controller annotation indicates that we have a controller class.

@RequestMapping(path = "/")
public String index() {

    return "index";
}    

The index() method returns the index string, which is resolved to index.ftl view. The view is located in the src/main/resources/templates directory. When Spring locates spring-boot-starter-freemarker artifact in the POM file, it automatically configures FreeMarker.

@RequestMapping(path = "/GetCities", produces = "application/json; charset=UTF-8")
@ResponseBody
public List<City> findCities() {

    List<City> cities = (List<City>) cityService.findAll();
    
    return cities;
}

For the GetCities path, the findCities() method is called. The produces parameter indicates that the method returns JSON data; Spring RequestResponseBodyMethodProcessor handles return values from methods annotated with @ResponseBody by writing to the body of the response with an HttpMessageConverter. The message converter in our case is MappingJackson2HttpMessageConverter, which reads and writes JSON using Jackson's ObjectMapper. (Jackson is a popular Java JSON library.)

index.ftl
<!DOCTYPE html>
<html>
    <head>
        <title>Home Page</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script type="text/javascript" src="webjars/jquery/jquery.min.js"></script>
    </head>
<body>

    <button id="mybtn">Get cities</button>

    <div>
        <ul id="output">

        </ul>
    </div>

    <script>
        $('#mybtn').click(function () {

            $.getJSON('GetCities', function (data) {

                $("ul#output > li").remove();

                $.each(data, function (key, value) {
                    $("#output").append('<li>' + value['name'] + " " + value['population'] + '</li>');
                });
            });
        });
    </script>
</body>
</html>

The index.ftl file is the template for the home page. It cointains a button which executes an asynchronous request to the web application. It loads a list of cities and writes them to the HTML list.

<script type="text/javascript" src="webjars/jquery/jquery.min.js"></script>

We include the JQuery library. Thanks to webjars-locator, we can include a version agnostic JQuery library. So we do not have to update the link if the version of JQuery changes.

<script>
    $('#mybtn').click(function () {

        $.getJSON('GetCities', function (data) {

            $("ul#output > li").remove();

            $.each(data, function (key, value) {
                $("#output").append('<li>' + value['name'] + " " + value['population'] + '</li>');
            });
        });
    });
</script>

With $.getJSON() method, we load data in JSON format using a HTTP GET request. The data is traversed with $.each() and written to the HTML list.

In this tutorial, we have used the @ResponseBody annotation in a Spring Boot web application. You might also be interested in the related tutorials: Spring Boot @PathVariable tutorial, Spring Boot @RequestParam tutorial, Spring Boot REST H2 tutorial, Standalone Spring applications, Java tutorial.