A simple event-driven system to track delivery trucks in real-time using Spring Boot and RabbitMQ. This project is designed to demonstrate how to build a scalable, decoupled architecture using messaging queues.
The system consists of three distinct Spring Boot applications (or three distinct modules within one app if you prefer to start simple) communicating entirely through RabbitMQ.
- Fleet Simulator (Producer): A scheduled task that generates fake GPS coordinates for delivery trucks and publishes them to the queue.
- Location Preditor: A RESTful API that allows developer to predict the next location of a truck based on its current and past locations for mocking purposes.
- RabbitMQ (Broker): Holds a Topic Exchange named fleet.tracking.exchange.
- Ingestion Worker (Consumer 1): Listens for all location pings, batches them, and saves them to a relational database.
- Geofence Alert Worker (Consumer 2): Listens only for specific regions and triggers an alert if a truck leaves a defined boundary.
- Language & Framework: Java 17+, Spring Boot 4.x, TypeScript, Node.js
- Messaging: Spring Boot Starter AMQP (RabbitMQ)
- Database: PostgreSQL with PostGIS extension for geospatial queries
- Infrastructure: Docker (to run RabbitMQ and PostgreSQL locally without polluting your system).
Every time a truck pings its location, the Producer will send a JSON message. We'll call this the LocationPingedEvent.
Sample JSON Payload
{
"truckId": "TRK-9021",
"region": "sumatra.selatan",
"latitude": -2.9909,
"longitude": 104.7565,
"speedKmh": 55.2,
"timestamp": "2026-03-24T20:21:23Z"
}(Note: These coordinates place the truck right in Palembang. We'll use South Sumatra as our test region.)
Instead of a simple queue, you will configure a Topic Exchange. This allows consumers to subscribe using wildcard routing keys.
- Exchange Name:
fleet.tracking.exchange - Routing Key Format:
region.{region_name}(e.g.,region.sumatra.selatan)
- Role: Emulate 10-20 trucks sending location updates every 5 seconds.
- Implementation: Use Spring's
@Scheduledannotation to create a scheduled task that generates random GPS coordinates within a defined area (e.g., South Sumatra) and publishes them to the RabbitMQ exchange with the appropriate routing key. - Routing: When sending the message, the producer attaches the routing key dynamically based on the truck's current
region (e.g.,
region.sumatra.selatan).
- Role: Provide an endpoint to predict the next location of a truck based on its current and past locations.
- Implementation: Create a REST controller with an endpoint like
/predict/that accepts a truck ID and returns a predicted next location based on simple linear extrapolation of the last few pings.
- Role: The "Source of Truth" recorder.
- Logic:
- Receives
LocationPingEventvia@RabbitListener. - Instead of calling
repository.save()immediately, it adds object to thread-safe batch list. - Every time the list hits 50 items, it performs a bulk insert into the database and clears the batch list.
- Receives
- Database: Use PostgreSQL with PostGIS to store the location data efficiently.
- Role: Real-time monitoring for geofence breaches.
- Logic:
- Listens to the same exchange but with a routing key that matches specific regions (e.g.,
region.sumatra.*). - For each incoming message, it checks if the truck's location is within a predefined geofence (e.g., a polygon around Palembang).
- If a truck leaves the geofence, it logs an alert message (or you can even send an email/notification for extra credit).
- Listens to the same exchange but with a routing key that matches specific regions (e.g.,