Skip to content

Repository files navigation

Inventory Management System (Spring Boot)

An inventory management application with a Spring Boot REST backend and a simple Thymeleaf frontend for quick browser-based usage.

This project is built for the Software Engineering Lab requirement and focuses on clean backend architecture plus a beginner-friendly Thymeleaf UI layer.

Project Overview

  • Domain: Inventory management
  • Backend: Spring Boot 3.2.5, Java 21, Spring Data JPA, Spring Security, Validation
  • Database: PostgreSQL
  • API Style: REST + DTO-based responses
  • Frontend: Thymeleaf templates with a minimal multi-page UI
  • Testing: JUnit 5, Mockito, Spring Boot Test, MockMvc
  • Containerization: PostgreSQL via Docker Compose
  • CI: GitHub Actions (.github/workflows/ci.yml) runs Maven tests on pushes and PRs
  • CD: GitHub Actions (.github/workflows/cd.yml) triggers Render deploy on main

Requirement Coverage (Current Status)

Status legend: Done

Requirement Status Notes
Authentication and Authorization Done Role-based access is enforced with SecurityConfig + @PreAuthorize; login/logout UI flow is implemented.
REST API Design (>=3 controllers, CRUD for >=2 entities) Done 6 controllers implemented. Full CRUD exists for Product and Category.
PostgreSQL + >=4 tables + relationships Done 6 entities with 1:N, N:1, 1:1, and N:N relationships.
Testing (>=15 unit + >=3 integration) Done Requirement is satisfied; latest local Surefire report shows 53 total tests (0 failures).
Dockerization (Dockerfile + compose app+db) Done Dockerfile and compose.yaml include both app and PostgreSQL services.
GitHub workflow strategy (main/develop/feature, protected main, PR review) Done Branching strategy and PR workflow are in use for development and release flow.
CI/CD (build + test + deploy from main) Done CI (ci.yml) runs tests; CD (cd.yml) triggers Render deploy from main.
Deployment on Render + public URL Done Live app is available on Render (see deployment URL below).
Documentation (README with architecture, ERD, API, run steps, CI/CD) Done This README documents the implemented architecture, APIs, setup, testing, and deployment.

Architecture

Layered architecture is used:

  • Controller layer: REST endpoints and HTTP status handling
  • Service layer: business rules and validations
  • Repository layer: Spring Data JPA data access
  • Entity/DTO layer: persistence models + API-safe response models
  • Exception layer: centralized global exception handling

Package Structure

src/main/java/com/example/inventorymanagement
|- config/
|  |- SecurityConfig.java
|- controller/
|  |- CategoryController.java
|  |- HomeController.java
|  |- PageController.java
|  |- ProductController.java
|  |- ProductDetailController.java
|  |- StockLogController.java
|  |- SupplierController.java
|  |- UserController.java
|- dto/
|  |- CategoryDTO.java
|  |- ProductDTO.java
|  |- ProductDetailDTO.java
|  |- StockLogDTO.java
|  |- SupplierDTO.java
|  `- UserDTO.java
|- entity/
|  |- Category.java
|  |- Product.java
|  |- ProductDetail.java
|  |- StockLog.java
|  |- Supplier.java
|  `- Users.java
|- exception/
|  |- ErrorDetails.java
|  |- GlobalExceptionHandler.java
|  `- ResourceNotFoundException.java
|- repository/
|  |- CategoryRepository.java
|  |- ProductRepository.java
|  |- ProductDetailRepository.java
|  |- StockLogRepository.java
|  |- SupplierRepository.java
|  `- UserRepository.java
`- service/
   |- CategoryService.java
   |- ProductService.java
   |- ProductDetailService.java
   |- StockLogService.java
   |- SupplierService.java
   `- UserService.java

Data Model (ER Overview)

erDiagram
    USERS ||--o{ STOCK_LOG : creates
    PRODUCT ||--o{ STOCK_LOG : tracked_in
    CATEGORY ||--o{ PRODUCT : contains
    PRODUCT ||--|| PRODUCT_DETAIL : has
    PRODUCT }o--o{ SUPPLIER : supplied_by
Loading

Entities implemented:

  • Users
  • Category
  • Product
  • ProductDetail
  • Supplier
  • StockLog

Security and Role Access

SecurityConfig uses URL-based authorization, method security (@PreAuthorize), HTTP Basic (API tools), and form login/logout (browser UI).

  • Public:
    • GET /
    • GET /login
    • GET /error
    • Static assets (/css/**, /js/**, /images/**)
  • API access:
    • GET /api/products/**, GET /api/categories/**, GET /api/product-details/**: ADMIN/SELLER/BUYER
    • GET /api/suppliers/**: ADMIN/SELLER
    • GET /api/logs/**: ADMIN
    • Other /api/**: authenticated, then method-level rules apply
  • UI access:
    • /ui/**: authenticated
    • Per-page role checks are enforced with @PreAuthorize

Password encryption is handled using BCryptPasswordEncoder in UserService.registerUser.

Thymeleaf Frontend (Simple UI)

The project includes a basic server-rendered UI using Thymeleaf and @Controller endpoints.

Page Controller

  • PageController serves UI routes under /ui
  • It fetches data through existing services, so REST APIs are not modified

UI Routes

  • GET /login - login page for ADMIN / SELLER / BUYER
  • GET /ui/dashboard - summary counts (products/categories/suppliers)
  • GET /ui/products - product list
  • GET /ui/categories - category list (buyers can access by URL; navbar intentionally hides menu item for buyer)
  • GET /ui/suppliers - supplier list
  • GET /ui/register - user registration form (ADMIN only)
  • POST /ui/register - submit registration form (ADMIN only)
  • POST /logout - logout current user and redirect to login page

Template Files

  • src/main/resources/templates/dashboard.html
  • src/main/resources/templates/products.html
  • src/main/resources/templates/categories.html
  • src/main/resources/templates/suppliers.html
  • src/main/resources/templates/register.html
  • src/main/resources/templates/fragments/navbar.html (shared navbar fragment)

REST API Endpoints

Users

  • POST /api/users/register - register user (ADMIN only)
  • GET /api/users/{username} - get user by username

Categories

  • GET /api/categories - list categories
  • POST /api/categories - create category
  • GET /api/categories/{id} - get category by id
  • PUT /api/categories/{id} - update category
  • DELETE /api/categories/{id} - delete category

Products

  • GET /api/products - list products
  • POST /api/products?categoryId={id} - create product
  • PUT /api/products/{id}/stock?newQuantity={n}&username={user} - update stock and write stock log
  • DELETE /api/products/{id} - delete product

Product Details

  • GET /api/product-details/{id} - get details by id
  • POST /api/product-details - create details

Suppliers

  • GET /api/suppliers - list suppliers
  • POST /api/suppliers - create supplier

Stock Logs

  • GET /api/logs - list stock transaction logs

Exception Handling

GlobalExceptionHandler maps exceptions into consistent JSON error payloads:

  • ResourceNotFoundException -> 404
  • IllegalArgumentException -> 400
  • Generic Exception -> 500

Testing

Test stack:

  • JUnit 5
  • Mockito
  • @WebMvcTest + MockMvc for controller integration-style tests
  • Service-layer unit tests with mocked repositories/dependencies

Current suite (latest local Surefire report):

  • Unit tests (service layer): 28
  • Controller tests (MockMvc/Web layer): 22
  • Integration/other tests: 3
  • Total: 53 tests

Run tests locally:

./mvnw clean test

For Windows PowerShell:

.\mvnw.cmd clean test

Local Setup

Prerequisites

  • Java 21
  • Maven (or use Maven Wrapper)
  • Docker + Docker Compose
  • PostgreSQL (or containerized Postgres from compose)

Environment Variables

Create/update .env:

DB_USER=admin
DB_PASSWORD=adminpassword123
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change-this-in-production

ADMIN_PASSWORD is used for first-time admin bootstrapping. In production, if you rely on auto-creation of the initial admin user, you should set a strong ADMIN_PASSWORD via environment variables (for example, in Render). On first startup, if ADMIN_USERNAME/ADMIN_PASSWORD are set and no ADMIN exists yet, the app auto-creates an ADMIN user with those credentials. If they are not set, the app still starts but you must create an admin user manually.

Start PostgreSQL with Docker Compose

docker compose up -d

Run the application

./mvnw spring-boot:run

PowerShell:

.\mvnw.cmd spring-boot:run

The app reads DB settings from src/main/resources/application.yaml.

Open the simple UI in your browser after starting the app:

http://localhost:8081/

CI Pipeline

GitHub Actions workflow: .github/workflows/ci.yml

What it does:

  1. Triggers on push and pull request
  2. Starts PostgreSQL service container
  3. Sets DB_USER and DB_PASSWORD env vars for tests
  4. Sets up JDK 21
  5. Runs ./mvnw -B clean test

CD Pipeline (Render)

GitHub Actions workflow: .github/workflows/cd.yml

What it does:

  1. Triggers on push to main
  2. Reads deploy hook from GitHub Secret RENDER_DEPLOY_HOOK_URL
  3. Sends a POST request to trigger Render deploy

If RENDER_DEPLOY_HOOK_URL is not configured, the workflow fails with a clear message.

Dockerization Status

Implemented:

  • Dockerfile for Spring Boot app (multi-stage build)
  • compose.yaml with both app and postgres
  • Environment-variable based DB credentials
  • CI workflow (.github/workflows/ci.yml) and CD workflow (.github/workflows/cd.yml)

Run full stack locally with:

docker compose up --build

Render Deployment Status

Live:

Git Workflow (Recommended for Requirement)

  • Long-lived branches: main, develop
  • Short-lived branches: feature/*
  • Open PR from feature -> develop, then develop -> main
  • Protect main and require at least one approval

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages