Real-time logistics dashboards built with Spring Boot 4, Spring Data JDBC, Angular 21, and MySQL.
Dashboard screenshot:
Live SSE updates (GIF):
- Backend: Java 25, Spring Boot 4, Spring Data JDBC, Flyway, Caffeine cache
- Frontend: Angular 21 (standalone components), TypeScript, SCSS
- Database: MySQL 8
- CI: GitHub Actions (
sse-apitests +sse-webbuild)
- Lower overhead than polling for near-live dashboard updates.
- Native browser support via
EventSource, with automatic reconnect semantics. - Simple one-way stream model fits operational read dashboards.
- Works efficiently with cached read models (
@Cacheable) that refresh on a fixed cadence.
The backend exposes snapshot and stream endpoints:
GET /api/dashboards/overviewGET /api/dashboards/inventory-alertsGET /api/dashboards/shipment-statusGET /api/dashboards/kpi-trendGET /api/dashboards/stream/overviewGET /api/dashboards/stream/inventory-alertsGET /api/dashboards/stream/shipment-statusGET /api/dashboards/stream/kpi-trendPOST /api/ingestion/shipment-events(idempotent write endpoint)
Versioned aliases are also available for dashboard reads and streams:
GET /api/v1/dashboards/overviewGET /api/v1/dashboards/inventory-alertsGET /api/v1/dashboards/shipment-statusGET /api/v1/dashboards/kpi-trendGET /api/v1/dashboards/stream/overviewGET /api/v1/dashboards/stream/inventory-alertsGET /api/v1/dashboards/stream/shipment-statusGET /api/v1/dashboards/stream/kpi-trendPATCH /api/shipments/{trackingNumber}/status(optimistic locking writes)PATCH /api/v1/shipments/{trackingNumber}/status(versioned alias)
Each SSE stream emits DashboardEventEnvelope payloads with:
stream: stream namesequence: monotonic event sequence numberpayload: current snapshot for that stream
- Core table primary keys use UUID strings (
VARCHAR(36)) for safer distributed write patterns. Idempotency-Keyis supported onPOST /api/ingestion/shipment-events.- Repeating the same idempotency key returns the same
shipmentEventIdwithout inserting duplicates.
shipmentsincludes aversioncolumn.- Status updates require
expectedVersionin the request body. - Update succeeds only when
expectedVersionmatches current DB version. - On stale version, the API returns
409 Conflict.
Example request:
{
"status": "DELIVERED",
"expectedVersion": 0,
"delayed": false
}docker compose up -dcd sse-api
./mvnw spring-boot:runOn Windows:
cd sse-api
.\mvnw.cmd spring-boot:runcd sse-web
npm install
npm startOpen http://localhost:4200.
API defaults are in sse-api/src/main/resources/application.properties and profile files.
Important environment variables:
DB_URL(default:jdbc:mysql://localhost:3306/logistics_dashboards?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC)DB_USER(default:logistics)DB_PASSWORD(default:logistics)APP_CORS_ALLOWED_ORIGINS(default:http://localhost:4200)DASHBOARD_STREAM_INTERVAL_MS(default:5000)DASHBOARD_DEMO_STREAM_ENABLED(default:trueindev,falseotherwise)DASHBOARD_DEMO_STREAM_INTERVAL_MS(default:4000)
When demo stream is enabled, the backend continuously mutates shipment, inventory, and KPI data so SSE dashboards visibly update in real time.
- API tests:
cd sse-api && ./mvnw test - Web build:
cd sse-web && npm run build

