A practice repository to learn and implement a productionβstyle backend with Spring Boot and a lightweight React frontend playground.
Backend: Spring Boot β’ JWT β’ MySQL β’ Testcontainers β’ Spotless β’ JaCoCo β’ SonarQube β’ Docker β’ AWS EC2 \ Frontend: React + Vite β’ Material UI β’ Axios Interceptors β’ Error Boundary
- π Overview
- π Review
- β¨ Features
- π§° Tech Stack
- ποΈ Repository Structure
- π Quickstart
- π API (sample)
- π₯οΈ Frontend Notes
This project is primarily for learning and handsβon practice. The goal is to build a realistic backend for an authentication/authorization flow and to rehearse essential frontend skills.
- Focus: Spring Boot 3 (Java 17+) with JWTβbased AuthN/AuthZ (login, register, logout, access/refresh token).
- Frontend: Small React app to exercise Axios interceptor auto refresh token, cleanup patterns with
useEffect
, and Error Boundaries. - Infra/Quality: Docker, AWS EC2 deployment, Spotless code format, JaCoCo coverage, Testcontainers for integration tests, SonarQube for static analysis, and JMeter for basic load testing.
β οΈ Since this is a learning project, some tradeβoffs are intentional to demonstrate patterns and alternatives.
π You can view the complete list of issues here: View on GitHub
Issues | Notes |
---|---|
Dev001 β Manager Exception, Normalize Response #1 | Learned to normalize API responses with consistent structure and implement centralized exception handling for better readability and frontend parsing. |
Dev001 β use MapStruct in project #3 | Explored MapStruct library for fast and type-safe object mapping between DTOs and entities, reducing boilerplate getter/setter conversions. |
Dev001 β use BCrypt #5 | Implemented password hashing using BCrypt before saving to the database, improving security for authentication system. |
Dev001 β Issue and verify JWT token #7 | Learned how to generate, sign, and verify JWT tokens to manage authentication and secure API endpoints effectively. |
Dev001 β Spring Security Part 1 (config endpoint) #9 | Configured endpoints and authentication entry points for Spring Security, setting up public/private routes and secure filters. |
Dev001 β Spring Security Part 2 (hasRole / hasAuthority) #11 | Practiced role-based authorization using hasRole() and hasAuthority() annotations in Spring Security. |
Dev001 β Spring Security Part 3 (Pre/Post Authorize) #13 | Learned method-level security with @PreAuthorize and @PostAuthorize for fine-grained access control in service layers. |
Dev001 β Handle Exception with flex http code #17 | Enhanced exception handling to return flexible HTTP status codes and meaningful error messages for frontend clients. |
Dev001 β Role-based authorization , annotation @ManyToMany #19 | Implemented @ManyToMany mapping between users and roles; applied role-based authorization for fine-grained access. |
Dev001 β Validation with custom annotation #21 | Created custom validation annotations and handled constraint messages for cleaner data validation flow. |
Dev001 β Feature Log out with JWT token #23 | Implemented logout feature by invalidating refresh tokens and handling token blacklisting logic. |
Dev001 β Refresh JWT token #25 | Added refresh-token endpoint to issue new access tokens and improve user experience without frequent re-login. |
Dev001 β Unit Test #28 | Practiced writing basic Unit Tests for controllers, services, and repositories using JUnit 5 following Spring Boot testing architecture. |
Dev001 β Integration Test with JaCoCo & TestContainers #31 | Integrated TestContainers for DB testing and JaCoCo for code coverage reports to ensure test quality and maintainability. |
Dev001 β Format code with Spotless #33 | Applied Spotless plugin to format code automatically and maintain consistent code style across the backend project. |
Dev001 β Learn about SonarLint and SonarQube #35 | Explored SonarLint for local static analysis and SonarQube for continuous code quality inspection and maintainability metrics. |
Dev001 β Build FrontEnd for Application (ReactJS) #39 | Developed a lightweight ReactJS frontend for Identify-Service to test authentication and token flows visually. |
Dev001 β Restructure project: backend + frontend folders #37 | Refactored repository structure into clear BACKEND and FRONTEND modules for cleaner project organization. |
Dev001 β Error Boundary , FallbackUI #42 | Implemented React ErrorBoundary and Fallback UI components to handle rendering errors gracefully on the client side. |
Dev001 β Complete Project (feature Login , Logout , Register) #44 | Completed core authentication flow : register, login, logout with JWT and refresh-token handling end-to-end. |
Dev001 β Fix issue Refresh token many time #46 | Fixed Axios interceptor logic to prevent multiple refresh-token calls when several parallel API requests fail due to expired access token. |
Dev001 β use HttpOnly cookie for Refresh, Access Token #48 | Replaced localStorage token storage with HttpOnly cookies for better security against XSS and token theft. |
Dev001 β Unique Field in JPA, concurrent request #50 | Fixed concurrency bug during registration by enforcing unique DB constraints and handling duplicate username exceptions gracefully. |
Dev001 β Learn about profiles and environment variables #52 | Studied Spring Profiles , environment variables , and how to configure dynamic values for multiple deployment environments. |
Dev001 β Build Project #54 | Learned different Spring Boot build formats (Fat JAR, WAR, Native, Docker Image) and chose Fat JAR for deployment simplicity. |
Dev001 β Using Docker #56 | Created Dockerfile , built image, ran and published image to Docker Hub . Fixed build/run issues during containerization process. |
Dev001 β Deploy to EC2 (AWS) #58 | Learned AWS EC2 setup (Ubuntu, Docker, Termius) and deployed Identify-Service container successfully on cloud instance. |
Dev001 β Refactor file structure & dynamic env setup (Spring Profiles) #62 | Refactored project structure, rebuilt image (v0.0.2) using Docker Compose , applied .env configuration for faster setup and deployment across profiles. |
- β User Register / Login / Logout
- π JWT Authentication (Access + Refresh) with rotation & expiry
- π Authorization with roles/permissions (sample endpoints)
- πͺ Optional cookie support for refresh token (HttpOnly, SameSite, Secure)
- π§ͺ Unit + Integration tests (JUnit 5 + Testcontainers)
- π§Ή Spotless formatting, JaCoCo coverage report, SonarQube quality gate
- βοΈ React + Vite + Material UI
- π Axios interceptors (auto attach access token, refresh on 401, singleβflight refresh)
- π§― Error Boundary and fallback UI
- π§Ό
useEffect
cleanup, request cancellation viaAbortController
Languages & Frameworks: Java 17, Spring Boot 3, React, TypeScript/JavaScript, HTML, CSS, Material UI Build & Runtime: Maven, Docker, Docker Compose Database: MySQL (dev via Docker), H2 (tests optional) Testing/QA: JUnit 5, Testcontainers, JaCoCo, SonarQube, Spotless Ops: AWS EC2, JMeter (load testing)
IDENTIFY/
ββ BACKEND/ # Spring Boot 3.x backend
β ββ src/
β β ββ main/java/ # Source code
β β ββ main/resources/ # Config files (application.yml, etc.)
β β ββ test/java/ # Unit & integration tests (Testcontainers, JUnit5)
β β ββ test/resources/
β ββ target/ # Build output (ignored by Git)
β ββ .env # Environment variables for backend
β ββ .env.example # Template for environment configuration
β ββ Dockerfile # Backend Docker build file
β ββ pom.xml # Maven dependencies & plugins
β
ββ FRONTEND/ # React + Vite + Material UI frontend
β ββ public/ # Static assets (favicon, etc.)
β ββ src/ # React components, routes, hooks, etc.
β ββ .env # Environment variables for frontend
β ββ .env.example # Example config for frontend
β ββ index.html # Main HTML entry
β ββ package.json # Frontend dependencies
β ββ yarn.lock # Yarn lock file
β
ββ deploy/ # Deployment configs (local, EC2, etc.)
β ββ docker-compose.yml # Multi-container orchestration (MySQL, backend)
β
ββ .gitattributes # Git attributes
ββ .gitignore # Ignored files and folders
You can run this project in two ways:
- Run everything locally (frontend + backend).
- Run backend via Docker Compose and frontend locally (recommended β since this project focuses on backend development).
Component | Recommended Version | Notes |
---|---|---|
JDK | 17+ | Required for Spring Boot backend |
Maven | 3.9+ | Build backend |
Node.js | 20+ | Run frontend |
Yarn / npm | latest | Install frontend dependencies |
MySQL | 8.0+ | You can use a Docker container like mysql:8.0.43-debian |
Step 1. Navigate to the frontend directory:
cd FRONTEND
Step 2. Install dependencies:
yarn install # or npm install
Step 3. Create a .env
file (based on .env.example
):
VITE_API_ENDPOINT=http://localhost:8080
VITE_AUTH_MODE=JWT
VITE_API_ENDPOINT
if your backend runs on a different host or port.
Step 4. Start the development server:
yarn dev --host
β Frontend will be available at http://localhost:5173
Step 1. Start MySQL:
You can run it via Docker:
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.43-debian
or use a local MySQL installation.
Step 2. Connect with MySQL Workbench or CLI (localhost:3306, user root), then create the database:
CREATE DATABASE identifyDB;
Step 3. Navigate to the backend directory:
cd BACKEND
Step 4. Create a .env
file (based on .env.example
):
SPRING_PROFILES_ACTIVE=dev
SERVER_PORT=8080
DBMS_CONNECTION=jdbc:mysql://localhost:3306/identifyDB
DBMS_USERNAME=root
DBMS_PASSWORD=root
SECRET_KEY="7RNUqJlIkY3IuGxPKbC7GoGDW40BdtEviJxdjqXSCqrptnnqC98+hyRUB87BxzQG"
JWT_ACCESS_EXP_MS=900000
JWT_REFRESH_EXP_MS=1209600000
Step 5. In your SecurityConfig.java
, make sure CORS allows your frontend origin:
corsConfiguration.addAllowedOrigin("http://localhost:5173");
Step 6. Build and run the backend:
mvn clean package -DskipTests
java -jar target/*-SNAPSHOT.jar
β Backend will be available at http://localhost:8080
- Docker Desktop or Docker Engine β₯ v27
- Docker Compose β₯ v2.20
Step 1. Create a .env
file inside the BACKEND
folder (based on .env.example
):
SPRING_PROFILES_ACTIVE=dev
SERVER_PORT=8080
DBMS_CONNECTION=jdbc:mysql://mysql:3306/identifyDB
DBMS_USERNAME=root
DBMS_PASSWORD=root
SECRET_KEY="7RNUqJlIkY3IuGxPKbC7GoGDW40BdtEviJxdjqXSCqrptnnqC98+hyRUB87BxzQG"
JWT_ACCESS_EXP_MS=900000
JWT_REFRESH_EXP_MS=1209600000
Step 2. Navigate to the deploy
folder:
cd deploy
Step 3. Run Docker Compose:
docker compose up -d
Docker will automatically:
- Create a MySQL container (mysql:8.0.43-debian)
- Start identify-service (Spring Boot backend)
- Create a private network and volume (dev001-network, dbdata)
β Once started:
- Backend β http://localhost:8080
- MySQL β localhost:3306
Repeat the frontend setup steps from Option 1 (Steps 1β4).
Ensure your .env
points to the backend API:
VITE_API_ENDPOINT=http://localhost:8080
Service | URL | Notes |
---|---|---|
Frontend (Vite) | http://localhost:5173 | Local dev mode |
Backend (Spring Boot) | http://localhost:8080 | API server |
MySQL | localhost:3306 | Accessible via Workbench |
Docker Network | dev001-network | Shared between backend & DB |
- Use
docker compose logs -f identify-service
to view backend logs. - After updating
.env
, rebuild withdocker compose up -d --build
. - The backend waits until MySQL passes its health check before starting.
POST /api/v1/auth/register # create account
POST /api/v1/auth/login # return access + refresh token
POST /api/v1/auth/refresh-token # rotate access token
POST /api/v1/auth/logout # revoke refresh
- Axios interceptor: attach
Authorization: Bearer <access>
, on 410 (GONE) β queue & refresh once. - Error Boundary: catch render/runtime errors β show fallback with retry.
- Cleanup: cancel pending requests on unmount (
AbortController
).