Skip to content

Repository files navigation

Product Catalogue

Product management system built as a multi-module Java application. Handles products, categories, stock tracking, price filtering, and role-based administration through a REST API and a server-rendered web interface.

The API serves JSON over HTTP with JWT authentication and OpenAPI documentation. The UI is a separate Spring Boot application that consumes the API and renders Thymeleaf templates with HTMX for dynamic behavior — no JavaScript framework, no build pipeline.

Modules

product-catalogue/
├── pom.xml                         Maven aggregator (builds both modules)
├── docker-compose.yml              All services: db, api, ui
├── start.sh                        Build, start, stop, test script
├── product-catalogue-api/          REST API — Spring Boot, JPA, PostgreSQL
│   └── Dockerfile                  Multi-stage build
└── product-catalogue-ui/           Web UI — Thymeleaf, HTMX, RestClient
    └── Dockerfile                  Multi-stage build

Each module has its own pom.xml with spring-boot-starter-parent. The root POM is an aggregator only — no shared dependencies, no inheritance. Modules build independently or together.

Tech Stack

API (product-catalogue-api)

Component Technology Version
Language Java (OpenJDK Temurin) 21
Framework Spring Boot 3.5.0
Security Spring Security 6.x
JWT JJWT 0.12.6
Persistence Spring Data JPA / Hibernate 6.x
Database PostgreSQL 17
Migrations Flyway managed
DTO Mapping MapStruct 1.6.3
Validation Jakarta Bean Validation 3.x
API Docs SpringDoc OpenAPI (Swagger UI) 2.8.6
Testing JUnit 5, MockMvc 5.12+
Test DB H2 (in-memory) managed

UI (product-catalogue-ui)

Component Technology Version
Language Java (OpenJDK Temurin) 21
Framework Spring Boot 3.5.0
Templating Thymeleaf 3.x
Dynamic behavior HTMX 2.0.4
HTTP Client Spring RestClient 6.x
Typography Cormorant Garamond, DM Sans
Styling Custom CSS (no framework)
Form validation Jakarta Bean Validation 3.x
Testing JUnit 5, MockMvc, Mockito 5.12+

Infrastructure

Component Technology Version
Containers Docker 24.0+
Orchestration Docker Compose 2.20+
Build Maven (wrapper included) 3.9+
Startup start.sh (bash)

Services

Service Port
PostgreSQL 5876 Database
API 8585 REST API, Swagger UI
UI 8586 Web interface

Quick Start

Using start.sh

git clone https://github.com/psandis/product-catalogue.git
cd product-catalogue
./start.sh              # build and start locally (Java 21 required)
./start.sh stop         # stop services
./start.sh status       # check what's running
./start.sh test         # run all 53 tests
./start.sh --help       # show all commands

Docker

./start.sh docker       # or: docker compose up --build
./start.sh docker -d    # detached mode
./start.sh docker-stop  # stop containers

Manual

# API with H2 (no database setup)
cd product-catalogue-api
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev

# UI (separate terminal)
cd product-catalogue-ui
./mvnw spring-boot:run

Open http://localhost:8586. Admin login: admin / admin1234 (seeded in dev profile).

Build

./mvnw package                                  # both modules
./mvnw test                                     # all tests
./mvnw package -pl product-catalogue-api        # api only
./mvnw test -pl product-catalogue-api -Dtest=ProductServiceTest  # single test

API

Swagger UI at http://localhost:8585/swagger-ui.html.

Auth

POST /api/auth/register Create account
POST /api/auth/login Returns JWT

Public

GET /api/products List with filters
GET /api/products/{id} Single product
GET /api/categories All categories
GET /api/categories/{id} Single category
GET /api/categories/{id}/products Products by category

Admin (requires Authorization: Bearer <token>, ADMIN role)

POST /api/admin/products Create product
PUT /api/admin/products/{id} Update product
PATCH /api/admin/products/{id}/stock Update stock
DELETE /api/admin/products/{id} Delete product
POST /api/admin/categories Create category
PUT /api/admin/categories/{id} Update category
DELETE /api/admin/categories/{id} Delete category (fails if products exist)

Filtering

GET /api/products?category=audio&brand=Sony&minPrice=50&maxPrice=300&availability=IN_STOCK&sort=price,asc&page=0&size=20

Parameters: category, brand, minPrice, maxPrice, availability (IN_STOCK / LOW_STOCK / OUT_OF_STOCK), search, page, size, sort.

Web UI

Server-rendered pages. The UI calls the API via RestClient and stores the JWT in the HTTP session.

URL
/ Landing page
/products Product listing with filter sidebar
/products/{id} Product detail
/categories Category listing
/auth/login Sign in
/auth/register Create account
/admin Dashboard with stats, product and category tables
/admin/products/new Create product
/admin/products/{id}/edit Edit product
/admin/categories/new Create category
/admin/categories/{id}/edit Edit category

Custom 404 and 500 error pages are included.

Seed Data

The dev profile seeds the database on startup with:

  • 1 admin user (admin / admin1234)
  • 4 categories (Audio, Computing, Photography, Home)
  • 11 products with real product data, pricing, and stock levels
  • Product images from Pexels (stored in product-catalogue-ui/src/main/resources/static/images/)

Business Rules

  • Unique SKU per product
  • Price must be positive, stock cannot be negative
  • Inactive products excluded from public endpoints
  • Categories cannot be deleted while products are assigned to them
  • Availability derived from stock: 0 = OUT_OF_STOCK, 1–4 = LOW_STOCK, 5+ = IN_STOCK

Architecture

API

com.productcatalogue/
├── config/        SecurityConfig, JwtService, JwtAuthenticationFilter, OpenApiConfig
├── controller/    ProductController, CategoryController, AdminProductController, AuthController
├── dto/request/   ProductCreateRequest, ProductUpdateRequest, StockUpdateRequest, etc.
├── dto/response/  ProductResponse, CategoryResponse, AuthResponse
├── entity/        Product, Category, AppUser, AvailabilityStatus, Role
├── exception/     ResourceNotFoundException, DuplicateResourceException, GlobalExceptionHandler
├── mapper/        ProductMapper, CategoryMapper (MapStruct)
���── repository/    ProductRepository, CategoryRepository, ProductSpecifications
└── service/       ProductService, CategoryService

UI

com.productcatalogue.ui/
├── config/        RestClientConfig, SecurityConfig, ApiProperties
├── controller/    HomeController, ProductViewController, AdminController, AuthViewController
├── dto/           ProductResponse, CategoryResponse, AuthResponse, PageResponse
├── dto/request/   ProductCreateRequest, ProductUpdateRequest, CategoryCreateRequest
├── form/          ProductForm, CategoryForm (Spring MVC form backing)
└── service/       ApiClient

Key Patterns

  • Java records for DTOs
  • JPA Specifications for composable filtering
  • Flyway migrations (no auto-DDL in production)
  • MapStruct (compile-time mapping, no reflection)
  • Stateless JWT on the API, session-based auth on the UI
  • ProblemDetail error responses (RFC 9457)
  • Multi-stage Docker builds
  • Method-level security (@PreAuthorize)
  • BCrypt password hashing

Configuration

Variable Default Module
DB_USERNAME postgres API Database user
DB_PASSWORD postgres API Database password
JWT_SECRET dev default API Signing key (change in production)
API_BASE_URL http://localhost:8585 UI API address

Tests

53 tests across both modules.

./mvnw test

API (19 tests)

ProductServiceTest 8 unit tests Availability logic, duplicate SKU, CRUD
ProductControllerIntegrationTest 10 integration tests Product and category CRUD, auth, validation, conflict handling
ProductCatalogueApiApplicationTests 1 Context loads

UI (34 tests)

Page loading 10 tests Home, products, product detail, categories, login, register, admin pages
Auth flow 5 tests Login success/failure, register success/failure, logout
Admin product CRUD 5 tests Create, edit, delete, validation, form loading
Admin category CRUD 5 tests Create, edit, delete, form loading, redirect without session
Error handling 4 tests API failure graceful degradation, product not found redirect, 404 page
Access control 5 tests Admin pages redirect to login without session

License

MIT

About

Product management system - Java 21, Spring Boot, JWT, Thymeleaf, HTMX, PostgreSQL

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages