Today we're moving on to the most interesting part: practice. In this lecture we'll build a simple microservice using Spring Boot.
Part 1: Environment and tooling setup
First let's prepare the environment for our microservice. We'll use Spring Initializr to quickly generate a starter project.
Step 1: Creating a project via Spring Initializr
Go to Spring Initializr and pick project settings:
- Project: Maven (or Gradle, if you're a fan).
- Spring Boot Version: pick a current version (for example, 3.0.0+).
- Dependencies:
- Spring Web — for building the REST API.
- Spring Data JPA — for database access.
- H2 Database — for a simple embedded DB (in a real project you can swap it for MySQL, PostgreSQL, etc.).
Fill in other project parameters, for example:
- Group:
com.example - Artifact:
orderservice - Name:
OrderService
Then click "Generate", download the archive and unzip it.
Step 2: Import the project into your IDE
Import the project into your favorite IDE (for example IntelliJ IDEA or Eclipse). Then open pom.xml and make sure all dependencies resolved correctly. If you're using Gradle, check build.gradle.
Part 2: Developing a simple microservice
We'll build an order management microservice (OrderService). Our microservice will expose a REST API for CRUD operations on the Order entity.
Step 1: Configure entities and database
The Order entity
Create the package com.example.orderservice.model, then add the Order class:
package com.example.orderservice.model;
import jakarta.persistence.*;
import java.time.LocalDateTime;
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String product;
private Integer quantity;
private Double price;
private LocalDateTime orderDate;
// Getters and Setters...
// No-args constructor
public Order() {}
// Constructor with parameters
public Order(String product, Integer quantity, Double price, LocalDateTime orderDate) {
this.product = product;
this.quantity = quantity;
this.price = price;
this.orderDate = orderDate;
}
}
@Entity annotation, JPA will politely ignore your class, and the database won't even know it exists.
Database configuration
In application.properties (or application.yml) add the H2 configuration:
spring.datasource.url=jdbc:h2:mem:ordersdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update
Now we have an embedded database and can interact with it via JPA.
Step 2: Create the repository
Add a repository interface for our entity.
Create the package com.example.orderservice.repository and inside it the OrderRepository class:
package com.example.orderservice.repository;
import com.example.orderservice.model.Order;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderRepository extends JpaRepository<Order, Long> {
}
With this interface we get all the standard CRUD operations out of the box.
Step 3: Implement business logic (service layer)
Add the service class. Create the package com.example.orderservice.service and the OrderService class:
package com.example.orderservice.service;
import com.example.orderservice.model.Order;
import com.example.orderservice.repository.OrderRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public List<Order> getAllOrders() {
return orderRepository.findAll();
}
public Order getOrderById(Long id) {
return orderRepository.findById(id).orElseThrow(() -> new RuntimeException("Order not found"));
}
public Order createOrder(Order order) {
return orderRepository.save(order);
}
public Order updateOrder(Long id, Order updatedOrder) {
Order order = getOrderById(id);
order.setProduct(updatedOrder.getProduct());
order.setQuantity(updatedOrder.getQuantity());
order.setPrice(updatedOrder.getPrice());
return orderRepository.save(order);
}
public void deleteOrder(Long id) {
orderRepository.deleteById(id);
}
}
Step 4: Implement the REST API (controller)
Now let's expose the REST API. Create the package com.example.orderservice.controller and the OrderController class:
package com.example.orderservice.controller;
import com.example.orderservice.model.Order;
import com.example.orderservice.service.OrderService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@GetMapping
public List<Order> getAllOrders() {
return orderService.getAllOrders();
}
@GetMapping("/{id}")
public ResponseEntity<Order> getOrderById(@PathVariable Long id) {
return ResponseEntity.ok(orderService.getOrderById(id));
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Order createOrder(@RequestBody Order order) {
return orderService.createOrder(order);
}
@PutMapping("/{id}")
public Order updateOrder(@PathVariable Long id, @RequestBody Order order) {
return orderService.updateOrder(id, order);
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteOrder(@PathVariable Long id) {
orderService.deleteOrder(id);
}
}
Part 3: Testing and debugging
Step 1: Run the application
Run OrderServiceApplication — the main class of our microservice:
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
If everything is set up correctly, the application will run on port 8080.
Step 2: Test with Postman or curl
Sample requests:
- GET
/api/orders— get all orders. - POST
/api/orderswith body:
{
"product": "Laptop",
"quantity": 2,
"price": 1200.00,
"orderDate": "2023-10-01T10:00:00"
}
- PUT
/api/orders/1to update an existing order. - DELETE
/api/orders/1to remove an order.
Part 4: What's next?
Congrats! We've built a basic order management microservice. You can extend this simple example by adding features like input validation, error handling, authentication, or integrating with Kafka for event-driven architecture. All that awaits us next!
GO TO FULL VERSION