A production-ready RESTful online bookstore API built with Spring Boot, featuring a shopping cart, order management, JWT authentication, and full Swagger documentation β deployed on AWS.
π Live Demo: Swagger UI π¬ Video Tutorial: Watch on Loom
- Overview
- Tech Stack
- Features
- Getting Started
- Environment Variables
- API Reference
- Security
- Usage Flow
- Database Schema
- Tests
- Swagger UI
Online Book Store is a backend REST API that supports two user roles:
- π€ Users β browse and search books by category, manage a personal shopping cart, and place orders
- π οΈ Admins β create, update, and delete books and categories, and manage order statuses
Any user whose email contains ..admin@.. is automatically assigned ROLE_ADMIN on registration.
| Category | Technology |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot |
| Security | Spring Security + JWT |
| Database | MySQL |
| Migrations | Liquibase |
| ORM | Spring Data JPA / Hibernate |
| Mapping | MapStruct |
| API Docs | Swagger / SpringDoc OpenAPI |
| Validation | Hibernate Validator |
| Boilerplate | Lombok |
| Testing | JUnit 5 |
| Pagination | Spring Data Pageable |
| Containerization | Docker |
| Build | Maven |
| Version Control | Git |
| Cloud (AWS) | EC2, RDS, IAM, ECR |
Following diagram shows project architecture layer by layer:
- Filter layer - client sends every request with a JWT bearer token. Before anything reaches the controllers, the request passes through the Security filter chain.
- Controller layer - holds five REST controllers. They handle HTTP mapping, validate incoming DTOs, and delegate all logic downward.
- Service layer - contains the business logic, split by domain.
- Repository layer - is built on Spring Data JPA. Each entity has its own repository interface.
- Database layer - MySQL, managed entirely by Liquibase. The 11 migration changelogs run on startup and create the schema.
- Domain model - sits at the base, shared across all layers - eight entities.
The application is deployed on Amazon Web Services (AWS) using a production-style architecture that separates compute, database, security, and container registry responsibilities.
| Service | Purpose in This Project |
|---|---|
| EC2 | Hosts the running Spring Boot Docker container and exposes the public API / Swagger UI |
| RDS (MySQL) | Managed relational database used to persist users, books, carts, and orders |
| IAM | Controls secure access to AWS resources through users, permissions, and CLI credentials |
| ECR Public | Stores and distributes the Docker image used to deploy the application |
| Security Groups | Firewall rules controlling inbound HTTP traffic to EC2 and MySQL traffic to RDS |
- Authentication - Register and login with JWT token issuance
- Book Management - Full CRUD for books, with search/filter by price and other parameters (Admin only for write operations)
- Category Management - Organize books into categories (Admin only for write operations)
- Shopping Cart - Add, update, and remove books from a personal cart
- Order Management - Place orders from cart, view order history and items, update order status (Admin)
- Role-Based Access Control -
USERandADMINroles enforced at endpoint level - Soft Deletes - Entities are never physically removed;
is_deletedflags ensure data integrity - API Documentation - Swagger UI available at
/swagger-ui.htmlor this link
- Java 17
- Maven
- Docker & Docker Compose
- MySQL
git clone https://github.com/your-username/online-book-store.git
cd online-book-storeSet up your .env file (see Environment Variables), then:
# 1. Build the JAR
mvn clean package
# 2. Start the Docker container
docker-compose upThe API will be available at:
http://localhost:{SPRING_LOCAL_PORT}/api
For example, with SPRING_LOCAL_PORT=4040:
http://localhost:4040/api/swagger-ui/index.html
Create a .env file in the project root. Use the template below as a guide:
MYSQLDB_USER=template_user
MYSQLDB_ROOT_PASSWORD=template_password
MYSQLDB_DATABASE=template_database
MYSQLDB_LOCAL_PORT=3303
MYSQLDB_DOCKER_PORT=3306
SPRING_LOCAL_PORT=4040
SPRING_DOCKER_PORT=8080
DEBUG_PORT=5005
A .env_template file is included in the repository with these example values.
π
SPRING_LOCAL_PORTdetermines the port your endpoints are served on locally.
All endpoints are prefixed with /api. There are 23 endpoints in total.
| Method | Path | Action | Required Fields | Auth |
|---|---|---|---|---|
| POST | /register |
Register a new user | email, firstName, lastName, password, repeatPassword |
PUBLIC |
| POST | /login |
Log in and receive a JWT token | email, password |
PUBLIC |
| Method | Path | Action | Required Fields | Optional Fields | Auth |
|---|---|---|---|---|---|
| POST | /categories |
Create a new category | name |
description |
ROLE_ADMIN |
| GET | /categories |
Get all categories | β | β | ROLE_USER |
| GET | /categories/{category_id} |
Get category by ID | β | β | ROLE_USER |
| PUT | /categories/{category_id} |
Update category by ID | name |
description |
ROLE_ADMIN |
| DELETE | /categories/{category_id} |
Delete category by ID | β | β | ROLE_ADMIN |
| GET | /categories/{category_id}/books |
Get all books in a category | β | β | ROLE_USER |
| Method | Path | Action | Required Fields | Optional Fields | Auth |
|---|---|---|---|---|---|
| POST | /books |
Create a new book | author, title, isbn, price, categoryIds |
description, coverImage |
ROLE_ADMIN |
| GET | /books |
Get all books | β | β | ROLE_USER |
| GET | /books/{book_id} |
Get book by ID | β | β | ROLE_USER |
| PUT | /books/{book_id} |
Update book by ID | author, title, isbn, price, categoryIds |
description, coverImage |
ROLE_ADMIN |
| DELETE | /books/{book_id} |
Delete book by ID | β | β | ROLE_ADMIN |
| GET | /books/search |
Search books by parameters | β | query params | ROLE_USER |
| Method | Path | Action | Required Fields | Auth |
|---|---|---|---|---|
| POST | /cart |
Add a book to the cart | bookId, quantity |
ROLE_USER |
| GET | /cart |
Get the current user's cart | β | ROLE_USER |
| PUT | /cart/cart-items/{cart_item_id} |
Update cart item quantity | quantity |
ROLE_USER |
| DELETE | /cart/cart-items/{cart_item_id} |
Remove an item from the cart | β | ROLE_USER |
| Method | Path | Action | Required Fields | Auth |
|---|---|---|---|---|
| POST | /orders |
Place a new order | shippingAddress |
ROLE_USER |
| GET | /orders |
Get all orders for current user | β | ROLE_USER |
| PATCH | /orders/{order_id} |
Update order status | status |
ROLE_ADMIN |
| GET | /orders/{order_id}/items |
Get all items in an order | β | ROLE_USER |
| GET | /orders/{order_id}/items/{item_id} |
Get a specific item from an order | β | ROLE_USER |
Authentication uses JWT Bearer tokens.
- Register at
POST /api/registeror login atPOST /api/login - Copy the
tokenvalue from the response - Add it as a header to all subsequent requests:
Authorization: Bearer <your_token_here>
Role permissions:
| Role | Capabilities |
|---|---|
| PUBLIC | Register, Login |
| ROLE_USER | Browse books & categories, manage own shopping cart & orders |
| ROLE_ADMIN | Everything ROLE_USER can do + manage books, categories, and order statuses |
π Any user whose email contains
admin@is automatically grantedROLE_ADMINon registration.
Diagram showing a simple use case of the application

The database is managed by Liquibase. Key tables include:
| Table | Description |
|---|---|
users |
User credentials and profile data |
roles |
ROLE_USER, ROLE_ADMIN |
user_roles |
Join table (users β roles) |
books |
Title, author, ISBN, price, cover image |
categories |
Name and description |
book_category |
Many-to-many join table (books β categories) |
shopping_carts |
One cart per user |
cart_items |
Book + quantity, linked to a shopping cart |
orders |
Shipping address, status, user reference |
order_items |
Snapshot of books and quantities at time of order |
The diagram shows a complete view over entities and their relations.
The project includes tests covering 92% of code lines across the application.
To run all tests run this command:
mvn testTests are written with JUnit 5 and cover the service, repository, and controller layers.
Interactive API documentation is available when the application is running.
Locally:
http://localhost:{SPRING_LOCAL_PORT}/api/swagger-ui/index.html
Live (AWS):
http://ec2-16-170-247-139.eu-north-1.compute.amazonaws.com/api/swagger-ui/index.html#/
Create new user request
Create new user response
Login request
Login response
Authorization JWT Token
List all categories request
List all categories response










