Skip to content

Latest commit

 

History

History
638 lines (485 loc) · 15.1 KB

File metadata and controls

638 lines (485 loc) · 15.1 KB

🚗 Vehicle Service Management System

Java Spring Boot Gradle PostgreSQL H2


📌 Overview

This project is a Spring Boot REST API designed using Clean Architecture principles.

It manages vehicle service operations including customers, vehicles, and service tracking.

The system demonstrates:

  • Layered architecture (Domain → UseCase → Infrastructure → Web)
  • DTO + MapStruct mapping
  • Role-based authorization via interceptors
  • Business rule enforcement in domain models
  • Exception handling with centralized handler
  • Pagination support

📌 Features

  • Customer management (CRUD)
  • Vehicle management (CRUD)
  • Vehicle service tracking (PENDING → IN_PROGRESS → COMPLETED)
  • Automatic next service date calculation
  • Soft delete support using Hibernate
  • Pagination support
  • Role-based access control (ADMIN)
  • Global exception handling
  • Standard API response structure
  • Clean Architecture implementation
  • Swagger API documentation
  • Rich Domain Models

🛠️ Tech Stack

Category Technology
Language Java 21
Framework Spring Boot 3.4
Build Tool Gradle
Database PostgreSQL / H2
ORM Spring Data JPA / Hibernate
Mapping MapStruct
API Docs Springdoc OpenAPI
Security Spring Security
Boilerplate Lombok
Architecture Clean Architecture
Code Analysis SonarQube

🏗️ Architecture Overview

The project follows Clean Architecture:

Controller → UseCase → Domain → Repository Interface
                                 ↓
                          Infrastructure (JPA)

🔧 Dependency Injection Strategy (Loose Coupling)

This project uses explicit Bean Configuration classes instead of relying only on annotations like @Service or @Repository.

This ensures the system remains:

  • Loosely coupled
  • Easily testable
  • Fully aligned with Clean Architecture principles

📌 Why This Approach?

Dependencies are wired manually using:

  • @Configuration
  • @Bean

This allows:

  • UseCase layer to depend only on interfaces
  • Infrastructure layer to provide implementations
  • Easy replacement of components (e.g., switching database)

🏗️ Bean Wiring Example


👤 Customer Module

  • customer usecase bean config
@Configuration
class CustomerBeanConfig {

    @Bean
    CustomerUseCase customerUseCase(CustomerRepository customerRepository) {
        return new CustomerUseCaseImpl(customerRepository);
    }
}
  • customer persistence bean config
@Configuration
class CustomerPersistenceBeanConfig {

    @Bean
    CustomerRepository customerRepository(
            JpaCustomerRepository jpaCustomerRepository,
            CustomerPersistenceMapper customerPersistenceMapper
    ) {
        return new CustomerRepositoryImpl(jpaCustomerRepository, customerPersistenceMapper);
    }
}

🚗 Vehicle Module

  • vehicle usecase bean config
@Configuration
class VehicleBeanConfig {

    @Bean
    VehicleUseCase vehicleUseCase(
            VehicleRepository vehicleRepository,
            CustomerRepository customerRepository) {
        return new VehicleUseCaseImpl(vehicleRepository, customerRepository);
    }
}
  • vehicle persistence bean config
@Configuration
class VehiclePersistenceBeanConfig {

    @Bean
    VehicleRepository vehicleRepository(
            JpaVehicleRepository jpaVehicleRepository,
            VehiclePersistenceMapper vehiclePersistenceMapper
    ) {
        return new VehicleRepositoryImpl(jpaVehicleRepository, vehiclePersistenceMapper);
    }
}

🧠 Dependency Flow

UseCase (Business Logic)
        ↓ depends on
Repository Interface
        ↓ implemented by
Infrastructure (JPA)

🚀 Advantages

  • Framework-independent business logic
  • Easier unit testing (mock interfaces)
  • Flexible implementation replacement
  • Strong separation of concerns

💡 Design Note

  • The UseCase layer avoids using @Service to remain framework-independent.

🔄 Request Flow

Client
 ↓
Controller (DTO)
 ↓
Mapper → Domain
 ↓
UseCase
 ↓
Repository Interface
 ↓
Infrastructure (JPA)
 ↓
Database
 ↓
Response (DTO)


📂 Layers Explanation

📌 Domain Layer

Contains core business logic.

Models

  • Customer
  • Vehicle
  • VehicleFuelType (Enum)
  • VehicleServiceStatus (Enum)
  • VehicleUpdateResult

Key Business Logic

  • Next service date = lastServiceDate + 6 months
  • Default vehicle status = PENDING
  • Prevent update if service is COMPLETED

Repositories

  • CustomerRepository
  • VehicleRepository

📌 UseCase Layer

Handles application logic.

CustomerUseCase

  • Get all customers
  • Save customer
  • Update customer
  • Delete customer

VehicleUseCase

  • Get all vehicles
  • Register vehicle
  • Update vehicle
  • Delete vehicle

Rules

  • Customer must exist before assigning vehicle
  • Inprogress or Completed vehicles cannot be updated or deleted
  • Service date auto-calculated
  • Default update vehicle service status as PENDING
  • Register new vehicle should have customer ID along with registration

📌 Infrastructure Layer

Handles database operations.

Customer

  • CustomerEntity
  • JpaCustomerRepository
  • CustomerRepositoryImpl
  • CustomerPersistenceMapper

Vehicle

  • VehicleEntity
  • JpaVehicleRepository
  • VehicleRepositoryImpl
  • VehiclePersistenceMapper

📌 Web Layer

Handles HTTP requests.

Controllers

  • CustomerController
  • VehicleController

DTOs

  • CustomerRequestDTO / CustomerResponseDTO
  • VehicleRequestDTO / VehicleResponseDTO / VehicleShortInfoDTO

Mappers

  • CustomerWebMapper
  • VehicleWebMapper

Interceptors

  • CustomerInterceptor
  • VehicleInterceptor

📌 Security

  • Spring Security configured
  • CSRF disabled
  • Swagger endpoints allowed
  • Role-based control via interceptors

📌 Global Handling

Exception Handling

Handled using:

- ResourceNotFoundException → 404
- ServiceAlreadyCompletedException → 409
- ForbiddenAccessException → 403
- Generic Exception → 500

Standard Response

Fields:

  • statusCode
  • message
  • timestamp
  • data

🚀 Features in Detail

  • Pagination using PageRequest
  • Soft delete using Hibernate
  • DTO mapping using MapStruct
  • Domain-driven business logic
  • Interceptor-based authorization
  • Automatic service scheduling

📂 Project Structure

# 📂 Project Structure


   📁 vehicle_service_system
    ├── 📁 domain                                       @Core Business Logic & Enterprise Rules
    │   ├── 📁 models                                   @Pure Domain Entities (No Framework Logic)
    │   │   ├── Customer.java
    │   │   ├── Vehicle.java
    │   │   ├── VehicleFuelType.java
    │   │   ├── VehicleServiceStatus.java
    │   │   └── VehicleUpdateResult.java
    │   └── 📁 repositories                             @Domain Repository Interfaces (Outbound Ports)
    │       ├── CustomerRepository.java
    │       └── VehicleRepository.java
    │
    ├── 📁 usecase                                      @Application Specific Business Rules
    │   ├── 📁 customer
    │   │   ├── CustomerUseCase.java                    @Inbound Port
    │   │   └── CustomerUseCaseImpl.java                @Business Logic Implementation
    │   └── 📁 vehicle
    │       ├── VehicleUseCase.java
    │       └── VehicleUseCaseImpl.java
    │
    ├── 📁 infrastructure                               @External Frameworks & Tools (Persistence)
    │   ├── 📁 customer
    │   │   ├── 📁 config                               @Dependency Injection Configurations
    │   │   │   ├── CustomerBeanConfig.java
    │   │   │   └── CustomerPersistenceBeanConfig.java
    │   │   └── 📁 persistence
    │   │       ├── 📁 entity                           @Database Entities (JPA)
    │   │       │   └── CustomerEntity.java
    │   │       ├── 📁 jpa                              @Spring Data Repositories
    │   │       │   └── JpaCustomerRepository.java
    │   │       ├── 📁 mapper                           @Persistence Mapping (Domain <-> Entity)
    │   │       │   └── CustomerPersistenceMapper.java
    │   │       └── CustomerRepositoryImpl.java         @Persistence Adapter
    │   └── 📁 vehicle
    │       ├── 📁 config
    │       │   ├── VehicleBeanConfig.java
    │       │   └── VehiclePersistenceBeanConfig.java
    │       └── 📁 persistence
    │           ├── 📁 entity
    │           │   └── VehicleEntity.java
    │           ├── 📁 jpa
    │           │   └── JpaVehicleRepository.java
    │           ├── 📁 mapper
    │           │   └── VehiclePersistenceMapper.java
    │           └── VehicleRepositoryImpl.java
    │
    ├── 📁 web                                          @Entry Points & Delivery (UI/API)
    │   ├── 📁 config                                   @Web MVC Configurations
    │   │   └── WebConfig.java
    │   ├── 📁 customer
    │   │   ├── 📁 controllers                          @REST API Controllers
    │   │   │   └── CustomerController.java
    │   │   ├── 📁 DTOs                                 @Request/Response Data Objects
    │   │   │   ├── CustomerRequestDTO.java
    │   │   │   └── CustomerResponseDTO.java
    │   │   ├── 📁 interceptor                          @Request Pre-processing
    │   │   │   └── CustomerInterceptor.java
    │   │   └── 📁 webMappers                           @Web Mapping (DTO <-> Domain)
    │   │       └── CustomerWebMapper.java
    │   └── 📁 vehicle
    │       ├── 📁 controllers
    │       ├── 📁 DTOs
    │       │   ├── VehicleRequestDTO.java
    │       │   ├── VehicleResponseDTO.java
    │       │   └── VehicleShortInfoDTO.java
    │       ├── 📁 interceptor
    │       └── 📁 webMappers
    │
    ├── 📁 GlobalExceptionHandler                       @Centralized Exception Management
    │   ├── ErrorMessage.java
    │   ├── ForbiddenAccessException.java
    │   ├── GlobalExceptionHandler.java
    │   ├── ResourceNotFoundException.java
    │   └── ServiceAlreadyCompletedException.java
    │
    ├── 📁 GlobalResponseHandler                        @Generic Response Wrapping
    │   └── StandardResponse.java
    │
    ├── 📁 spring_security                              @Security & Access Control
    │   └── SecurityConfig.java
    │
    └── VehicleServiceSystemApplication.java            @Spring Boot Bootstrap Class


⚙️ API Endpoints

👤 Customer APIs

Method Endpoint Description
GET /api/v1/autocare/customers/all Get all customers
POST /api/v1/autocare/customers/register Register customer
PUT /api/v1/autocare/customers/{id} Update customer
DELETE /api/v1/autocare/customers/{id} Delete customer

🚗 Vehicle APIs

Method Endpoint Description
GET /api/v1/autocare/vehicles/all Get all vehicles
POST /api/v1/autocare/vehicles/register Register vehicle
PUT /api/v1/autocare/vehicles/{id} Update vehicle
DELETE /api/v1/autocare/vehicles/{id} Delete vehicle

🔐 Authorization

🔐 Authorization

Action Access
View all customers ADMIN
Delete customer ADMIN
Manage vehicles ADMIN

Header required: role: ADMIN


📚 API Documentation

Swagger UI:

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

OpenAPI JSON:

http://localhost:5000/v3/api-docs

👤 Customer API Example

📥 Sample Request

{
  "customerName": "James Smith",
  "customerPhone": "555-0101",
  "customerEmail": "james.smith@example.com"
}

📤 Sample Response

{
  "statusCode": 200,
  "message": "Customers details fetched successfully",
  "timestamp": "2026-04-27T19:05:11.8739514",
  "data": [
    {
      "customerId": 1,
      "customerName": "James Smith",
      "customerPhone": "555-0101",
      "customerEmail": "james.smith@example.com",
      "vehicles": [
        {
          "vehicleId": 1,
          "vehicleNumber": "NY-7829-K",
          "vehicleModel": "Ford F-150",
          "lastServiceDate": "2024-01-15",
          "nextServiceDate": "2024-07-15",
          "mileage": 15000
        }
      ]
    }
  ]
}

🚗 Vehicle API Example

📥 Sample Request

{
  "vehicleNumber": "CAB-1234",
  "vehicleModel": "Toyota Prius",
  "vehicleFuelType": "HYBRID",
  "mileage": 50000,
  "lastServiceDate": "2025-01-01",
  "customerId": 1
}

📤 Sample Response

{
  "statusCode": 200,
  "message": "Details fetched successfully",
  "timestamp": "2026-04-27T19:16:15.648869",
  "data": [
    {
      "vehicleId": 1,
      "vehicleNumber": "NY-7829-K",
      "vehicleModel": "Ford F-150",
      "vehicleFuelType": "PETROL",
      "lastServiceDate": "2024-01-15",
      "nextServiceDate": "2024-07-15",
      "mileage": 15000,
      "customerId": 1,
      "customerName": "James Smith",
      "vehicleServiceStatus": "COMPLETED"
    }
  ]
}

▶️ How to Run

1. Clone repository

git clone https://github.com/yahan-botheju/vehicle-service-system.git

2. Navigate to project

cd vehicle-service-system

3. Run application

./gradlew bootRun

👨‍💻 Author

Developed as a Clean Architecture practice project focusing on:

  • Real-world backend structure
  • Scalable system design
  • Separation of concerns

⭐ Project Purpose

This project was built to practice:

  • Clean Architecture
  • Spring Boot advanced structuring
  • DTO & mapping strategies
  • Business rule implementation
  • API design best practices
  • Rich Domain Models
  • Standered Error Response

📌 Note

  • This is a learning-focused project, but the architecture is strong enough to evolve into a production-ready system.