- About the Project
- Tech Stack
- Project Structure
- Features
- Getting Started
- API Documentation
- How JWT Works
- Database Schema
- Screenshots
- Author
ExpenseEase is a production-grade RESTful backend system built with Spring Boot that allows users to register, log in with JWT-secured tokens, and fully manage their personal expenses through a clean web dashboard.
This project was built to demonstrate real-world backend architecture skills including:
- Stateless JWT Authentication using Spring Security
- Full CRUD REST API with proper HTTP status codes
- MySQL database with JPA/Hibernate ORM
- DTOs and Repository Pattern for clean architecture
- Global Exception Handling for consistent error responses
- Frontend served from Spring Boot static resources
| Layer | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot 3.3.5 |
| Security | Spring Security + JWT (jjwt 0.12.6) |
| Database | MySQL 8.0 |
| ORM | Spring Data JPA / Hibernate |
| Build Tool | Maven |
| Frontend | HTML5, CSS3, Vanilla JavaScript |
| API Testing | Postman |
| IDE | Eclipse |
| Version Control | Git & GitHub |
expenseease/
├── src/
│ ├── main/
│ │ ├── java/com/expenseease/
│ │ │ ├── ExpenseeaseApplication.java ← App entry point
│ │ │ ├── config/
│ │ │ │ └── SecurityConfig.java ← JWT + Spring Security setup
│ │ │ ├── controller/
│ │ │ │ ├── AuthController.java ← POST /api/auth/register, /login
│ │ │ │ ├── ExpenseController.java ← full CRUD + filter/sort/paginate/summary
│ │ │ │ └── HealthController.java ← GET /api/health
│ │ │ ├── dto/
│ │ │ │ ├── RegisterRequest.java
│ │ │ │ ├── LoginRequest.java
│ │ │ │ ├── AuthResponse.java
│ │ │ │ ├── ExpenseRequest.java
│ │ │ │ ├── ExpenseResponse.java
│ │ │ │ └── ApiResponse.java
│ │ │ ├── entity/
│ │ │ │ ├── User.java ← users table
│ │ │ │ └── Expense.java ← expenses table
│ │ │ ├── exception/
│ │ │ │ ├── GlobalExceptionHandler.java
│ │ │ │ ├── ResourceNotFoundException.java
│ │ │ │ └── BadRequestException.java
│ │ │ ├── repository/
│ │ │ │ ├── UserRepository.java
│ │ │ │ └── ExpenseRepository.java
│ │ │ ├── security/
│ │ │ │ ├── JwtTokenProvider.java ← Generate & validate JWT
│ │ │ │ ├── JwtAuthenticationFilter.java ← Intercepts every request
│ │ │ │ └── CustomUserDetailsService.java
│ │ │ └── service/
│ │ │ ├── AuthService.java ← Registration & login logic
│ │ │ └── ExpenseService.java ← Expense CRUD logic
│ │ └── resources/
│ │ ├── application.properties ← DB + JWT config
│ │ └── static/
│ │ ├── css/
│ │ │ ├── auth.css ← login & register page styles
│ │ │ └── dashboard.css ← all dashboard page styles
│ │ ├── js/
│ │ │ ├── api.js
│ │ │ ├── auth.js ← login / register form submission
│ │ │ ├── modal.js ← add expense modal (shared across pages)
│ │ │ ├── dashboard.js
│ │ │ ├── expenses.js ← live search, filter, pagination
│ │ │ ├── summary.js
│ │ │ └── expense-form.js
│ │ ├── index.html
│ │ ├── register.html
│ │ ├── dashboard.html
│ │ ├── expenses.html
│ │ ├── summary.html
│ │ └── add-expense.html
├── pom.xml ← All Maven dependencies
└── README.md
- User Registration with BCrypt password hashing
- User Login with JWT token response
- All expense endpoints protected — users only see their own data
- Token stored in
localStorage, auto-redirects to dashboard on login - Sign out clears token and redirects to login page
- ➕ Add expense via modal — opens on the same page, no navigation away
- 📋 View all expenses with live search, instant category filter, sort by date or amount
- ✏️ Edit any expense on a dedicated edit page
- 🗑️ Delete with confirmation dialog, list refreshes instantly
- 📄 Pagination — 10 expenses per page with page number buttons
- Total spent (all time), total expense count, this month's total, top category
- Recent 5 expenses with edit and delete actions
- Category breakdown sidebar showing amount per category
- Add Expense button and sidebar link both open the modal — you never leave the page
- Category breakdown cards with animated progress bars and percentage of total
- Monthly trend — all 12 months of the current year as a bar chart, current month highlighted
- Yearly trend — all years of recorded data compared side by side
- Last 12 months breakdown table with expense count per month
- Average expense value across all records
- Dark theme with sidebar navigation
- Add Expense modal available on every page — Dashboard, All Expenses, Summary
- Live search on All Expenses — no Apply button, results update as you type (400ms debounce)
- Fully responsive layout
Make sure you have these installed:
| Tool | Download |
|---|---|
| Java 21 (JDK) | https://adoptium.net/temurin/releases/ |
| Apache Maven | https://maven.apache.org/download.cgi |
| MySQL 8.0 | https://dev.mysql.com/downloads/installer/ |
| Eclipse IDE | https://www.eclipse.org/downloads/ |
1. Clone the repository
git clone https://github.com/asarthak2003/expenseease.git
cd expenseease2. Create MySQL database
CREATE DATABASE expenseease_db;3. Configure application.properties
Open src/main/resources/application.properties and update your MySQL password:
spring.datasource.url=jdbc:mysql://localhost:3306/expenseease_db?createDatabaseIfNotExist=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=YOUR_MYSQL_PASSWORD_HERE4. Run the application
In Eclipse:
- Right-click
ExpenseeaseApplication.java - Select Run As → Java Application
Or via Maven terminal:
mvn spring-boot:run5. Open in browser
http://localhost:8080
The app will auto-create the users and expenses tables on first run. ✅
Full API testing guide with Postman screenshots: see API_TESTING.md
http://localhost:8080
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/auth/register |
Register a new user |
POST |
/api/auth/login |
Login and receive JWT token |
GET |
/api/health |
Health check |
Add header:
Authorization: Bearer <your_jwt_token>
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/expenses |
Create a new expense |
GET |
/api/expenses |
Get all expenses (supports filters) |
GET |
/api/expenses/summary |
Get spending summary & category totals |
GET |
/api/expenses/{id} |
Get one expense by ID |
PUT |
/api/expenses/{id} |
Update an expense |
DELETE |
/api/expenses/{id} |
Delete an expense |
?category=Food
?startDate=2024-01-01&endDate=2024-12-31
1. User logs in → POST /api/auth/login
2. Server validates credentials against MySQL
3. Server generates signed JWT token (24hr expiry)
4. Client stores token in localStorage
5. Every subsequent request sends:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
6. JwtAuthenticationFilter validates the token on every request
7. If valid → request proceeds to controller
8. If invalid/expired → 401 Unauthorized
JWT Structure:
eyJhbGciOiJIUzI1NiJ9 ← Header (algorithm)
.eyJzdWIiOiJ1c2VyQG... ← Payload (email + expiry)
.SflKxwRJSMeKKF2QT4... ← Signature (tamper-proof)
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL, -- BCrypt hashed
role VARCHAR(255) NOT NULL DEFAULT 'ROLE_USER',
created_at DATETIME(6)
);CREATE TABLE expenses (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
category VARCHAR(255) NOT NULL,
date DATE NOT NULL,
description VARCHAR(500),
user_id BIGINT NOT NULL,
created_at DATETIME(6),
updated_at DATETIME(6),
FOREIGN KEY (user_id) REFERENCES users(id)
);Tables are auto-created by Hibernate when the app starts (
ddl-auto=update). No manual SQL needed.
This project includes a complete Postman testing guide. 📄 See API_TESTING.md for:
- Step-by-step Postman request setup
- Request bodies with examples
- Expected response samples
- How to use the JWT token in Postman
Sarthak Agrawal
This project is open source and available under the MIT License.