REST API for managing a vehicle fleet. Handles vehicles, drivers, trips, and maintenance scheduling. Built with Java 17 and Spring Boot 3.
Live demo: (add Railway URL after deploy)
| Layer | Technology |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot 3.2 |
| Security | Spring Security 6 + JWT (jjwt 0.12) |
| ORM | Spring Data JPA + Hibernate |
| Database | PostgreSQL 15 |
| Migrations | Flyway |
| API Docs | SpringDoc OpenAPI / Swagger UI |
| Validation | Bean Validation (jakarta.validation) |
| Build | Maven 3.9 |
| Tests | JUnit 5 + Mockito |
- Auth — login returns a JWT; every other endpoint requires it
- Role-based access — three roles (
ADMIN,DISPATCHER,DRIVER) with different permissions per endpoint - Vehicles — register, update, track status (ACTIVE / IDLE / MAINTENANCE / RETIRED)
- Drivers — manage driver records, license expiry, and vehicle assignments
- Trips — start, close, or cancel a trip; odometer and fuel usage tracked automatically
- Maintenance — schedule and complete service records; a background job runs at 06:00 daily and flags anything overdue
- Analytics — fleet utilization, per-vehicle cost and distance, and per-driver stats
- Consistent error responses — every error comes back as JSON with a status, message, and timestamp
- Swagger UI — interactive docs with Bearer token support at
/swagger-ui.html
Fetching the vehicle list (authenticated)

- Java 17+ (Temurin 17 LTS)
- Maven 3.9+ (download)
- PostgreSQL 15+ (download)
CREATE DATABASE fleet_ops;git clone https://github.com/YOUR_USERNAME/fleet-ops-api.git
cd fleet-ops-apiSet your database credentials as environment variables:
export DB_URL=jdbc:postgresql://localhost:5432/fleet_ops
export DB_USERNAME=postgres
export DB_PASSWORD=yourpasswordOr create src/main/resources/application-local.yml (already in .gitignore):
spring:
datasource:
url: jdbc:postgresql://localhost:5432/fleet_ops
username: your_pg_username
password: your_pg_passwordmvn spring-boot:runFlyway runs on startup and applies both migrations automatically:
V1__init_schema.sql— tables and indexesV2__seed_data.sql— sample users, vehicles, drivers, and trips
http://localhost:8080/swagger-ui.html
All seed users have the password password.
| Username | Role | Access |
|---|---|---|
admin |
ADMIN | Everything |
dispatcher |
DISPATCHER | Trips, driver assignments, fleet view |
driver1 |
DRIVER | Their own trips |
driver2 |
DRIVER | Their own trips |
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "password"}'Pass the returned token as Authorization: Bearer <token> on all subsequent requests.
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/auth/login |
Public | Login, returns JWT |
| POST | /api/auth/register |
ADMIN | Create a new user |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/vehicles |
ADMIN, DISPATCHER | List all vehicles |
| GET | /api/vehicles/{id} |
All roles | Get a vehicle |
| POST | /api/vehicles |
ADMIN | Register a vehicle |
| PUT | /api/vehicles/{id} |
ADMIN | Update a vehicle |
| PATCH | /api/vehicles/{id}/status |
ADMIN, DISPATCHER | Update status |
| DELETE | /api/vehicles/{id} |
ADMIN | Delete a vehicle |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/drivers |
ADMIN, DISPATCHER | List all drivers |
| GET | /api/drivers/active |
ADMIN, DISPATCHER | List active drivers |
| GET | /api/drivers/{id} |
All roles | Get a driver |
| POST | /api/drivers |
ADMIN | Create a driver |
| PUT | /api/drivers/{id} |
ADMIN | Update a driver |
| PATCH | /api/drivers/{id}/assign/{vehicleId} |
ADMIN, DISPATCHER | Assign a vehicle |
| PATCH | /api/drivers/{id}/unassign |
ADMIN, DISPATCHER | Remove assignment |
| DELETE | /api/drivers/{id} |
ADMIN | Deactivate a driver |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/trips |
ADMIN, DISPATCHER | List all trips |
| GET | /api/trips/{id} |
All roles | Get a trip |
| GET | /api/trips/vehicle/{vehicleId} |
ADMIN, DISPATCHER | Trips by vehicle |
| GET | /api/trips/driver/{driverId} |
All roles | Trips by driver |
| POST | /api/trips |
All roles | Start a trip |
| PATCH | /api/trips/{id}/close |
All roles | Close a trip |
| PATCH | /api/trips/{id}/cancel |
ADMIN, DISPATCHER | Cancel a trip |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/maintenance |
ADMIN, DISPATCHER | List all records |
| GET | /api/maintenance/{id} |
ADMIN, DISPATCHER | Get a record |
| GET | /api/maintenance/vehicle/{vehicleId} |
ADMIN, DISPATCHER | Records by vehicle |
| GET | /api/maintenance/overdue |
ADMIN, DISPATCHER | Overdue records |
| GET | /api/maintenance/upcoming?days=7 |
ADMIN, DISPATCHER | Upcoming records |
| POST | /api/maintenance |
ADMIN, DISPATCHER | Schedule maintenance |
| PATCH | /api/maintenance/{id}/complete |
ADMIN, DISPATCHER | Mark complete |
| DELETE | /api/maintenance/{id} |
ADMIN | Delete a pending record |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/analytics/summary |
ADMIN | Fleet-wide summary |
| GET | /api/analytics/vehicles |
ADMIN | Per-vehicle stats |
| GET | /api/analytics/drivers |
ADMIN, DISPATCHER | Per-driver stats |
mvn testUnit tests use Mockito. No database needed.
- Push to GitHub
- Go to railway.app → New Project → Deploy from GitHub
- Add a PostgreSQL plugin
- Set environment variables:
DB_URL=jdbc:postgresql://<host>:5432/<db>
DB_USERNAME=<user>
DB_PASSWORD=<password>
JWT_SECRET=<random base64 string>
PORT=8080
- Railway detects Maven and builds with
mvn package - Swagger UI:
https://your-app.up.railway.app/swagger-ui.html
src/
├── main/java/com/fleetops/
│ ├── config/ # Security, OpenAPI config
│ ├── controller/ # REST controllers
│ ├── dto/
│ │ ├── request/
│ │ └── response/
│ ├── exception/ # Custom exceptions + global handler
│ ├── model/ # JPA entities + enums
│ │ └── enums/
│ ├── repository/ # Spring Data JPA repositories
│ ├── security/ # JWT util, filter, UserDetailsService
│ └── service/ # Business logic
└── main/resources/
├── application.yml
└── db/migration/
├── V1__init_schema.sql
└── V2__seed_data.sql

