Spring Data REST Example

This tutorial covers a Spring Data REST Example with Spring Boot. Learn to use Spring Data REST to create a production-ready RESTFul API within minutes.

Overview

Spring Data REST is a Spring Web Framework that helps build Hyper Media Driven RESTFul Web Services with ease. Spring Data REST’s most significant advantage is that it avoids boilerplate components and code blocks. Moreover, Spring Boot helps initialize Spring Data REST components with zero configurations.

This tutorial will create a production-ready RESTFul Service in just a few steps. Let’s build a Spring Boot Data REST application from scratch.

For a detailed understanding of Spring Data REST and its components, we recommend reading Spring Data REST Guide.

Building Spring Data REST Application

Spring Data REST applications are based on the Entities and Repositories. We will build a simple Student Service that exposes standard RESTful APIs and Spring Data REST-based profile resources.

To do so, we will build a Spring Boot project and add Spring Data REST dependencies. We will use H2, an in-memory database, to persist our student entity. However, you can use any other database if you want.

Adding Dependencies

We need Spring Data REST and Spring Data JPA dependencies to build this REST application. Along with that, we will need H2 Database dependency. H2 is an in-memory database that Spring Boot can configure automatically. Thus, we do not need to provide any data source configurations.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>runtime</scope>
</dependency>Code language: HTML, XML (xml)

Building Initial Schema

Spring Boot helps create initial database schema and initial data using schema.sql and data.sql files, respectively. Every time the application starts, Spring Boot runs these scripts to ensure that the database objects are in the correct form.

For this tutorial, we will create a simple Student table (if it does not exist already). The Id column in the student table is auto-incremented. Let’s add a create table script into the schema.sql file.

DROP TABLE IF EXISTS student;

CREATE TABLE student
(
  id   INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(250) NOT NULL
);Code language: SQL (Structured Query Language) (sql)

Building Persistence Layer

Now, we will add a Student Entity and a Student Repository to our application. Spring Data REST doesn’t require any Controllers to create RESTFul Services. It detects the Repository interfaces and exports the associated Entity as a REST resource upon startup.

Student Entity
For the sake of simplicity, our Student entity has only two fields.

@Data
@Entity
public class Student {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;
}Code language: Java (java)

Note that we are using Lombok @Data annotation. That helps us avoid boilerplate codes like standard getters, setters, and constructors.

Student Repository
Let’s create a Repository interface for our Entity. We are extending our repository from JpaRepository. However, you can use a different interface as per your needs.

@RepositoryRestResource
public interface StudentRepository
    extends JpaRepository<Student, Long> {
}Code language: Java (java)

Validating REST Endpoints

So far, we have everything needed to run our Spring Data REST web application. Now, we will launch the application and access the root resource.

Access Root Resource

The root resource is located at ‘/’, and we can access it from any browser or command prompt.

$ curl -i -X GET 'http://localhost:8080/'
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/hal+json
Transfer-Encoding: chunked

{
  "_links" : {
    "students" : {
      "href" : "http://localhost:8080/students{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}Code language: plaintext (plaintext)

We can see that our student resource and a Spring Data REST Profile resource are now available.

Create New Resource

Let’s create a new Student resource using the POST method on the Student’s collection resource (/students).

$ curl -i -X POST \
  -H 'Content-Type: application/json' \
  -d '{ "name": "Bob" }' \
  'http://localhost:8080/students'
HTTP/1.1 201
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Location: http://localhost:8080/students/1
Content-Type: application/hal+json
Transfer-Encoding: chunked

{
  "name" : "Bob",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/students/1"
    },
    "student" : {
      "href" : "http://localhost:8080/students/1"
    }
  }
}Code language: plaintext (plaintext)

The output shows the Student with the name “Bob” is successfully created.

Updating a Resource

Let’s try executing an update command on the newly created resource. We will change the name of the Student whose Id is 1.

$ curl -i -X PUT \
  -H 'Content-Type: application/json' \
  -d '{ "name": "Mark" }' \
  'http://localhost:8080/students/1'

HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Location: http://localhost:8080/students/1
Content-Type: application/hal+json
Transfer-Encoding: chunked

{
  "name" : "Mark",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/students/1"
    },
    "student" : {
      "href" : "http://localhost:8080/students/1"
    }
  }
}Code language: plaintext (plaintext)

The output shows that the Students name is now updated as “Mark”.

Accessing Resource Profile

Spring Data REST automatically exposes profile resources for our entities. These profile resources serve as API documentation. They enlist all the fields of the entities as well as permitted operations on them.

$ curl -i -X GET 'http://localhost:8080/profile/students'
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/alps+json
Transfer-Encoding: chunked

{
  "alps" : {
    "version" : "1.0",
    "descriptor" : [ {
      "id" : "student-representation",
      "href" : "http://localhost:8080/profile/students",
      "descriptor" : [ {
        "name" : "name",
        "type" : "SEMANTIC"
      } ]
    }, {
      "id" : "create-students",
      "name" : "students",
      "type" : "UNSAFE",
      "descriptor" : [ ],
      "rt" : "#student-representation"
    }, {
      "id" : "get-students",
      "name" : "students",
      "type" : "SAFE",
      "descriptor" : [ {
        "name" : "page",
        "type" : "SEMANTIC",
        "doc" : {
          "format" : "TEXT",
          "value" : "The page to return."
        }
      }, {
        "name" : "size",
        "type" : "SEMANTIC",
        "doc" : {
          "format" : "TEXT",
          "value" : "The size of the page to return."
        }
      }, {
        "name" : "sort",
        "type" : "SEMANTIC",
        "doc" : {
          "format" : "TEXT",
          "value" : "The sorting criteria to use to calculate the content of the page."
        }
      } ],
      "rt" : "#student-representation"
    }, {
      "id" : "patch-student",
      "name" : "student",
      "type" : "UNSAFE",
      "descriptor" : [ ],
      "rt" : "#student-representation"
    }, {
      "id" : "update-student",
      "name" : "student",
      "type" : "IDEMPOTENT",
      "descriptor" : [ ],
      "rt" : "#student-representation"
    }, {
      "id" : "delete-student",
      "name" : "student",
      "type" : "IDEMPOTENT",
      "descriptor" : [ ],
      "rt" : "#student-representation"
    }, {
      "id" : "get-student",
      "name" : "student",
      "type" : "SAFE",
      "descriptor" : [ ],
      "rt" : "#student-representation"
    } ]
  }
}Code language: plaintext (plaintext)

Here we can see that the profile resource correctly returned the API documentation for the student endpoint. If you wish to learn more about the profile resources, please read Spring Data REST – Profile Resource.

Summary

This practical tutorial covered creating a Spring Data REST Service from scratch. We practically understood that Spring Data REST could refer to the repositories and exposes the resources in a production-ready RESTFul Web Service with zero configurations.

For the complete source of the examples used here, please visit our GitHub Repository.