/spring-modulith-with-ddd

Modular Monolith architecture demonstration with Spring Modulith and DDD

Primary LanguageJavaMIT LicenseMIT

Building Modular Monolith Applications with Spring Modulith and Domain Driven Design

This repository showcases a Modular Monolith implementation of borrowing books in a library with Spring Boot, Spring Modulith and Domain Driven Design principles.

The code is explained in a series of blog posts.

  1. Building Modular Monolith Applications with Spring Boot and Domain Driven Design - First attempt at building a Modular Monolith code with only Spring Boot and DDD (does not use Spring Modulith). The code is available in branch part-1-ddd-solution.
  2. Improving Modular Monolith Applications with Spring Modulith - In this blog, we rethink the domain model and apply eventual consistency with Spring Modulith to make the application easier to test, self-documenting and more maintainable. The code is available in branch part-2-spring-modulith and main.
  3. TBA - Further improvements with Hexagonal architecture.

Project Requirements

  • JDK 21
  • Spring Boot 3.2

The Business Problem

  1. The library consists of thousands of books. There can be multiple copies of the same book.
  2. Before being included in the library, every book receives a barcode stamped at the back or one of the end pages. This barcode number uniquely identifies the book.
  3. A patron of the library can make a request to place a book on hold by either locating the book in the library or directly going to the circulation desk and ask for a book by title. If book is available, the patron can proceed to checkout (collect) the book.
  4. The book is checked out for a fixed period of 2 weeks.
  5. To check in (return) the book, the patron can go to the circulation desk or drop it in the drop zone.

Bounded Contexts

image

Run the application

Run the application with the command: mvn spring-boot:run.

Swagger REST API Docs

Access the Swagger UI at http://localhost:8080/swagger-ui.html

image

Examples

Add book to Library

curl -X POST -H Content-Type:application/json http://localhost:8080/catalog/books \
  -d '{"title":"Sapiens","catalogNumber":"12345","isbn":"9780062316097","author":"Yuval Noah Harari"}' | jq

Response:

{
  "id": 1,
  "title": "Sapiens",
  "catalogNumber": {
    "barcode": "12345"
  },
  "isbn": "9780062316097",
  "author": {
    "name": "Yuval Noah Harari"
  }
}

Place a book on hold (start the borrowing process)

curl -X POST -H Content-Type:application/json http://localhost:8080/borrow/loans \
  -d '{"barcode": "12345", "patronId": 1}' | jq

Response:

{
  "id": 1,
  "bookBarcode": "12345",
  "patronId": 1,
  "dateOfHold": "2023-12-28",
  "dateOfCheckout": null,
  "holdDurationInDays": 3,
  "loanDurationInDays": 0,
  "dateOfCheckin": null,
  "status": "HOLDING"
}

Checkout (collect) a book

curl -X POST http://localhost:8080/borrow/loans/1/checkout | jq

Response:

{
  "id": 1,
  "bookBarcode": "12345",
  "patronId": 1,
  "dateOfHold": "2023-12-28",
  "dateOfCheckout": "2023-12-28",
  "holdDurationInDays": 3,
  "loanDurationInDays": 14,
  "dateOfCheckin": null,
  "status": "ACTIVE"
}

Checkin (return) a book

curl -X POST http://localhost:8080/borrow/loans/1/checkin | jq

Response:

{
  "id": 1,
  "bookBarcode": "12345",
  "patronId": 1,
  "dateOfHold": "2023-12-28",
  "dateOfCheckout": "2023-12-28",
  "holdDurationInDays": 3,
  "loanDurationInDays": 14,
  "dateOfCheckin": "2023-12-28",
  "status": "COMPLETED"
}