Skip to content

A REST API for task management with soft delete functionality and advanced filtering capabilities.

Notifications You must be signed in to change notification settings

JacobSmxth/task-manager-api

Repository files navigation

Task Manager API

A REST API for task management with soft delete functionality and advanced filtering capabilities.

Features

  • CRUD operations for tasks with priority levels (1-10) and categories
  • Partial updates with DTOs: update only the fields you need to change
  • Soft delete: tasks are marked as deleted rather than removed from the database
  • Undo delete functionality by re-calling delete on a soft-deleted task
  • Multi-dimensional filtering: combine category and priority range filters
  • Automatic timestamp tracking for creation, completion, and deletion
  • Toggle task completion status with timestamp recording

Tech Stack

  • Java 21
  • Spring Boot 3.5.6
  • Spring Data JPA
  • H2 Database (file-based persistence)
  • Gradle

Getting Started

Prerequisites

  • Java 21 or higher
  • Gradle (or use included wrapper)

Running the Application

./gradlew bootRun

The API will start on http://localhost:8081

H2 Console

Access the H2 database console at http://localhost:8081/h2-console

  • JDBC URL: jdbc:h2:file:./data/demo
  • Username: sa
  • Password: (leave blank)

API Endpoints

Get Tasks

GET /api/tasks

Query parameters (all optional):

  • category - filter by category
  • higher - minimum priority (inclusive)
  • less - maximum priority (inclusive)

Examples:

  • /api/tasks - all active tasks
  • /api/tasks?category=work - all work tasks
  • /api/tasks?higher=5&less=8 - tasks with priority 5-8
  • /api/tasks?category=personal&higher=7 - personal tasks with priority >= 7

Get Task by ID

GET /api/tasks/{id}

Returns 404 if task doesn't exist or is deleted.

Create Task

POST /api/tasks
Content-Type: application/json

{
  "name": "Task name",
  "category": "work",
  "priority": 5
}

Update Task (Partial Update)

PATCH /api/tasks/{id}
Content-Type: application/json

{
  "name": "Updated task name",
  "category": "personal",
  "priority": 8
}

Partially update a task. All fields are optional - only provide the fields you want to change.

Examples:

  • Update only priority: {"priority": 9}
  • Update name and category: {"name": "New name", "category": "urgent"}
  • Update all fields: {"name": "Complete task", "category": "work", "priority": 10}

Returns 404 if task doesn't exist or is deleted.

Toggle Task Completion

PUT /api/tasks/toggle/{id}

Toggles completion status and sets/clears completedAt timestamp. Returns 400 if task is deleted.

Delete Task (Soft Delete)

DELETE /api/tasks/{id}

Marks task as deleted. Calling delete again on a deleted task will restore it (undo).

Database Schema

Task

  • id - Auto-generated primary key
  • name - Task name (required, not blank)
  • category - Category label (optional)
  • priority - Priority level 1-10 (required)
  • completed - Boolean completion status
  • madeAt - Creation timestamp (auto-set)
  • completedAt - Completion timestamp (set on toggle)
  • deletedAt - Deletion timestamp (null = active)

Architecture

Standard three-layer Spring Boot architecture with DTOs and centralized exception handling:

  • Controller - HTTP request handling and response mapping
  • DTO (Data Transfer Objects) - API contract layer for request/response data
  • Service - Business logic and transaction management
  • Repository - Data access with Spring Data JPA
  • Entity - Domain models mapped to database tables
  • Exception - Custom exceptions with global exception handler

All query methods filter out soft-deleted tasks (deletedAt IS NULL) except for admin recovery endpoints.

Key Implementation Details

Soft Delete Pattern

Tasks are never removed from the database. The deletedAt timestamp marks a task as deleted:

  • null = active task (shown in normal queries)
  • timestamp = deleted task (filtered from normal queries)

Admin methods (findTasksIncludingDeleted, findTaskByIdIncludingDeleted) bypass the filter for recovery scenarios.

DTO Pattern

The API uses Data Transfer Objects (DTOs) for request/response handling:

  • TaskUpdateDTO - Accepts partial updates with optional fields
  • DeleteResponseDTO - Structured response for delete/restore operations
  • Only non-null fields in the DTO are applied to the entity
  • Validation constraints apply only to provided fields
  • Prevents mass assignment vulnerabilities
  • Decouples API contract from database schema

Transaction Management

Write operations use @Transactional to ensure atomicity:

  • Creating tasks
  • Updating tasks (partial or full)
  • Toggling completion
  • Soft delete/restore

Read operations don't require transactions as they don't modify data.

Exception Handling

Centralized exception handling using @RestControllerAdvice:

Custom Exceptions:

  • TaskNotFound - Thrown when task doesn't exist or is deleted (404 Not Found)
  • TaskWasDeleted - Thrown when operations attempted on deleted tasks (400 Bad Request)

Global Exception Handler:

  • Catches and formats all exceptions into consistent JSON responses
  • Includes HTTP status code, error message, and timestamp
  • Handles validation errors from Jakarta Bean Validation
  • Returns first validation error message for cleaner responses

Response Format:

{
  "status": 404,
  "message": "Task not found or has been deleted",
  "timestamp": "2025-10-22T10:30:00"
}

Validation

Multi-layer validation strategy:

Entity-level Validation:

  • @NotBlank on name field
  • @NotNull on priority field
  • @Min(1) and @Max(10) on priority field
  • Custom error messages for better UX

Controller-level Validation:

  • @Valid annotation triggers validation on request bodies
  • Applied to POST (create) and PATCH (update) endpoints
  • Validation errors caught by GlobalExceptionHandler
  • Returns 406 Not Acceptable with validation message

What I Learned

  • Implementing soft delete patterns with recovery functionality
  • Complex Spring Data JPA query method naming conventions
  • Proper service layer transaction boundaries
  • Multi-parameter conditional query routing in controllers
  • RESTful API design with idempotent operations
  • DTO pattern for flexible partial updates with validation
  • Custom exception hierarchy and centralized error handling with @RestControllerAdvice
  • Multi-layer validation strategy with Jakarta Bean Validation
  • Moving business logic from controllers to service layer for better separation of concerns

About

A REST API for task management with soft delete functionality and advanced filtering capabilities.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages