Lizard & Dog Blog

Spring boot REST API – Part 1

The gist

Spring Boot offers a simple and efficient way to create REST API. In this article, we’ll explain how you can set up your own API, and connect it to a database to serve content to your mobile and Web apps.

Tech stack

We’ll be using the latest version of Spring, using the default Apache Tomcat server and we will use PostgreSQL for the database. The machine I’ll be using for this tutorial is a Linux server but note that save for database set up the steps are pretty much the same on the other os.

What is a REST API, and why spring?

A REST API is a web service that uses standard HTTP methods for communication and follows representational state transfer principles. Spring Boot is a popular framework for building REST APIs in Java because it simplifies development with its conventions, auto-configuration, and a wide range of libraries and tools.

If you want to learn more about the REST protocol, here are a few links:

https://en.wikipedia.org/wiki/REST

The setup

We’ll divide the set up into the prerequisites (postgresql and java installation) and the actual installation and configuration of Spring.

PostgreSQL Setup

On windows:

Download PostgreSQL Installer:

  • Visit the official PostgreSQL download page: PostgreSQL Download
  • Download the installer suitable for your Windows version (32-bit or 64-bit).

Run the Installer:

  • Double-click on the downloaded installer file to start the installation process.
  • Follow the on-screen instructions. You can leave most settings as default unless you have specific requirements.

Configure PostgreSQL:

  • During the installation, you’ll be prompted to set a password for the default user ‘postgres’. Remember this password, as it will be needed to connect to the PostgreSQL database.

Complete the Installation:

  • Finish the installation process, and PostgreSQL will be installed on your Windows machine.

Start/Stop PostgreSQL Service:

  • PostgreSQL service should start automatically after installation. You can manage the service using the Services application or by running pg_ctl commands in the command prompt.

On linux:

Update Package Repository:

  • Open a terminal.
  • Update the package repository by running: sudo apt update

Install PostgreSQL:

  • Install PostgreSQL by running:sudo apt install postgresql

Configure PostgreSQL:

  • PostgreSQL is automatically started and initialized during installation.
  • The default user is ‘postgres’. You can set a password for this user by running:sudo passwd postgres

Start/Stop PostgreSQL Service:

  • The PostgreSQL service should start automatically. You can use the following commands to manage the service:
sudo service postgresql start
sudo service postgresql stop

On macOS:

Install PostgreSQL with Homebrew:

  • Open a terminal.
  • Install Homebrew if you haven’t already by following the instructions on Homebrew’s official website.
  • Install PostgreSQL by running: brew install postgresql

Start/Stop PostgreSQL Service:

  • Homebrew will automatically start the PostgreSQL service. You can use the following commands to manage the service: brew services start postgresql brew services stop postgresql

Configure PostgreSQL:

  • The default user is ‘postgres’. You can set a password for this user using the psql command: psql postgres \password postgres

To get spring boot running, go to the following link:

https://start.spring.io/

Select the dependencies as per the following image:

We’ll be using Java 17 and Maven for this project, but this could also be done with any other java version and gradle.

Unzip your project and open it with your IDE of choice. Here’s what it looks like on IntelliJ:

The java directory is where we’ll be writing our code.

Take note of the pom.xml file, that’s where you’ll be putting your dependencies, and the application.properties, where you’ll specify info pertaining to db connection and server port.

The API

For this example we’ll be using a database of animals for an pet shop. The pet shop has a list of animals, each associated with a name, a species and a price. As the pet shop owner you want to be able to list all the animals of a given species, or list all the animals by price.

The great thing about Spring is once you are connected to the database, you can easily create tables with the data you want. These will be created as java objects containing the properties you want to use.

Setting up the tables

We’ll begin by setting up the database Entity (in our case the Animal class). Create the following file in your java folder:

package com.example.demo;

import jakarta.persistence.*;

@Entity
@Table(name = "animals")
public class Animal {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String species;
    private double price;
    private boolean sold;
    // Constructors, getters, and setters can be added here.
// Default constructor
    public Animal() {    }
// Parameterized constructor    
  public Animal(String name, String species, double price, boolean sold) {        
        this.name = name;        
        this.species = species;        
        this.price = price;        
        this.sold = sold;    }
//Parameterized constructor 2    
     public Animal(String name, String species, double price) {
        this.name = name;
        this.species = species;
        this.price = price;
        this.sold=false;
    }  

    @Override
    public String toString() {
        return "Animal{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", species='" + species + '\'' +
                ", price=" + price +
                ", sold=" + sold +
                '}';
    }
    // Getters and setters
    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 getSpecies() {        return species;    }

    public void setSpecies(String species) {
        this.species = species;    }

    public double getPrice() {        return price;    }

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

    public boolean isSold() {        return sold;    }

    public void setSold(boolean sold) {        this.sold = sold;    }
}

Overall this looks like a regular java class. Note the following distinctions:

  • It requires a constructor with all the values.
  • It has the @Entity annotation, that signifies it is a JPA entity.
  • It has the @Table annotations whichpecifies the name of the database table to which this entity is mapped.
  • The id of the animal has two associated annotations, @Id and @GeneratedValue(strategy = GenerationType.IDENTITY) . @Id Denotes the primary key field of the entity. @GeneratedValue(strategy = GenerationType.IDENTITY) Configures the strategy for generating primary key values.

The next step in developing our API is to connect it to a database. To do so, we’ll work with the application.properties file.

You’ll begin by creating a new psql user, who will be associated to a database. For the sake of this exercise, the user will be called John, associated with the password password1234 (also for goodness sake, please change that in production!)

Here’s how your application properties should look like. The first 3 lines specify the database connection information.

This line spring.jpa.hibernate.ddl-auto=create-drop specifies that the table will be created when the application starts and deleted when it ends.

Note that by default, when you run the application it’ll start a server on port 8080. To change that you can append the following line to your application.properties:

server.port=8081

Run the application and you should notice in the console that the following line appears:

Hibernate: create table animals (price float(53) not null, sold boolean not null, id bigserial not null, name varchar(255), species varchar(255), primary key (id))

This means that the table was created. Now to access it!

Setting up the methods

The way our code will be structured will be like so:

A controller class will contain the methods we’ll be using.

A service class will contain the “behind the scenes” logic for each method.

A repository will contain the interface between our java code and our database.

The controller:

We’ll begin by creating the AnimalController class like so:

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/petShopAPI")
public class AnimalController {

@GetMapping("/getAnimals")
public String getAnimals()
{

return "Nothing there yet!";

}
}

The annotations are pretty straightforward for this one:

@RestController: tells you this is a rest controller!

@RequestMapping(“/api/petShopAPI”): specifies the url path for this controller. It comes in handy if you want to have multiple controllers for your api.

The GET mapping is associated with the getAnimals() method, and with the /getAnimals url extension.
If you launch the app and go to your browser at the url:

localhost:8080/api/petShopAPI/getAnimals

You should see the following text on the screen:

Nothing there yet!

We’ll then create the following methods:

    @PostMapping("/buyAnimal")
    public void buyAnimal(@RequestParam(name="name", required=true)String name, @RequestParam(name="species", required=true)String species, @RequestParam(name="price", required=true) double price )
    {
        
    }

    @PutMapping("/sellAnimal")
    public void sellAnimal(@RequestParam(name="name", required=true)String animalName)
    {

    }

    @DeleteMapping("/removeAnimalFromInventory")
    public void removeAnimal(@RequestParam(name="id", required=true)long animalID)
    {

    }

These methods are the endpoints we will use to modify the animal database.

The @RequestParam annotation allows to append more information to the the request. Say you’d like to buy an Animal (aka add it to the database). You’d be passing the following information with your POST request:

name=Mephisto

species=cat

price=300.0

For safety reasons it is sometimes better to use headers instead of params but these will be covered in a later blog post.

To test if your basic controller is working, you could install a program like postman that would help you generate post, put and delete request. Here, I used postman to simulate the above POST request:

It generated me a 200 OK response, meaning the request didn’t generate any errors with our API.

The service and repository:

Right now, our code doesn’t do much in terms of actual database interaction. To solve that, we’ll create one AnimalService class and one AnimalRepository interface.

package com.example.demo;

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

@Repository
public interface AnimalRepository extends JpaRepository<Animal, Long> {
}
package com.example.demo;

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

@Service
public class AnimalService {
    AnimalRepository animalRepository;

    @Autowired
    public AnimalService(AnimalRepository animalRepository){
        this.animalRepository=animalRepository;
    }
    
}

The AnimalRepository contains methods that access directly the database. The AnimalService on the other hand will contain the actual logic of our code.

The @Autowired annotation in the constructor signals to Spring that when it creates an instance of AnimalService, it should automatically provide an instance of AnimalRepository.

We’ll proceed the same way by adding a constructor to the controller, to specify it needs to create an instance of the service:

public class AnimalController {
    AnimalService animalService;
    @Autowired
    public AnimalController(AnimalService animalService) {
        this.animalService = animalService;
    }

    //... Rest of the code goes here
}

This will allow us to directly use the service in the controller.

Let’s now focus on the service itself. We’ll work on how to append a new animal to our database first:

@Service
public class AnimalService {
// Your service constructor here...
    public void buyAnimal(String name, String species, double price){
        Animal newAnimal= new Animal(name,species,price);
        animalRepository.save(newAnimal);
    }
}

We’ll then update the controller code to call this method when we do a POST request:

@RestController
@RequestMapping("/api/petShopAPI")
public class AnimalController {
    
// Your other methods and constructor...
    @PostMapping("/buyAnimal")
    public void buyAnimal(@RequestParam(name="name", required=true)String name, @RequestParam(name="species", required=true)String species, @RequestParam(name="price", required=true) double price )
    {
       animalService.buyAnimal(name, species, price);
    }

}

Relaunch the code and try your request again, and you should have the following console output:

Hibernate: insert into animals (name,price,sold,species) values (?,?,?,?)

This shows you successfully added Mephisto to the list of animals in your inventory. It is however not very telling, how do we access our inventory?

To focus on that, we’ll implement the GET method, first in the service:

@Service
public class AnimalService {
// Your service constructor here...
    public List<Animal> getAnimals(){
        return animalRepository.findAll();
    }
}

And then in the controller:

@RestController
@RequestMapping("/api/petShopAPI")
public class AnimalController {
    
// Your other methods and constructor...
    @GetMapping("/getAnimals")
    public List<Animal> getAnimals()
    {
          return animalService.getAnimals();
    }
}

Notice how we changed the return type of the method? It should now display a list of animals when you launch the request in the browser.

Try relaunching the code and doing a POST request, then a GET request:

The output is a JSON array. You could view JSON as a standard way of passing information. A JSON object is usually constructed like a Map of properties and values and is commonly used in conjunction with rest APIs.

Next steps:

In the next part of our tutorial, we’ll implement the PUT and DELETE methods, and will show you various database manipulation methods, as well as request headers. Click here to access it.

You can also access the full code of the tutorial on our GitHub:

https://github.com/lizardanddog/spring_tutorial_repository


If you have any question, feel free to post them below, or to visit our website at:

lizardanddog.com

One response to “Spring boot REST API – Part 1”

  1. […] already implemented the basics of a Spring Boot API in Part 1 , but now we want to add additional functionalities to our existing […]

    Like

Leave a comment