Spring Boot Microservices Choreography Example

Introduction

This project demonstrates the choreography saga pattern in Spring Boot microservices architecture using Apache Kafka,

Spring Cloud Eureka, and Spring Cloud API Gateway.

In modern microservices architectures, handling distributed transactions across multiple services is a complex problem. Traditional ACID transactions do not scale well across service boundaries, especially in cloud‑native and event‑driven systems.

The goal is to build a loosely coupled, event‑driven, and highly scalable system where services coordinate business transactions using Kafka events and asynchronous calls. So, each service consumes events to trigger local transactions and publishes new events to trigger subsequent steps, enhancing loose coupling, scalability, and resilience.

Saga Choreography

A Saga is a sequence of local transactions where each step publishes an event that triggers the next step.

There are two main saga styles:

Orchestration

  • A central controller manages the workflow.
  • Simpler flow visibility, but higher coupling.

An example on orchestration can be found Spring Boot Microservices Orchestration Example.

Choreography

  • No central coordinator.
  • Each service reacts to events and publishes new ones.
  • More scalable and resilient.
  • Better fits event‑driven architectures.

In this Saga Choreography example, Kafka becomes the backbone of the transaction flow.

Tech Stack

  • Spring Boot for all services
  • Spring REST APIs
  • Spring Cloud Eureka Server for service discovery
  • Spring Cloud API Gateway for routing requests to services
  • MySQL
  • Kafka
  • Maven

High‑Level Architecture

Systems involved – we will build seven Spring Boot applications:

  1. discovery-service (Eureka Server) – 8761
  2. api-gateway (Spring Cloud Gateway) – 8080
  3. order-service (Saga initiator) – 8081
  4. payment-service (Processes payments) – 8082
  5. inventory-service (Checks & reserves stock) – 8083
  6. notification-service (Sends SMS/Email-style notifications) – 8084
  7. common-dto (Shared DTO Module)
  • discover-service is used for service registration
  • api-gateway is single entry point
  • order-service is saga initiator
  • payment-service is used for processing payment
  • inventory-service is used for stock validation
  • notification-service is used for event notifications
  • common-dto is shared event models

Each of the above services:

  • Has its own database
  • Is independently deployable
  • Communicates only via Kafka events
  • No service calls another service directly

Business Flow:

Client → API Gateway → Order Service → Kafka
→ Payment Service → Kafka
→ Inventory Service → Kafka
→ Notification Service → Kafka
→ Order Service (final status update)

Event‑Driven Workflow

Apache Kafka is used for event driven flow. Kafka uses the following topics:

  • order-created
  • payment-completed
  • payment-failed
  • inventory-reserved
  • inventory-failed
  • notification-send
  • order-status-updated

Kafka guarantees:

  • Asynchronous communication
  • Loose coupling
  • Fault tolerance (events survive service restarts)

Startup Kafka

Open Command Prompt and run:

Start Zookeeper

bin\windows\zookeeper-server-start.bat config\zookeeper.properties

Start Kafka

bin\windows\kafka-server-start.bat config\server.properties

If you have enabled auto.create.topics.enable=true in server.properties then you don’t need to create kafka topics manually, otherwise you can create them manually using the following commands:

bin\windows\kafka-topics.bat --create --topic order-created --bootstrap-server localhost:9092
bin\windows\kafka-topics.bat --create --topic payment-completed --bootstrap-server localhost:9092
bin\windows\kafka-topics.bat --create --topic payment-failed --bootstrap-server localhost:9092
bin\windows\kafka-topics.bat --create --topic inventory-reserved --bootstrap-server localhost:9092
bin\windows\kafka-topics.bat --create --topic inventory-failed --bootstrap-server localhost:9092
bin\windows\kafka-topics.bat --create --topic notification-send --bootstrap-server localhost:9092

MySQL Server Startup

Make sure MySQL server is running. The databases are created automatically due to ?createDatabaseIfNotExist=true

You will see the following databases corresponding your services:

  • order-service: orderdb
  • payment-service: paymentdb
  • inventory-service: inventorydb
  • notification-service: notificationdb

You can insert one product in the inventory to test the flow when you startup the services:

INSERT INTO inventory (product_id, quantity)
VALUES ('P1001', 10);

Microservices Startup

Start the services in the following order:

  • Discovery Service (Port 8761)
  • Order Service (8081)
  • Payment Service (8082)
  • Inventory Service (8083)
  • Notification Service (8084)
  • API Gateway (8080)

API Gateway Test URLs

When microservices run, you can test endpoints like:

POST http://localhost:8080/orders/create
POST http://localhost:8080/orders
GET http://localhost:8080/payments/status/123
GET http://localhost:8080/inventory/check/abc

End‑to‑End Saga Flow

  1. All services register to Eureka
  2. All HTTP requests route through Gateway
  3. Kafka event flow implements Saga Choreography

Test Flow

Client sends request

POST /orders (via API Gateway)

Order Service

  • Saves order with status ORDER_CREATED
  • Publishes order-created

Payment Service

  • Consumes order-created
  • If amount ≤ 5000 → payment succeeds
  • Publishes payment-completed

Inventory Service

  • Consumes payment-completed
  • Checks stock
  • Publishes inventory-reserved

Order Service

Final status updated to ORDER_COMPLETED

Notification Service

Saves notification logs

Summary

  • Saga completes
  • No distributed locks
  • No blocking calls

Test Examples

Successful Test

Request:

POST http://localhost:8080/orders

Content-Type: application/json

Body:

{
  "userId": "user100",
  "amount": 1200.50
}

Expected Flow (Logs):

order-service – Order Created Event Sent
payment-service – Payment Completed Event Sent
inventory-service – Inventory Reserved Event Sent
notification-service – Notification saved (Inventory Reserved)
order-service – Order Completed

Expected DB Output:

orders.order_status = ORDER_COMPLETED

Failure Test

Request

POST http://localhost:8080/orders

Content-Type: application/json

Body:

{
  "userId": "user200",
  "amount": 6500
}

Expected Flow (logs):

order-service – Order Created
payment-service – Payment Failed
notification-service – notification: Payment failed
order-service – Order Cancelled

Verify Notification Storage

You can verify the notification by the following request.

Request:

GET http://localhost:8080/notifications

Expected sample result:

[
  {
    "id": 1,
    "orderId": "123e-uuid",
    "message": "Payment successful for Order: 123e-uuid",
    "email": "customer@example.com"
  }
]

Verify Payment and Inventory Records

Payment:

http://localhost:8080/payments/{orderId}

Inventory:

http://localhost:8080/inventory/{orderId}

Full Saga Flow Summary

Client → POST /orders

Order Service → publish order-created

Payment Service → payment-completed / payment-failed

Inventory Service → inventory-reserved / inventory-failed

Order Service → updates order state

Notification Service → sends notification email

Conclusion

This project demonstrates a real‑world, end‑to‑end Saga Choreography implementation using Spring Boot microservices and Kafka, without shortcuts or hidden orchestration logic.

Source Code

Download

Share

Related posts

No comments

Leave a comment