Your first Spring boot RESTful API
In this tutorial, we are going to work you through the steps of building a small but functional spring boot RESTful API to perform basic CRUD operation on an Object call Item.
Your pom.xml file should have these dependencies
/itemApi/pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Create the Item Entity Class. You can use Lombok to auto generate Getter and Setter at compile time
itemApi/src/main/java/com/eddytnk/itemApi/model/Item.java
package com.eddytnk.itemApi.model;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
@Data
public class Item {
@Id
private Long id;
private String name;
private double price;
private int quantity;
}
Create a JPA Repository to help manage CRUD and basic operations for this Entity. In this project, we are using H2 in-memory database. Most-likely in your project you would be using a different Database like Oracle or MySql or DB2 but however, the process is the same and spring boot will auto configure connection to the database once we add the dependency to the class path. For example one spring boot sees com.h2database in the class path it will auto-configure H2 in-memory database
itemApi/src/main/java/com/eddytnk/itemApi/repository/ItemRepository.java
package com.eddytnk.itemApi.repository;
import com.eddytnk.itemApi.model.Item;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ItemRepository extends JpaRepository<Item, Long> {
}
Now that you have created the Entity class and a Repository to manage persistent and retrieval of this entity, you will now need the Service class to manage the business logic around this entity.
package com.eddytnk.itemApi.service;
import com.eddytnk.itemApi.model.Item;
import com.eddytnk.itemApi.repository.ItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class ItemService {
private ItemRepository itemRepository;
@Autowired
public ItemService(ItemRepository itemRepository) {
this.itemRepository = itemRepository;
}
public List<Item> getAllItems() {
return itemRepository.findAll();
}
public Item getItem(Long id) {
Optional<Item> itemOptional = itemRepository.findById(id);
if (!itemOptional.isPresent()) {
throw new RuntimeException("Item not found.");
}
return itemOptional.get();
}
public Item addNewItem(Item item) {
return itemRepository.save(item);
}
public void updateItem(Long id, Item item) {
Optional<Item> itemOptional = itemRepository.findById(id);
if (!itemOptional.isPresent()) {
throw new RuntimeException("Item not found.");
}
Item newItem = itemOptional.get();
newItem.setId(item.getId());
newItem.setName(item.getName());
newItem.setPrice(item.getPrice());
newItem.setQuantity(item.getQuantity());
itemRepository.save(newItem);
}
public void removeItem(Long id) {
itemRepository.deleteById(id);
}
}
Every API is not complete without the Interface in which the user connects to the API. This interface is defined in the Controller Component.
package com.eddytnk.itemApi.controller; import com.eddytnk.itemApi.model.Item; import com.eddytnk.itemApi.service.ItemService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.net.URI; import java.util.List; @RestController @RequestMapping("/api") public class ItemController { private ItemService itemService; @Autowired public ItemController(ItemService itemService) { this.itemService = itemService; } @PutMapping("/items") public ResponseEntity<?> addItem(@RequestBody Item item) { Item savedItem = itemService.addNewItem(item); return ResponseEntity.created(URI.create("/items/" + savedItem.getId())).build(); } @GetMapping("/items") public ResponseEntity<List<Item>> getItems() { return ResponseEntity.ok(itemService.getAllItems()); } @GetMapping("/items/{itemId}") public ResponseEntity<Item> getItem(@PathVariable("itemId") Long id) { return ResponseEntity.ok(itemService.getItem(id)); } @PostMapping("/items/{itemId}") public ResponseEntity<?> updateItem(@PathVariable("itemId") Long id, @RequestBody Item item) { itemService.updateItem(id, item); return ResponseEntity.noContent().build(); } @DeleteMapping("/items/{itemId}") public ResponseEntity<?> deleteItem(@PathVariable("itemId") Long id) { itemService.removeItem(id); return ResponseEntity.noContent().build(); } }
You can now run your application and try out the different endpoints
GET /api/items –> Retrieve all Items
GET /api/items/{itemId} –> retrieve a particular Item
PUT /api/Items/ –> Add a new Item to the Database
POST /api/items/{itemId} –> Update the Item with id {itemId}
DELETE /api/items/{itemId} –> Delete item with id {itemId}
When developing RESTful API, we have to make sure we properly use all the HTTP verbs GET, POST, PUT, DELETE, PATCH correctly
The HTTP Verb PATCH is mostly used when a particular field in the Entity is to be modified independently from the others e.g if i want to only change the value of price in the Item Entity while keeping all the others unchanged
@PatchMapping("/items/{itemId}")
public ResponseEntity<?> changePrice(@PathVariable("itemId") Long id, @RequestParam("price") Double price) {
itemService.changePrice(id, price);
return ResponseEntity.noContent().build();
}
Download or Clone source code on GitHub
This is a nice walk through and perfect for quick revisions. Much courage in your writings. We stick to the blog cause we know more is coming.
Hello there, just became aware of your blog through Google, and
found that it’s truly informative. I am gonna watch out for
brussels. I’ll appreciate if you continue this in future.
A lot of people will be benefited from your writing.
Cheers!