Spring Boot 2 + PostgreSQL + JWT + React - Full Stack Web Development - Part 2 RESTful Web Service


22 Jun 2019  Michal Fabjanski  5 mins read.

Our application works quite well, but we would like to use the REST principles and manage data via HTTP requests.

In Spring Boot, HTTP requests are handled by controller classes.

In the previous post, we have created an application that automatically creates a database and adds some data to it. Let’s add controllers to it!

REST basics

REST (Representational State Transfer) is an architectural style for designing distributed systems. It’s not a standard, but it defines a set of constraints such as being stateless or having a client/server relationship. The six constraints defined by Roy Fielding (REST creator):

  • Stateless: The server doesn’t hold any information about users,
  • Cacheable: Many users request the same resources. It is useful to cache responses,
  • Uniform interface between components: This simplifies the architecture, as all components follow the same rules to speak to one another,
  • Layered system: individual components cannot see beyond the immediate layer with which they are interacting,
  • Client-server architecture: the client and the server both have a different set of concerns. The server does not send any information without a request from the client,
  • Code on demand: code may be downloaded to extend client functionality. This is an optional constraint.

RESTful Spring Boot service

In Spring boot all requests are handled by controller classes. We have to create our own controller class. To do this, let’s first create the java package for our controller (I created net.devdiaries.wallet.controllers package). Next, create the controller class: CurrenciesController.java.
Now, add the @RestController annotation before the class definition.
@RestController is used to mark classes as Spring MVC Controller. Our controller class looks like this:

         
package net.devdiaries.wallet.controllers;    
    
import org.springframework.web.bind.annotation.RestController;    
    
@RestController    
public class CurrencyController {    
        
}  

To be able to return currencies from the database, we have to inject CurrencyRepository created in previous post.
We will also add a method with the @RequestMapping annotation, which will fetch all currencies from CurrencyRepository. @RequestMapping maps the URL address and/or HTTP method to the controller. Now our code looks like this:

           
package net.devdiaries.wallet.controllers;    
    
import net.devdiaries.wallet.domain.Currency;    
import net.devdiaries.wallet.domain.CurrencyRepository;    
import org.springframework.beans.factory.annotation.Autowired;    
import org.springframework.web.bind.annotation.*;    
    
    
@RestController    
public class CurrencyController {    
    
 private final CurrencyRepository currencyRepository;    
    
 @Autowired    
 public CurrencyController(CurrencyRepository currencyRepository) {    
        this.currencyRepository = currencyRepository;    
    }    
    
 @GetMapping("/currencies")    
 public Iterable<Currency> getCurrencies() {    
        return currencyRepository.findAll();    
    }  
  }      

We are ready to run the application. After run navigates to localhost:8080/currencies. We can see that application get all the currencies from the database and return it in JSON format:
getCurrencies-spring-controller

We must add a few more methods that we will need in our Wallet application.

1 - addCurrency() method marked by @PostMapping annotation:

            
@PostMapping("/currencies")    
void addCurrency(@RequestBody Currency currency) {    
    currencyRepository.save(currency);    
}  

Annotation @PostMapping ( "/currencies") maps the given path to the appropriate method that will handle the HTTP request (POST). @RequestBody annotation maps the HttpRequest body to a transfer or domain object (Currency object).

2 - updateCurrency() method which will be used to update the currency status:

        
@PutMapping("/currencies")    
void updateCurrency(@RequestBody Currency currency) {    
    currencyRepository.save(currency);    
}      

3 - deleteCurrency() method for removing Currency objects from database:

            
@DeleteMapping("/currencies/{id}")    
void deleteCurrency(@PathVariable Long id) {    
    currencyRepository.deleteById(id);    
}  

In deleteCurrency() we used the @PathVariable annotation that will retrieve the currency id from the URI.

The following source code shows the controller final code:

   
package net.devdiaries.wallet.controllers;    
    
import net.devdiaries.wallet.domain.Currency;    
import net.devdiaries.wallet.domain.CurrencyRepository;    
import org.springframework.beans.factory.annotation.Autowired;    
import org.springframework.web.bind.annotation.RestController;    
import org.springframework.web.bind.annotation.GetMapping;    
import org.springframework.web.bind.annotation.DeleteMapping;    
import org.springframework.web.bind.annotation.PostMapping;    
import org.springframework.web.bind.annotation.PutMapping;    
import org.springframework.web.bind.annotation.PathVariable;    
import org.springframework.web.bind.annotation.RequestBody;    
    
    
@RestController    
public class CurrencyController {    
    
 private final CurrencyRepository currencyRepository;    
    
 @Autowired    
 public CurrencyController(CurrencyRepository currencyRepository) {    
        this.currencyRepository = currencyRepository;    
    }    
    
 @GetMapping("/currencies")    
 public Iterable<Currency> getCurrencies() {    
        return currencyRepository.findAll();    
    }    
    
    @DeleteMapping("/currencies/{id}")    
    void deleteCurrency(@PathVariable Long id) {    
        currencyRepository.deleteById(id);    
    }    
    
    @PostMapping("/currencies")    
    void addCurrency(@RequestBody Currency currency) {    
        currencyRepository.save(currency);    
    }    
    
    @PutMapping("/currencies")    
    void updateCurrency(@RequestBody Currency currency) {    
        currencyRepository.save(currency);    
} 
}           

Summary

Congratulations! That’s all. We have created a controller with which the frontend of our application will communicate via REST. In the next post, we will take care of securing the backend of our application. I invite you to read the next part.