Spring Boot H2 REST tutorial

In this tutorial, we are going to create a simple Spring Boot RESTful application with H2 database.

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.

Apache Tomcat is an open source Java Servlet Container developed by the Apache Software Foundation (ASF). Tomcat implements several Java EE specifications including Java Servlet, JavaServer Pages (JSP), Java EL, and WebSocket. Tomcat can be run in standalone and embedded mode.

H2 is an open source relational database management system created entirely in Java. It can be embedded in Java applications or run in the client-server mode. It is easy to deploy and install and has small footprint.

JdbcTemplate is a Spring library that helps programmers create applications that work with relational databases and JDBC. It takes care of many tedious and error-prone low-level details such as handling transactions, cleaning up resources, and correctly handling exceptions. JdbcTemplate is shipped in Spring's spring-jdbc module.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. Humans can easily read and write and machines parse and generate JSON. The official Internet media type for JSON is application/json. The JSON filename extension is .json.

A RESTFul application follows the REST architectural style, which is used for designing networked applications. RESTful applications generate HTTP requests which perform CRUD (Create/Read/Update/Delete) operations on resources.

Application

Our application is a Spring Boot RESTful application that runs on embedded Tomcat server. It returns data from H2 database in JSON format. The application uses JdbcTemplate to simplify JDBC programming.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── Application.java
    │   │           ├── bean
    │   │           │   └── City.java
    │   │           ├── controller
    │   │           │   └── MyController.java
    │   │           └── service
    │   │               ├── CityService.java
    │   │               └── ICityService.java
    │   └── resources
    │       ├── application.yml
    │       ├── data-h2.sql
    │       └── schema-h2.sql
    └── test
        └── java         

This is the project structure.

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>SpringBootRestH2</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>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>     
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>                                              
                
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>         

    </dependencies>       
    
</project>

This is the Maven build file. The h2 dependency is a driver for H2 database. The spring-boot-devtools enables hot swapping, disables template cache and enables live reloading. The spring-boot-starter-web is starter for building web, including RESTful, applications using Spring MVC. The spring-boot-starter-jdbc is a starter for using JDBC in Spring Boot.

application.yml
server:
    port: 8086
    context-path: /rest

spring: 
    main:
        banner-mode: "off"       
    datasource:
        platform: h2
        driverClassName: org.h2.Driver
        url: jdbc:h2:mem:test;MODE=PostgreSQL
      
logging: 
    level: 
        org: 
            springframework: ERROR

The application.yml file contains various configuration settings of a Spring Boot application. We have mappings for server port and context path (application name). With the banner-mode property we turn off the Spring banner. The platform value is used in SQL initialization scripts: schema-${platform}.sql and data-${platform}.sql. We set H2 to use PostgreSQL compatibility mode. The H2 database is run in memory. Also, we set the logging level for spring framework to ERROR. The file is located in the in the src/main/resources directory.

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.

schema-h2.sql
CREATE TABLE CITIES(ID BIGINT PRIMARY KEY AUTO_INCREMENT, 
                  NAME VARCHAR(30), POPULATION BIGINT);

This SQL script creates the CITIES table.

data-h2.sql
INSERT INTO CITIES(NAME, POPULATION) VALUES('Bratislava', 432000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('Budapest', 1759000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('Prague', 1280000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('Warsaw', 1748000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('Los Angeles', 3971000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('New York', 8550000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('Edinburgh', 464000);
INSERT INTO CITIES(NAME, POPULATION) VALUES('Berlin', 3671000);

This script fills the table with data. Both scripts are located in the root of the classpath.

ICityService.java
package com.zetcode.service;

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

public interface ICityService {

    public List<City> findAll();
    public City findById(Long id);
}

ICityService provides contract methods to get all cities and get a city by its id from the data source.

CityService.java
package com.zetcode.service;

import com.zetcode.bean.City;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class CityService implements ICityService {

    @Autowired
    private JdbcTemplate jtm;

    @Override
    public List<City> findAll() {

        String sql = "SELECT * FROM CITIES";

        List<City> cities = jtm.query(sql, new BeanPropertyRowMapper(City.class));

        return cities;
    }

    @Override
    public City findById(Long id) {

        String sql = "SELECT * FROM CITIES WHERE ID=?";

        City city = (City) jtm.queryForObject(sql, new Object[]{id},
                new BeanPropertyRowMapper(City.class));

        return city;
    }
}

CityService contains the implementation of the findAll() and findById() methods. We use Spring JdbcTemplate to execute SQL code.

@Autowired
private JdbcTemplate jtm;

JdbcTemplate is injected.

String sql = "SELECT * FROM CITIES";

This is SQL to select all cities from the CITIES table.

List<City> cities = jtm.query(sql, new BeanPropertyRowMapper(City.class));

BeanPropertyRowMapper converts a row into a new instance of the specified mapped target class.

String sql = "SELECT * FROM CITIES WHERE ID=?";

This is SQL to select a specific city identified by id from the CITIES table.

City city = (City) jtm.queryForObject(sql, new Object[]{id},
        new BeanPropertyRowMapper(City.class));

To get one row from the CITIES table, we use the queryForObject() method.

MyController.java
package com.zetcode.controller;

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

@RestController
public class MyController {

    @Autowired
    private ICityService cityService;

    @RequestMapping("/cities")
    public List<City> findCities() {
        
        return cityService.findAll();
    }

    @RequestMapping("/cities/{userId}")
    public City findCity(@PathVariable Long userId) {
        
        return cityService.findById(userId);
    }
}

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 ICityService cityService;

We inject a ICityService into the countryService field.

@RequestMapping("/cities")
public List<City> findCities() {
    
    return cityService.findAll();
}

The @RequestMapping annotation is used to map web requests to Spring controller methods. Here we map a request with the /cities path to the controller's findCities() method. The default request is a GET request.

We do not need to convert the City domain object to JSON manually. Because Jackson 2 is on the classpath, (included via spring-boot-starter-web, Spring chooses MappingJackson2HttpMessageConverter automatically to convert the City instance to JSON.

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. The @SpringBootApplication enables auto-configuration and component scanning.

$ 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/cities
[{"id":1,"name":"Bratislava","population":432000},{"id":2,"name":"Budapest","population":1759000},
{"id":3,"name":"Prague","population":1280000},{"id":4,"name":"Warsaw","population":1748000},
{"id":5,"name":"Los Angeles","population":3971000},{"id":6,"name":"New York","population":8550000},
{"id":7,"name":"Edinburgh","population":464000},{"id":8,"name":"Berlin","population":3671000}]

With the curl command, we get all cities.

$ curl localhost:8086/rest/cities/1
{"id":1,"name":"Bratislava","population":432000}

Here we get one city identified by its id.

In this tutorial, we have created a Spring Boot RESTful application, which returns data from H2 database in JSON format. You might also be interested in the related tutorials: Spring Boot Thymeleaf tutorial, Spring Boot Mustache tutorial, Spring Boot Swing integration tutorial, Introduction to Spring web applications, Spring Boot RESTFul application, JdbcTemplate in a classic Spring application.