Spring Boot @ResponseBody
last modified July 16, 2023
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.
build.gradle
...
src
├── main
│ ├── java
│ │ └── com
│ │ └── zetcode
│ │ ├── Application.java
│ │ ├── controller
│ │ │ └── MyController.java
│ │ ├── model
│ │ │ └── City.java
│ │ └── service
│ │ ├── CityService.java
│ │ └── ICityService.java
│ └── resources
│ └── templates
│ └── index.ftlh
└── test
├── java
└── resources
This is the project structure of the application.
plugins {
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
}
group = 'com.zetcode'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
implementation 'org.webjars:webjars-locator:0.45'
implementation 'org.webjars:jquery:3.6.0'
}
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.
package com.zetcode.model;
import java.util.Objects;
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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
City city = (City) o;
return population == city.population &&
Objects.equals(id, city.id) &&
Objects.equals(name, city.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, population);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("City{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append(", population=").append(population);
sb.append('}');
return sb.toString();
}
}
This is the City bean. It has id, name,
and population attributes.
package com.zetcode.service;
import com.zetcode.model.City;
import java.util.List;
public interface ICityService {
List<City> findAll();
}
ICityService contains the contract method to get all cities.
package com.zetcode.service;
import com.zetcode.model.City;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class CityService implements ICityService {
@Override
public List<City> findAll() {
var cities = new ArrayList<City>();
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;
}
}
CityService returns eight city objects.
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() {
var 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.ftlh 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() {
var 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.)
<!DOCTYPE html>
<html>
<head>
<title>Home Page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script 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 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.
package com.zetcode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The Application sets up the Spring Boot application.
In this article we have used the @ResponseBody annotation in a
Spring Boot web application.