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
- 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
| 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 |
The project follows Clean Architecture:
Controller β UseCase β Domain β Repository Interface
β
Infrastructure (JPA)
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
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)
- 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 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);
}
}UseCase (Business Logic)
β depends on
Repository Interface
β implemented by
Infrastructure (JPA)
- Framework-independent business logic
- Easier unit testing (mock interfaces)
- Flexible implementation replacement
- Strong separation of concerns
- The UseCase layer avoids using @Service to remain framework-independent.
Client
β
Controller (DTO)
β
Mapper β Domain
β
UseCase
β
Repository Interface
β
Infrastructure (JPA)
β
Database
β
Response (DTO)
Contains core business logic.
- Customer
- Vehicle
- VehicleFuelType (Enum)
- VehicleServiceStatus (Enum)
- VehicleUpdateResult
- Next service date = lastServiceDate + 6 months
- Default vehicle status = PENDING
- Prevent update if service is COMPLETED
- CustomerRepository
- VehicleRepository
Handles application logic.
- Get all customers
- Save customer
- Update customer
- Delete customer
- Get all vehicles
- Register vehicle
- Update vehicle
- Delete vehicle
- 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
Handles database operations.
- CustomerEntity
- JpaCustomerRepository
- CustomerRepositoryImpl
- CustomerPersistenceMapper
- VehicleEntity
- JpaVehicleRepository
- VehicleRepositoryImpl
- VehiclePersistenceMapper
Handles HTTP requests.
- CustomerController
- VehicleController
- CustomerRequestDTO / CustomerResponseDTO
- VehicleRequestDTO / VehicleResponseDTO / VehicleShortInfoDTO
- CustomerWebMapper
- VehicleWebMapper
- CustomerInterceptor
- VehicleInterceptor
- Spring Security configured
- CSRF disabled
- Swagger endpoints allowed
- Role-based control via interceptors
Handled using:
- ResourceNotFoundException β 404
- ServiceAlreadyCompletedException β 409
- ForbiddenAccessException β 403
- Generic Exception β 500
Fields:
- statusCode
- message
- timestamp
- data
- Pagination using PageRequest
- Soft delete using Hibernate
- DTO mapping using MapStruct
- Domain-driven business logic
- Interceptor-based authorization
- Automatic service scheduling
# π 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
| 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 |
| 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 |
| Action | Access |
|---|---|
| View all customers | ADMIN |
| Delete customer | ADMIN |
| Manage vehicles | ADMIN |
Swagger UI:
http://localhost:5000/swagger-ui/index.html
OpenAPI JSON:
http://localhost:5000/v3/api-docs
{
"customerName": "James Smith",
"customerPhone": "555-0101",
"customerEmail": "james.smith@example.com"
}
{
"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
}
]
}
]
}{
"vehicleNumber": "CAB-1234",
"vehicleModel": "Toyota Prius",
"vehicleFuelType": "HYBRID",
"mileage": 50000,
"lastServiceDate": "2025-01-01",
"customerId": 1
}
{
"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"
}
]
}git clone https://github.com/yahan-botheju/vehicle-service-system.gitcd vehicle-service-system./gradlew bootRunDeveloped as a Clean Architecture practice project focusing on:
- Real-world backend structure
- Scalable system design
- Separation of concerns
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
- This is a learning-focused project, but the architecture is strong enough to evolve into a production-ready system.