HelloKoding

Practical coding guides

Spring Boot REST API Web Service Example

In this tutorial, you will learn to build a simple REST API web service example in Spring Boot by using Spring Web MVC with JPA, Hibernate and HSQL

What you’ll need

  • Your favorite IDE
  • JDK 8+ or OpenJDK 8+
  • Maven 3+

Init project structure

You can create and init a new Spring Boot project by using Spring CLI or Spring Initializr. Learn more about using these tools at here

The final project structure as below

├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── hellokoding
│       │           └── springboot
│       │               └── restful
│       │                   ├── product
│       │                   │   ├── Product.java
│       │                   │   ├── ProductAPI.java
│       │                   │   ├── ProductRepository.java
│       │                   │   └── ProductService.java
│       │                   └── Application.java
│       └── resources
│           └── application.properties
└── pom.xml

Project dependencies

Add Spring Web MVC into your project as a dependency on pom.xml or build.gradle file. In Spring Boot project, you can add the dependency spring-boot-starter-web. The library versions can be omitted as it is resolved by the parent pom provided by Spring Boot

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

We also need Spring Data JPA and HSQL Java Client dependencies for working with the HSQL database

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
</dependency>

You can find the full pom.xml file as below

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.hellokoding.springboot</groupId>
    <artifactId>springboot-restfulapi</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <org.apache.maven.plugins.version>3.6.0</org.apache.maven.plugins.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Define JPA Entity and Repository

Product.java

package com.hellokoding.springboot.restful.product;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.math.BigDecimal;

@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String description;

    private BigDecimal price;

    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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}

ProductRepository.java

package com.hellokoding.springboot.restful.product;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {
}

ProductRepository extends Spring Data JPA’s JpaRepository to provide the common CRUD functions such as findAll, findById, saveAll, save, deleteById to the underlying database

Define Service and REST APIs

ProductService.java

package com.hellokoding.springboot.restful.product;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class ProductService {
    private final ProductRepository productRespository;

    @Autowired
    public ProductService(ProductRepository productRespository) {
        this.productRespository = productRespository;
    }

    public List<Product> findAll() {
        return productRespository.findAll();
    }

    public Optional<Product> findById(Long id) {
        return productRespository.findById(id);
    }

    public Product save(Product stock) {
        return productRespository.save(stock);
    }

    public void deleteById(Long id) {
        productRespository.deleteById(id);
    }
}

ProductAPI.java

package com.hellokoding.springboot.restful.product;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;


@RestController
@RequestMapping("/api/v1/products")
public class ProductAPI {
    private final ProductService productService;

    @Autowired
    public ProductAPI(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public ResponseEntity<List<Product>> findAll() {
        return ResponseEntity.ok(productService.findAll());
    }

    @GetMapping("/{id}")
    public ResponseEntity<Product> findById(@PathVariable Long id) {
        Optional<Product> product = productService.findById(id);

        return ResponseEntity.ok(productService.findById(id).get());
    }

    @PostMapping
    public ResponseEntity<Product> create(Product product) {
        return ResponseEntity.status(HttpStatus.CREATED).body(productService.save(product));
    }

    @PutMapping("/{id}")
    public ResponseEntity<Product> update(@PathVariable Long id, @RequestBody Product product) {
        return ResponseEntity.accepted().body(productService.save(product));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity delete(@PathVariable Long id) {
        productService.deleteById(id);

        return ResponseEntity.accepted().build();
    }
}

In Spring, you can use @Controller or @RestController class annotation to indicate a handler for HTTP requests

@RestController is a shorthand for @Controller and @ResponseBody

@ResponseBody indicates handler methods return value will be serialized as JSON and bind to the web response body

@RequestMapping class annotation maps HTTP requests with end point /api/v1/products to all handler methods in ProductAPI class

@RequestBody indicates HTTP request body in JSON string format will be converted to the parameter object

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping indicate HTTP GET, POST, PUT, DELETE request handlers respectively

@PathVariable maps the handler parameter with the URI variable

Config and Run

Application Configurations

Application.java

package com.hellokoding.springboot.restful;

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);
    }
}

Run the application with JDK/OpenJDK and Maven

Type the below command at the project root directory

mvn clean spring-boot:run

Test your REST APIs with curl

Create a new product

curl -i -H "Content-Type: application/json" -X POST -d '{"name":"Hello Koding","description": "Simple coding examples and tutorials","price":"1"}' http://localhost:8080/api/v1/products

Find all products

curl -i http://localhost:8080/api/v1/products

Source code

https://github.com/hellokoding/hellokoding-courses/tree/master/springboot-examples/springboot-restapi

Follow HelloKoding