Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

66 Commits

Folders and files

Repository files navigation

☁️ CloudTask

CloudTask is a production-oriented RESTful Task Management API built with Spring Boot. It demonstrates how to build, secure, test, containerize, deploy, and monitor a real-world backend application.

The system provides REST APIs for task management, authentication, authorization, audit logging, and administration, with PostgreSQL persistence, Flyway migrations, Docker, GitHub Actions CI/CD, AWS EC2 deployment, Prometheus metrics, and Grafana monitoring.


πŸ“‹ Table of Contents


🎯 Overview

CloudTask is designed as a production-oriented monolithic backend for secure task management.

Core Goals

  • Build a layered Spring Boot REST API
  • Implement secure JWT authentication and authorization
  • Enforce user ownership and data isolation
  • Persist data reliably with PostgreSQL and Flyway
  • Protect APIs with rate limiting
  • Validate behavior with unit and integration testing
  • Automate CI/CD using GitHub Actions
  • Deploy the application to AWS EC2 using Docker Compose
  • Monitor the application using Actuator, Prometheus, and Grafana

πŸ—οΈ Architecture

CloudTask follows a layered architecture with security, persistence, CI/CD, and observability around the application.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        Client           β”‚
β”‚  REST API / Swagger UI  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚ HTTP
             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Spring Boot API       β”‚
β”‚                         β”‚
β”‚ JWT Authentication      β”‚
β”‚ Rate Limit Filter       β”‚
β”‚ Spring Security         β”‚
β”‚ Controllers             β”‚
β”‚ Services                β”‚
β”‚ Repositories            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚         β”‚
        β”‚         └─────────────────────┐
        β–Ό                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    PostgreSQL     β”‚        β”‚ Spring Boot        β”‚
β”‚                   β”‚        β”‚ Actuator / Metrics β”‚
β”‚ JPA / Hibernate   β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ Flyway Migrations β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚    Prometheus      β”‚
                              β”‚ Metric Collection  β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚      Grafana       β”‚
                              β”‚ Monitoring Dashboardβ”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Deployment Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    GitHub    β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GitHub Actions CI    β”‚
β”‚ Build + Test         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚ success
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GitHub Actions CD    β”‚
β”‚ SSH Deployment       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           AWS EC2               β”‚
β”‚                                 β”‚
β”‚        Docker Compose           β”‚
β”‚                                 β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ CloudTask   β”‚ β”‚ PostgreSQL β”‚ β”‚
β”‚ β”‚ API :8080   β”‚ β”‚    :5432   β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚        β”‚                        β”‚
β”‚        β–Ό                        β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Prometheus  β”‚ β”‚  Grafana   β”‚ β”‚
β”‚ β”‚    :9090    β”‚ β”‚   :3000    β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Tech Stack

Category Technology Purpose
Language Java 21 Application development
Backend Spring Boot 3 REST API and application framework
Web Spring Web / Tomcat HTTP and REST endpoints
Security Spring Security Authentication and authorization
Authentication JWT Stateless access-token authentication
Refresh Tokens JWT refresh-token flow Access-token renewal
Password Security BCrypt Password hashing
Database PostgreSQL 18 Persistent relational storage
Persistence Spring Data JPA / Hibernate ORM and data access
Migration Flyway Version-controlled database migrations
Validation Jakarta Validation Request validation
API Documentation OpenAPI / Swagger UI Interactive API documentation
Rate Limiting Bucket4j Per-user token-bucket rate limiting
Audit Logging Custom audit logging User activity and request auditing
Unit Testing JUnit 5 / Mockito Isolated business-logic testing
Integration Testing Spring Boot Test / Testcontainers Full application and database integration testing
Containerization Docker Application containerization
Orchestration Docker Compose Local and EC2 multi-container deployment
CI/CD GitHub Actions Automated build, test, and deployment
Cloud AWS EC2 Application hosting
Monitoring Spring Boot Actuator Health and application metrics
Metrics Micrometer / Prometheus Metrics instrumentation and collection
Visualization Grafana Monitoring dashboards
Build Tool Maven Dependency and build management

✨ Key Features

1. Task Management

  • Create, retrieve, update, and soft-delete tasks
  • Task ownership
  • Task priority and status
  • Pagination
  • Sorting
  • Dynamic filtering using JPA Specifications
  • Search across multiple task fields

2. Authentication & Authorization

  • User registration
  • User login
  • JWT-based authentication
  • Refresh tokens
  • Role-based authorization
  • USER and ADMIN roles
  • BCrypt password hashing
  • Ownership validation for protected resources

3. Security

  • Spring Security
  • JWT authentication filter
  • User ownership enforcement
  • Collection-level task isolation
  • Per-user rate limiting with Bucket4j
  • Correct 401, 403, 404, and 429 HTTP behavior

4. Audit Logging

  • Audit logging for important actions
  • User activity tracking
  • IP address capture
  • User-Agent capture
  • Request context handling

5. Database & Persistence

  • PostgreSQL
  • Spring Data JPA
  • Hibernate
  • Flyway database migrations
  • JPA auditing
  • Soft delete
  • Persistent Docker volume

6. Testing

  • JUnit 5 unit tests
  • Mockito-based service tests
  • Spring Boot integration tests
  • PostgreSQL integration testing with Testcontainers
  • Authentication and JWT integration testing
  • Task ownership and authorization integration testing
  • Rate-limit integration testing
  • Actuator health endpoint testing
  • Meaningful coverage focused on important behavior and security boundaries

7. CI/CD

  • GitHub Actions CI
  • Automated Maven build and test execution
  • Continuous deployment after successful CI
  • SSH-based EC2 deployment
  • git fetch + git reset --hard origin/main
  • Docker Compose rebuild and startup
  • Post-deployment application health checks
  • Deployment failure when the application does not become healthy

8. Observability

  • Spring Boot Actuator
  • /actuator/health
  • /actuator/prometheus
  • Prometheus metric collection
  • Grafana dashboards
  • Application availability monitoring
  • HTTP request-rate monitoring
  • HTTP 5xx error-rate monitoring
  • HTTP response-time monitoring
  • JVM memory and heap monitoring
  • Process CPU monitoring
  • JVM live-thread monitoring
  • Failure and recovery verification

πŸ”§ System Design

Request Flow

Client
  β”‚
  β–Ό
JWT Authentication
  β”‚
  β–Ό
Rate Limit Filter
  β”‚
  β–Ό
Spring Security
  β”‚
  β–Ό
Controller
  β”‚
  β–Ό
Service
  β”‚
  β–Ό
Repository
  β”‚
  β–Ό
PostgreSQL
  β”‚
  β–Ό
HTTP Response

Authentication Flow

Client
  β”‚
  β”œβ”€β”€ POST /auth/register
  β”‚
  └── POST /auth/login
           β”‚
           β–Ό
      Authentication
           β”‚
           β–Ό
      Access Token
           β”‚
           β–Ό
  Authorization: Bearer <JWT>
           β”‚
           β–Ό
      Protected API

Refresh Token Flow

Access Token Expires
        β”‚
        β–Ό
POST /auth/refresh
        β”‚
        β–Ό
Validate Refresh Token
        β”‚
        β–Ό
Issue New Token Pair

Rate Limiting Flow

Authenticated Request
        β”‚
        β–Ό
   RateLimitFilter
        β”‚
        β–Ό
   User ID Bucket
        β”‚
        β–Ό
Token Available?
   β”‚          β”‚
  YES         NO
   β”‚          β”‚
   β–Ό          β–Ό
Continue    HTTP 429
Request     Retry-After

πŸš€ Getting Started

Prerequisites

  • Java 21
  • Docker
  • Docker Compose
  • Git
  • Maven Wrapper included in the project

Clone the Repository

git clone https://github.com/mkalki/cloud-task-api.git
cd cloud-task-api

Environment Variables

Create a .env file in the project root:

POSTGRES_DB=cloudtask
POSTGRES_USER=cloudtask
POSTGRES_PASSWORD=your_database_password

JWT_SECRET=your_long_random_jwt_secret

Never commit .env to GitHub.

Add this to .gitignore:

.env

🐳 Running with Docker

Build and start the application stack:

docker compose up -d --build

Check running containers:

docker compose ps

View CloudTask logs:

docker compose logs app

Stop the stack:

docker compose down

The PostgreSQL data is stored in a persistent Docker volume.

To remove the database volume as well:

docker compose down -v

Warning: docker compose down -v deletes the PostgreSQL volume and its stored database data.


πŸ“š API Documentation

CloudTask uses OpenAPI and Swagger UI for interactive API documentation.

Swagger UI provides:

  • REST endpoint discovery
  • Request and response schemas
  • Interactive endpoint testing
  • JWT authorization support

Local

http://localhost:8080/swagger-ui/index.html

AWS EC2

http://<EC2_PUBLIC_IP>:8080/swagger-ui/index.html

πŸ” REST API

Authentication Endpoints

Method Endpoint Description
POST /auth/register Register a new user
POST /auth/login Authenticate and receive tokens
POST /auth/refresh Refresh an access token

Task Endpoints

Method Endpoint Description
GET /tasks Get tasks belonging to the authenticated user
POST /tasks Create a new task
GET /tasks/{id} Get a task by ID
PUT /tasks/{id} Update a task
DELETE /tasks/{id} Soft-delete a task

Protected endpoints require:

Authorization: Bearer <JWT_TOKEN>

πŸ“ Example Task Request

Create Task

POST /tasks
{
  "title": "Deploy CloudTask",
  "description": "Deploy the application on AWS EC2",
  "priority": "HIGH"
}

Example response:

{
  "id": 1,
  "title": "Deploy CloudTask",
  "description": "Deploy the application on AWS EC2",
  "status": "TODO",
  "priority": "HIGH",
  "ownerId": 1
}

πŸ”Ž Pagination, Filtering & Sorting

CloudTask supports pagination and sorting:

GET /tasks?page=0&size=10

Dynamic filtering is implemented using JPA Specifications.

Supported capabilities:

  • Pagination
  • Sorting
  • Dynamic filtering
  • Searching across multiple task fields

πŸ§ͺ Testing

CloudTask uses both unit testing and integration testing.

Unit Testing

Unit tests focus on isolated service-layer business logic using:

  • JUnit 5
  • Mockito
  • Mocked dependencies
  • Behavior-focused assertions

Integration Testing

Integration tests verify multiple real components working together.

The integration environment includes:

MockMvc
   β”‚
   β–Ό
Spring Security
   β”‚
   β–Ό
Controller
   β”‚
   β–Ό
Service
   β”‚
   β–Ό
Repository
   β”‚
   β–Ό
PostgreSQL Testcontainer

Integration coverage includes:

  • Spring application context loading
  • Authentication and JWT flows
  • Refresh token behavior
  • Logout/token revocation
  • Task ownership
  • Authorization boundaries
  • Collection-level task isolation
  • Unauthenticated access
  • Rate limiting
  • Actuator health

Run the complete test suite:

./mvnw test

The full suite has been verified successfully.


πŸ“ˆ Observability

CloudTask uses Spring Boot Actuator + Micrometer + Prometheus + Grafana.

Actuator

Health endpoint:

http://localhost:8080/actuator/health

Prometheus metrics:

http://localhost:8080/actuator/prometheus

Prometheus

Prometheus scrapes CloudTask every 15 seconds using:

app:8080/actuator/prometheus

Prometheus is available locally at:

http://localhost:9090

Grafana

Grafana reads metrics from Prometheus and provides a monitoring dashboard.

Grafana is available locally at:

http://localhost:3000

Dashboard Panels

The CloudTask dashboard currently includes:

Panel Purpose
CloudTask Availability Detect whether the application is reachable
JVM Memory Usage Monitor JVM memory consumption
HTTP Request Rate Monitor incoming request traffic
HTTP 5xx Error Rate Monitor server-side failures
HTTP Average Response Time Monitor request latency
JVM Heap Usage % Monitor heap utilization
Process CPU Usage % Monitor application CPU consumption
JVM Live Threads Monitor JVM thread count

Observability Architecture

CloudTask
    β”‚
    β–Ό
Spring Boot Actuator
    β”‚
    β–Ό
/actuator/prometheus
    β”‚
    β–Ό
Prometheus
    β”‚
    β–Ό
Grafana
    β”‚
    β–Ό
CloudTask Monitoring Dashboard

Failure and Recovery Verification

The monitoring setup was tested by stopping and restarting the CloudTask application container.

Application Running
        β”‚
        β–Ό
Prometheus up = 1
        β”‚
        β–Ό
Stop CloudTask
        β”‚
        β–Ό
Prometheus up = 0
        β”‚
        β–Ό
Restart CloudTask
        β”‚
        β–Ό
Prometheus up = 1

This verifies that the monitoring system can detect both application failure and recovery.

Dashboard Configuration

The exported Grafana dashboard is stored in:

grafana/dashboards/cloudtask-dashboard.json

Grafana Dashboard

CloudTask Grafana Dashboard - Availability and Traffic

CloudTask Grafana Dashboard - JVM and Application Metrics


πŸ”„ CI/CD

Continuous Integration

GitHub Actions runs the project's automated build and test process.

Git Push
   β”‚
   β–Ό
GitHub Actions CI
   β”‚
   β–Ό
Maven Build + Tests

Continuous Deployment

Successful CI triggers deployment for pushes to main.

Push to main
      β”‚
      β–Ό
CI succeeds
      β”‚
      β–Ό
CD workflow
      β”‚
      β–Ό
SSH to EC2
      β”‚
      β–Ό
git fetch origin
      β”‚
      β–Ό
git reset --hard origin/main
      β”‚
      β–Ό
docker compose up -d --build
      β”‚
      β–Ό
Wait for application startup
      β”‚
      β–Ό
GET /actuator/health
      β”‚
   β”Œβ”€β”€β”΄β”€β”€β”€β”
  UP      FAIL
   β”‚        β”‚
   β–Ό        β–Ό
Success   Deployment fails

The CD workflow also collects Docker status and recent application logs when the health check fails.


☁️ AWS EC2 Deployment

CloudTask is deployed to AWS EC2 using Docker Compose.

Deployment Flow

GitHub
   β”‚
   β–Ό
GitHub Actions
   β”‚
   β–Ό
AWS EC2
   β”‚
   β–Ό
Docker Compose
   β”‚
   β”œβ”€β”€ CloudTask API :8080
   β”œβ”€β”€ PostgreSQL    :5432
   β”œβ”€β”€ Prometheus    :9090
   └── Grafana       :3000

The application is available at:

http://<EC2_PUBLIC_IP>:8080

Swagger UI:

http://<EC2_PUBLIC_IP>:8080/swagger-ui/index.html

The EC2 Security Group must allow the required inbound ports.

The deployment has been verified for:

  • User registration
  • User login
  • JWT authentication
  • Protected REST endpoints
  • Task creation
  • Task updates
  • Task retrieval
  • External access through the EC2 public IP
  • PostgreSQL persistence after Docker restart
  • Post-deployment health verification

πŸ“ Project Structure

cloud-task-api/
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       β”œβ”€β”€ ci.yml
β”‚       └── cd.yml
β”‚
β”œβ”€β”€ grafana/
β”‚   └── dashboards/
β”‚       └── cloudtask-dashboard.json
β”‚
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main/
β”‚   β”‚   β”œβ”€β”€ java/
β”‚   β”‚   β”‚   └── com/
β”‚   β”‚   β”‚       └── mkalki/
β”‚   β”‚   β”‚           └── cloudtaskapi/
β”‚   β”‚   β”‚               β”œβ”€β”€ audit/
β”‚   β”‚   β”‚               β”œβ”€β”€ config/
β”‚   β”‚   β”‚               β”œβ”€β”€ context/
β”‚   β”‚   β”‚               β”œβ”€β”€ controller/
β”‚   β”‚   β”‚               β”œβ”€β”€ dto/
β”‚   β”‚   β”‚               β”œβ”€β”€ entity/
β”‚   β”‚   β”‚               β”œβ”€β”€ exception/
β”‚   β”‚   β”‚               β”œβ”€β”€ ratelimit/
β”‚   β”‚   β”‚               β”œβ”€β”€ repository/
β”‚   β”‚   β”‚               β”œβ”€β”€ security/
β”‚   β”‚   β”‚               β”œβ”€β”€ service/
β”‚   β”‚   β”‚               └── specification/
β”‚   β”‚   β”‚
β”‚   β”‚   └── resources/
β”‚   β”‚       β”œβ”€β”€ application.properties
β”‚   β”‚       └── db/
β”‚   β”‚           └── migration/
β”‚   β”‚
β”‚   └── test/
β”‚
β”œβ”€β”€ compose.yaml
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ prometheus.yml
β”œβ”€β”€ pom.xml
└── README.md

🎯 Interview Talking Points

1. Why a layered architecture?

Layer separation keeps responsibilities focused:

Controller β†’ Service β†’ Repository β†’ Database

This improves maintainability, testability, and separation of concerns.

2. Why JWT?

JWT provides stateless authentication:

  • No server-side HTTP session required
  • Token carries authenticated identity
  • Works well for REST APIs
  • Protected endpoints validate the token before access

3. Why refresh tokens?

Short-lived access tokens reduce exposure if an access token is compromised, while refresh tokens allow clients to obtain new access tokens without forcing frequent login.

CloudTask also supports refresh-token invalidation and reuse protection.

4. Why Testcontainers for integration tests?

Testcontainers allows the integration tests to run against a real PostgreSQL database rather than a mocked database.

This verifies real interactions across:

Application
β†’ JPA
β†’ Hibernate
β†’ PostgreSQL

5. Why meaningful integration testing instead of 100% coverage?

The goal is to cover:

  • Important application behavior
  • Security boundaries
  • Major success paths
  • Important failure paths

Testing every possible parameter combination can increase maintenance cost without proportional value.

6. Why Bucket4j for rate limiting?

CloudTask uses a token-bucket model where each authenticated user gets a bucket keyed by user ID.

User ID
   ↓
Bucket
   ↓
Token available β†’ request allowed
No token       β†’ 429

The production configuration currently allows 100 tokens with a 100-token refill over one minute.

7. Why Prometheus and Grafana?

Prometheus collects and stores numerical application metrics.

Grafana queries Prometheus and turns those metrics into dashboards.

Application
   ↓
Actuator / Micrometer
   ↓
Prometheus
   ↓
Grafana

8. Why health checks in CI/CD?

A successful Docker startup does not necessarily mean the application is ready to serve traffic.

The CD workflow therefore verifies:

Container Started
      ↓
Application Started
      ↓
/actuator/health
      ↓
Deployment Success

πŸš€ Future Enhancements

  • v2: Redis-based priority task scheduler β€” scheduled task execution (September 2026)
  • Nginx + HTTPS β€” reverse proxy, TLS, and domain configuration
  • Advanced observability β€” alerting and production dashboards

πŸ“ License

CloudTask is currently an educational and portfolio-oriented backend project.


πŸ‘€ Author

Mohan R

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages