Spring Boot @ResponseBody shows how to bind controller return values to response body.
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.
@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.
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.
build.gradle
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.
com/zetcode/model/City.java
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.
com/zetcode/service/ICityService.java
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.
com/zetcode/service/CityService.java
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.
com/zetcode/controller/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() {
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.)
resources/templates/index.ftlh
<!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.
com/zetcode/Application.java
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.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.