Build a REST service with Spring Boot and JPA
Tags: spring, rest, jpa, java
Published: 2020-11-20 02:19:21

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] (https://start.spring.io/). 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. 

```java
package com.spring.demo;

@SpringBootApplication
public class RestServiceApplication  {

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

}
```
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.

```java
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
}
```

```java
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
}
```

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.

```java
package com.spring.demo.repositories;

public interface CustomerRepository extends JpaRepository <Customer, Long>{
	
	Collection<Customer> findAllByLastName(String lastName);
	Collection<Customer> findAllByFirstName(String firstName);

}
```

```java
package com.spring.demo.repositories;

public interface SubscriptionRepository extends JpaRepository<Subscription, Long>{

}
```

## 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.

```java
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();
	}
}
```

> 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. 

```java
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"));		
	}
}

```

## 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
```

## 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:

{% youtube p8AdyMlpmPk %}