DEV Community

Nathaly Lopez 👩‍💻
Nathaly Lopez 👩‍💻

Posted on

Build a REST service with Spring Boot and JPA

Creating a REST service with Spring Boot and JPA can be done in less than 10 minutes.

What you need

  • Your favorite IDE (Eclipse, IntelliJ IDEA, Netbeans, STS, etc.)
  • JDK 1.8

Spring Boot works with any of those IDEs. I use Eclipse with Spring Tools plugin which is very useful to run Spring Boot applications from the IDE itself.

Getting Started

First you will need to create a new Maven project with help of Spring Initializr. Select the next dependencies:

  • Web
  • JPA
  • H2

Choose "Generate" and a .zip file will be downloaded. Unzip it. Inside you’ll find a Maven-based project including a pom.xml build file.

Spring Boot Application

In the project that you just generated you will find a class with a main method and the @SrpingBootApplication annotation. This annotation is all we need to run a Spring Boot application.

package com.spring.demo;

@SpringBootApplication
public class RestServiceApplication  {

    public static void main(String[] args) {
    SpringApplication.run(RestServiceApplication.class, args);
    }

}
Enter fullscreen mode Exit fullscreen mode

This is the main class for your Spring Boot application. As you can see Spring Boot saves us a lot of configuration time.

Please note that the package where this class is located will be the one that Spring Boot scans to look for all your application beans. Make sure that all your other classes are located in child packages of this base package. Otherewise Spring Boot will not find your beans and therefore will not be able to inject them. You could also place all classes in the same package, but that is not such a good practice, is it?

Create Entities

Then let's start creating your entity classes that will be used to persist the data with JPA. There are some cases where the service interface model does not necessarily matches the database model. In those cases a data or bean mapping is needed, but for now let's keep it simple.

package com.spring.demo.model;

@Entity
public class Customer {

    @Id @GeneratedValue( strategy = GenerationType.IDENTITY)
    private Long customerId;
    private String firstName;
    private String lastName;

    @OneToMany (cascade = CascadeType.ALL, mappedBy = "customer")
    @JsonIgnoreProperties("customer")
    private List<Subscription> subscriptions;

    public Customer() {}

    public Customer(String firstName, String lastName) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
    }
        //getters & setters
}
Enter fullscreen mode Exit fullscreen mode
package com.spring.demo.model;

@Entity
public class Subscription {

    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private Long id;
    private String description;

    @ManyToOne 
    private Customer customer;

    public Subscription() {}

    public Subscription (Customer customer, String description) {
        this.customer = customer;
        this.description = description;
    }

    //getters & setters
}
Enter fullscreen mode Exit fullscreen mode

Notice that there is a one-to-many relationship between the Customer and Subscription entities. Make sure you use the @JsonIgnoreProperties annotation avoid getting unexpected duplications in the JSON response (having customer within subscription and then subscription again within customer over and over).

Creating Repositories

We need to create repository interfaces to extend JpaRepository which provide us with a set of methods we can use to save, update, delete our entities in the database.

package com.spring.demo.repositories;

public interface CustomerRepository extends JpaRepository <Customer, Long>{

    Collection<Customer> findAllByLastName(String lastName);
    Collection<Customer> findAllByFirstName(String firstName);

}
Enter fullscreen mode Exit fullscreen mode
package com.spring.demo.repositories;

public interface SubscriptionRepository extends JpaRepository<Subscription, Long>{

}
Enter fullscreen mode Exit fullscreen mode

REST Controller

This will be our REST service controller class. This is where we define all the resources that our Service will have. Note that the /subscription resource is expecting a {customerId} path variable and a body with a "description" field.

package com.spring.demo.controllers;

@RestController
public class CustomerServiceController {

    @Autowired
    private CustomerRepository customerRepository;

    @Autowired 
    private SubscriptionRepository subscriptionRepository;

    @RequestMapping("/customers")
    public Collection<Customer> getAllCustomers(){
        return customerRepository.findAll();
    }

    @GetMapping("/customer/{firstName}")
    public Collection<Customer> getByFirstName (@PathVariable String firstName){
        return customerRepository.findAllByFirstName(firstName);
    }

    @PostMapping("/customer")
    public Collection<Customer> addCustomer(@RequestBody Customer customer){
        customerRepository.save(customer);
        return customerRepository.findAll();
    }

    @PostMapping("/subscription/{customerId}")
    public Collection<Customer> addSubscriptionToCustomer(@RequestBody Subscription subscription, @PathVariable Long customerId){

        Optional<Customer> customerOpt = customerRepository.findById(customerId);

        if (customerOpt.get() != null) {
            subscriptionRepository.save(new Subscription(customerOpt.get(), subscription.getDescription()));
        }

        return customerRepository.findAll();
    }
}
Enter fullscreen mode Exit fullscreen mode

Please note that to save some time, the repositories have been injected and used directly from the Rest Controller. However it is a good practice to isolate this logic into a Service layer. A Service class should inject the repositories and contain all the data access logic. The Rest Controller would only call the service layer and return whatever the service is returning.

Bootstrap Class

In case we want to pre-propulate data into the database when our application starts, we can implement the CommandLineRunner interface and override the run method. The moment we implement this class, it will be executed at start up.

An alternative would be to add a *data.sql file into the /resources folder. Spring Boot will take all the DDL or DDM that we add there and run it against the H2 database.

package com.spring.demo.bootstrap;

@Component
public class ServiceCommandLineRunner implements CommandLineRunner{

    private CustomerRepository customerRepository;

    public ServiceCommandLineRunner(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @Override
    public void run(String... args) throws Exception {
        customerRepository.save(new Customer("John", "Doe"));
        customerRepository.save(new Customer("Jane", "Doe"));       
    }
}

Enter fullscreen mode Exit fullscreen mode

H2 Database

H2 is an in memory database that Bootstrap provides. Once the Bootstrap application has been run, to access the H2 console go to this URL: http://localhost:8080/h2-console/

There are two things you need to configure first:

  • 1) Enable H2 console

If you don't enable the console, it would give you an error when you hit the URL above.

  • 2) Set up a data source URL

It is not mandatory, but if you don't set up your own database name, it will be an auto-generated number, something like: jdbc:h2:mem:dc28e750-996e-419e-a35d-79335b1e6706

Add these lines to your application.properties file

spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
Enter fullscreen mode Exit fullscreen mode

Summary

As you can see it is very simple to create a REST service with Spring Boot. Here is a short video showing how to create an even simpler service:

Latest comments (0)