Spring Boot RESTFul application
last modified July 13, 2020
In this tutorial, we are going to create a simple Spring Boot RESTful application. Our application will be deployed on an embedded Tomcat server.
We show how to return data in JSON and XML formats from our web service.
Spring Boot
Spring is a popular Java application framework for creating enterprise applications. Spring Boot is a way to create stand-alone, production-grade Spring based applications with minimal effort.
RESTFul application
A RESTFul application creates a system (API) that follows the REST architectural style, which is used for designing networked applications. RESTful applications use HTTP requests perform CRUD (Create/Read/Update/Delete) operations on resources.
Spring Boot RESTFul simple example
The following code example creates a web service that reads data from a CSV file and returns it in JSON format to the client.
$ tree . ├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── Application.java │ │ ├── bean │ │ │ └── Country.java │ │ ├── controller │ │ │ └── MyController.java │ │ └── service │ │ ├── CountryService.java │ │ └── ICountryService.java │ └── resources │ ├── application.yml │ └── countries.csv └── test └── java
This is the project structure.
<?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>SpringBootRest</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>SpringBootRest</name> <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-web</artifactId> </dependency> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>3.8</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
This is the Maven build file. The opencsv
is used for working with CSV
data. The spring-boot-starter-web
is a starter for
building web and RESTful applications. The application is packaged
into an executable JAR file. The executable JAR is created with the
spring-boot-maven-plugin
.
server: port: 8086 contextPath: /rest
The application.yml
file contains various configuration settings of a Spring Boot
application. We have mappings for server port and context path (application name). The
file is located in the in the src/main/resources
directory.
Country, Population Slovakia,5429000 Norway,5271000 Croatia,4225000 Russia,143439000 Mexico,122273000 Vietnam,95261000 Sweden,9967000 Iceland,337600 Israel,8622000 Hungary,9830000 Germany,82175700 Japan,126650000
The countries.csv
, located in the src/main/resources
directory,
contains the data that is used in our application.
package com.zetcode.bean; public class Country { private String name; private int population; public Country() { } public Country(String name, int population) { this.name = name; this.population = population; } 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; } }
The fields from the countries.csv
file are mapped to the
Country
class.
package com.zetcode.service; import com.zetcode.bean.Country; import java.util.ArrayList; public interface ICountryService { public ArrayList<Country> findAll(); }
This is the ICountryService
interface. It contains one method
called findAll
.
package com.zetcode.service; import com.opencsv.CSVReader; import com.zetcode.bean.Country; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import org.springframework.stereotype.Service; @Service public class CountryService implements ICountryService { private final ArrayList<Country> countries; public CountryService() { countries = new ArrayList(); } @Override public ArrayList<Country> findAll() { FileInputStream fis = null; try { String fileName = "src/main/resources/countries.csv"; fis = new FileInputStream(new File(fileName)); CSVReader reader = new CSVReader(new InputStreamReader(fis)); String[] nextLine; reader.readNext(); while ((nextLine = reader.readNext()) != null) { Country newCountry = new Country(nextLine[0], Integer.valueOf(nextLine[1])); countries.add(newCountry); } } catch (FileNotFoundException ex) { Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE, null, ex); } finally { try { if (fis != null) { fis.close(); } } catch (IOException ex) { Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE, null, ex); } } return countries; } }
This is the implementation of the ICountryService
contract.
It contains the findAll
method that reads data from
the countries.csv
file and returns a list of Country
objects.
package com.zetcode.controller; import com.zetcode.bean.Country; import com.zetcode.service.ICountryService; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @Autowired private ICountryService countryService; @RequestMapping("/countries") public List<Country> listCountries() { return countryService.findAll(); } }
This is the controller class for the Spring Boot RESTful application. The @RestController
annotation
creates a RESTful controller. While the traditional
MVC controller uses ModelAndView
, the RESTful controller
simply returns the object and the object data is written directly to the HTTP response
in JSON or XML format.
@Autowired private ICountryService countryService;
We inject a CountryService
into the countryService
variable.
@RequestMapping("/countries") public List<Country> listCountries() { return countryService.findAll(); }
The @RequestMapping
annotation is used to map web requests to Spring
controller methods. Here we map a request with the /countries
path
to the controller's listCountries
method. The default request is
a GET request.
We do not need to convert the Country
domain object to JSON manually.
Because Jackson 2 is on the classpath, Spring chooses MappingJackson2HttpMessageConverter
automatically to convert the Country
instance to JSON.
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.
The @SpringBootApplication
enables auto-configuration
and component scanning.
$ mvn package
With mvn package
command, we build the application.
$ mvn spring-boot:run
With mvn spring-boot:run
command, we run the application.
The application is deployed on embedded Tomcat server.
$ curl localhost:8086/rest/countries [{"name":"Slovakia","population":5429000},{"name":"Norway","population":5271000}, {"name":"Croatia","population":4225000},{"name":"Russia","population":143439000}, {"name":"Mexico","population":122273000},{"name":"Vietnam","population":95261000}, {"name":"Sweden","population":9967000},{"name":"Iceland","population":337600}, {"name":"Israel","population":8622000},{"name":"Hungary","population":9830000}, {"name":"Germany","population":82175700},{"name":"Japan","population":126650000}]
With the curl
command, we test the application.
Returning XML data
To return XML data instead of JSON, we need to add a dependency and modify the controller.
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
We add the jackson-dataformat-xml
to the dependencies.
package com.zetcode.controller; import com.zetcode.bean.Country; import com.zetcode.service.ICountryService; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { @Autowired private ICountryService countryService; @RequestMapping(value="/countries", method=RequestMethod.GET, produces=MediaType.APPLICATION_XML_VALUE) public List<Country> listCountries() { return countryService.findAll(); } }
We choose the MediaType.APPLICATION_XML_VALUE
type to tell
the controller to return XML data.
In this tutorial, we have created a Spring Boot RESTful application returning data in JSON and XML.