A full-stack task management application built with Spring Boot 3.3.5 backend and React TypeScript frontend, demonstrating modern enterprise-grade development patterns and best practices.
This project implements a layered architecture following Spring Boot best practices with clear separation of concerns:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Presentation Layer β
β @RestController - HTTP endpoints & request/response β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Service Layer β
β @Service - Business logic & transaction management β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Data Access Layer β
β @Repository - JPA repositories & database operations β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Domain Model β
β @Entity - JPA entities & domain objects β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Spring Boot 3.3.5 - Auto-configuration, embedded server, production-ready features
- Spring Data JPA - Data persistence abstraction with Hibernate ORM
- Spring Web MVC - RESTful web services with annotation-driven controllers
- Java 21 - Latest LTS with modern language features
- PostgreSQL - Production database with ACID compliance
- H2 Database - In-memory database for testing
- Maven - Dependency management and build automation
- React 18.3.1 - Component-based UI library
- TypeScript - Type-safe JavaScript development
- Vite - Fast build tool and development server
- Tailwind CSS - Utility-first CSS framework
- NextUI - Modern React component library
- React Router DOM - Client-side routing
- Axios - HTTP client for API communication
src/main/java/com/testpjt/tasks/
βββ TasksApplication.java # @SpringBootApplication entry point
βββ controllers/ # REST API endpoints
β βββ TaskListController.java # Task list CRUD operations
β βββ TasksController.java # Task CRUD operations (nested resource)
β βββ GlobalExceptionHandler.java # @ControllerAdvice error handling
βββ services/ # Business logic layer
β βββ TaskListService.java # Task list business interface
β βββ TaskService.java # Task business interface
β βββ impl/
β βββ TaskListServiceImpl.java # @Service implementation
β βββ TaskServiceImpl.java # @Service implementation
βββ repositories/ # Data access layer
β βββ TaskListRepository.java # @Repository JPA interface
β βββ TaskRepository.java # @Repository with custom queries
βββ domain/
β βββ entities/ # JPA entities
β β βββ TaskList.java # @Entity with @OneToMany
β β βββ Task.java # @Entity with @ManyToOne
β β βββ TaskStatus.java # Enum (OPEN, CLOSED)
β β βββ TaskPriority.java # Enum (HIGH, MEDIUM, LOW)
β βββ dto/ # Data Transfer Objects
β βββ TaskListDto.java # Record-based DTO
β βββ TaskDto.java # Record-based DTO
β βββ ErrorResponse.java # Error response structure
βββ mappers/ # Entity-DTO conversion
βββ TaskListMapper.java # Mapping interface
βββ TaskMapper.java # Mapping interface
βββ impl/
βββ TaskListMapperImpl.java # @Component mapper
βββ TaskMapperImpl.java # @Component mapper
src/
βββ main.tsx # Application entry point
βββ App.tsx # Root component
βββ AppProvider.tsx # Context providers
βββ components/ # React components
β βββ TaskListsScreen.tsx # Task lists view
β βββ TasksScreen.tsx # Tasks view
β βββ CreateUpdateTaskListScreen.tsx # Task list form
β βββ CreateUpdateTaskScreen.tsx # Task form
βββ domain/ # TypeScript types
βββ TaskList.ts # Task list interface
βββ Task.ts # Task interface
βββ TaskStatus.ts # Status enum
βββ TaskPriority.ts # Priority enum
- @SpringBootApplication enables auto-configuration, component scanning, and configuration
- Constructor-based dependency injection for immutable dependencies
- @Service, @Repository, @Component annotations for Spring container management
@Repository
public interface TaskRepository extends JpaRepository<Task, UUID> {
List<Task> findByTaskListId(UUID taskListId); // Query by method name
Optional<Task> findByTaskListIdAndId(UUID taskListId, UUID id); // Composite queries
}@RestController
@RequestMapping(path = "/api/task-lists/{task_list_id}/tasks") // Nested resource pattern
public class TasksController {
@GetMapping // GET /api/task-lists/{id}/tasks
@PostMapping // POST /api/task-lists/{id}/tasks
@GetMapping("/{task_id}") // GET /api/task-lists/{id}/tasks/{taskId}
@PutMapping("/{task_id}") // PUT /api/task-lists/{id}/tasks/{taskId}
@DeleteMapping("/{task_id}") // DELETE /api/task-lists/{id}/tasks/{taskId}
}@Entity
@Table(name = "task_lists")
public class TaskList {
@OneToMany(mappedBy = "taskList", cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
private List<Task> tasks;
}
@Entity
@Table(name = "tasks")
public class Task {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "task_list_id")
private TaskList taskList;
}@Service
public class TaskServiceImpl implements TaskService {
@Override
@Transactional // Declarative transaction management
public void deleteTask(UUID taskListId, UUID taskId) {
// Atomic operation with automatic rollback on exceptions
}
}@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({IllegalArgumentException.class})
public ResponseEntity<ErrorResponse> handleExceptions(RuntimeException ex, WebRequest request) {
// Centralized error handling with consistent response format
}
}- application.properties for environment-specific configuration
- Profile-based configuration (development vs. test)
- PostgreSQL for production, H2 for testing
GET /api/task-lists- List all task listsPOST /api/task-lists- Create a new task listGET /api/task-lists/{id}- Get task list by IDPUT /api/task-lists/{id}- Update task listDELETE /api/task-lists/{id}- Delete task list
GET /api/task-lists/{listId}/tasks- List tasks in a task listPOST /api/task-lists/{listId}/tasks- Create task in task listGET /api/task-lists/{listId}/tasks/{taskId}- Get specific taskPUT /api/task-lists/{listId}/tasks/{taskId}- Update taskDELETE /api/task-lists/{listId}/tasks/{taskId}- Delete task
CREATE TABLE task_lists (
id UUID PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
created TIMESTAMP NOT NULL,
updated TIMESTAMP NOT NULL
);CREATE TABLE tasks (
id UUID PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
due_date TIMESTAMP,
status VARCHAR(20) NOT NULL, -- OPEN, CLOSED
priority VARCHAR(20) NOT NULL, -- HIGH, MEDIUM, LOW
task_list_id UUID REFERENCES task_lists(id),
created TIMESTAMP NOT NULL,
updated TIMESTAMP NOT NULL
);This project includes visual documentation diagrams:
- Java 21+
- Node.js 18+
- PostgreSQL 12+
- Maven 3.6+
cd server
# Configure database in application.properties
spring.datasource.url=jdbc:postgresql://localhost:5433/postgres
spring.datasource.username=postgres
spring.datasource.password=your_password
# Run the application
./mvnw spring-boot:run
# Or build and run JAR
./mvnw clean package
java -jar target/tasks-0.0.1-SNAPSHOT.jarcd client
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build# Backend
cd server
docker-compose up -d
# Frontend
cd client
docker-compose up -dcd server
./mvnw test # Run all tests
./mvnw test -Dtest=TaskServiceTest # Run specific test classcd client
npm run test # Run Jest tests
npm run test:coverage # Run with coverage- Layered Architecture - Clear separation between controllers, services, and repositories
- Dependency Injection - Constructor injection for immutable dependencies
- Exception Handling - Centralized error handling with
@ControllerAdvice - Data Transfer Objects - Separation of internal entities from API contracts
- Repository Pattern - Spring Data JPA for data access abstraction
- Transaction Management - Declarative transactions with
@Transactional - Configuration Management - Externalized configuration with profiles
- RESTful Design - Proper HTTP methods and status codes
- Validation - Input validation at controller level
- Testing - Separate test configuration with H2 database
./mvnw clean compile # Compile source code
./mvnw test # Run tests
./mvnw package # Create JAR file
./mvnw spring-boot:run # Run application# Create executable JAR with embedded Tomcat
./mvnw clean package -Dmaven.test.skip=true
# Run with production profile
java -jar -Dspring.profiles.active=prod target/tasks-0.0.1-SNAPSHOT.jar- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request



