Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Expense Tracker API

A secure, multi-user expense tracking REST API with JWT authentication, category-based organization, and real-time filtering/reporting.

Java Spring Boot PostgreSQL Docker

πŸ”— Live API: https://expense-tracker-api-qur3.onrender.com
πŸ“˜ Swagger UI: https://expense-tracker-api-qur3.onrender.com/swagger-ui/index.html

Note

Hosted on Render's free tier: The first request or visiting Swagger UI after a period of inactivity may take 30–50 seconds to respond while the server instance spin-up completes.


Features

  • JWT-Based Authentication: Secure endpoints with user registration, login, and token generation.
  • Category Management: Create, read, update, and delete categories for expense classification.
  • Expense Tracking:
    • Add, update, view, and delete expenses tied directly to the authenticated user.
    • Multi-criteria filtering by category and amount threshold.
    • Paginated retrieval, sorting (ascending/descending by amount), and range-based filtering (by ID).
    • Statistical endpoints like expense counts per category.
  • API Documentation: Built-in interactive API exploration via Springdoc OpenAPI (Swagger UI).
  • Docker Support: Containerized deployment setup using a multi-stage execution model.

Tech Stack

  • Backend Framework: Spring Boot 3.5.6
  • Language: Java 21
  • Security: Spring Security & JSON Web Tokens (jjwt version 0.12.5)
  • Database: PostgreSQL (integrated with Neon Cloud Database)
  • ORM / Persistence: Spring Data JPA & Hibernate
  • API Documentation: Springdoc OpenAPI WebMVC UI (2.8.13)
  • Boilerplate Reduction: Project Lombok
  • Build Tool: Maven

Architecture

Controller ──> Service ──> Repository ──> Database

This application is built adhering to the standard multi-layered architecture guidelines. Controllers receive client HTTP requests, sanitize and validate input payloads using DTO validation constraints, and map them to business processes in the Service layer. The Service layer implements core logical actions and translates entities between client-facing DTO contracts and JPA models. The Repository layer handles DB operations via Spring Data JPA, ensuring clean segregation of concerns.

Key Design Decisions

  • Token-Bound Identity: User identity is derived server-side from the JWT claims β€” never trusted from client input β€” preventing users from accessing, modifying, or deleting other users' data.
  • DTO Decoupling: Data Transfer Objects (DTOs) decouple the API contract from JPA entities, ensuring internal database schema modifications do not break the public-facing API.
  • Centralized Exception Handling: A centralized global exception handler (@ControllerAdvice) intercepts failures and returns structured, standardized JSON error responses instead of raw server stack traces.

Project Structure

expense-tracker/
β”œβ”€β”€ .mvn/                     # Maven wrapper configuration
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main/
β”‚   β”‚   β”œβ”€β”€ java/
β”‚   β”‚   β”‚   └── com/example/expense_tracker/
β”‚   β”‚   β”‚       β”œβ”€β”€ controller/   # REST API controllers
β”‚   β”‚   β”‚       β”œβ”€β”€ dto/          # Data Transfer Objects (DTOs) for requests/responses
β”‚   β”‚   β”‚       β”œβ”€β”€ exception/    # Custom exceptions & global exception handler
β”‚   β”‚   β”‚       β”œβ”€β”€ model/        # JPA Entities (User, Category, Expenses)
β”‚   β”‚   β”‚       β”œβ”€β”€ repository/   # JPA Repositories
β”‚   β”‚   β”‚       β”œβ”€β”€ security/     # Spring Security, JWT filters & config
β”‚   β”‚   β”‚       └── service/      # Business logic implementation
β”‚   β”‚   └── resources/
β”‚   β”‚       └── application.properties  # Database & logging configurations
β”‚   └── test/                 # Test packages
β”œβ”€β”€ Dockerfile                # Docker setup for packaging and running the app
β”œβ”€β”€ pom.xml                   # Maven dependencies and build plugins
└── README.md                 # Project documentation

Getting Started

Prerequisites

  • Java Development Kit (JDK) 21
  • Maven 3.x (or use the included ./mvnw wrapper)
  • A running PostgreSQL instance (local or hosted, e.g. Neon)

Environment Variables

The application can read environment variables to override default database settings dynamically at runtime (useful for deployments on Render or Docker containers):

Environment Variable Description Example Value
JWT_SECRET Secret key used to sign and verify JSON Web Tokens (must be at least 256 bits) mysecretkeymysecretkeymysecretkeymysecretkey123456789
SPRING_DATASOURCE_URL JDBC connection URL for PostgreSQL jdbc:postgresql://ep-db-pooler.aws.neon.tech/expense_tracker?sslmode=require
SPRING_DATASOURCE_USERNAME Username for database access neondb_owner
SPRING_DATASOURCE_PASSWORD Password for database access your_secret_password

Run Locally

  1. Navigate to the project root:
    cd expense-tracker
  2. Build and package the application:
    ./mvnw clean package
  3. Run the Spring Boot application:
    ./mvnw spring-boot:run

The application will start on port 8080 (default) and connect to the configured database.

Run with Docker

  1. Build the Docker Image:
    docker build -t expense-tracker-api .
  2. Run the Container (overriding database properties with environment variables):
    docker run -p 8080:8080 \
      -e JWT_SECRET="your-custom-jwt-secret-key-at-least-256bits-long" \
      -e SPRING_DATASOURCE_URL="jdbc:postgresql://your-db-host/db-name" \
      -e SPRING_DATASOURCE_USERNAME="your-username" \
      -e SPRING_DATASOURCE_PASSWORD="your-password" \
      expense-tracker-api

API Reference

Full interactive docs are available via Swagger UI at: https://expense-tracker-api-qur3.onrender.com/swagger-ui/index.html

Auth (/auth) β€” Public

Method Endpoint Description
POST /auth/register Register a new user with username and password
POST /auth/login Authenticate username/password and receive a JWT token
GET /auth/hello Public heartbeat/health check check (Returns "hello")

Category (/category) β€” Public

Method Endpoint Description
POST /category Create a new category
GET /category Retrieve all categories
GET /category/{id} Get category details by its database ID
PUT /category/{id} Update the name of an existing category
DELETE /category/{id} Remove a category by its ID

Expenses (/api/expenses) β€” πŸ”’ JWT Required

Important

All endpoints under /api/** require the header: Authorization: Bearer <token>

Method Endpoint Description
POST /api/expenses Add a new expense for the authenticated user
GET /api/expenses Get all expenses logged by the authenticated user
GET /api/expenses/search Filter expenses globally by categoryId and/or minimum amount threshold
GET /api/expenses/high-amount Filter expenses with an amount greater than a specified threshold
GET /api/expenses/count Count the total number of expenses under a given category ID
GET /api/expenses/filter Retrieve a paginated list of expenses filtered by category
GET /api/expenses/id-range Retrieve a paginated list of expenses with IDs between id1 and id2
GET /api/expenses/sort Retrieve a paginated, sorted list of user expenses by amount
GET /api/expenses/{id} Get details of a specific expense by ID
PUT /api/expenses/{id} Update an existing expense by ID (must own the resource)
DELETE /api/expenses/{id} Delete an existing expense by ID (must own the resource)

Sample Request/Response

Add Expense (POST /api/expenses)

Headers:

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

Request Body:

{
  "categoryId": 1,
  "amount": 25.50
}

Response (201 Created):

{
  "success": true,
  "message": "Expense Added Successfully!",
  "data": {
    "id": 12,
    "amount": 25.50,
    "category": {
      "id": 1,
      "name": "Food & Dining"
    }
  }
}

Roadmap / What's Next

  • Standardizing Response Envelopes: Adapt category and auth controllers to wrap responses in consistent DTO structures for standard API envelopes.
  • Enhanced Test Coverage: Implement unit and integration tests using Spring Boot Starter Test to assert domain validations.
  • Aggregated Expense Statistics: Introduce additional dashboards/reporting endpoints for monthly budget utilization summaries.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A secure, multi-user expense tracking REST API with JWT authentication, category-based organization, and real-time filtering/reporting.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages