
This project was part of the Sparta Java-Spring Boot Backend Boot Camp
Preview of what I've contributed
- Inventory Concurrency Control: Redis Distributed Lock and Lua Script
- Saga Pattern for Order-Delivery State Management
- RabbitMQ
- Delivery Risk Analysis with Gemini AI Integration
- Slack Webhook Notifications
- Exception Handling & State Validation
🐱 GitHub Link
https://github.com/GT5-LT7/LogiBox

Overview
- A B2B (Business-to-Business) logistics and delivery management system
- Sparta Logistics operates regional hub centers, each storing goods from multiple suppliers/vendors
- Hub restocking from suppliers is out of scope for this project (assumed to happen externally)
- When a delivery request comes in, goods are moved from the source hub to the destination hub and delivered to the final recipient
🖍️ Technical Highlights

- Framework
- Java17, Spring Boot 3.5.14
- Spring Cloud 2025.0.2
- MicroService Architecture
- Service Discovery - Eureka Server
- API Gateway - Spring Cloud Gateway
- Service Communication - OpenFeign
- Distributed Tracing - Zipkin
- Circuit Breaker - Resilience4j
- Asynchronous Communication - RabbitMQ (Spring AMQP)
- Data Layer
- Database - PostgreSQL
- Caching - Redis
- Type-safe dynamic query - QueryDSL
- In-memory database for testing - H2
- Integration test - Testcontainers
- API Integration
- Kakao API
- Gemini API
- Slack Webhook
- Infrastructure / Deployment
- Docker, Docker Compose
- GitHub Actions
Services
- Domain Services
- user-service
- logistics-service
- catalog-service
- order-service
- Infra Components (API Gateway, Eureka Server)
🤹♀️ Team & My Responsibility


We divided responsibilities by domain, with each member responsible for one or more domains. - I'm the highlighted one.
My Code Design & Implementation
Designing the code
Goal
When an order comes in, I wanted the system to predict delivery risks or delays early, so the team could react in time. I used the Gemini API to analyze order and delivery details and automatically generate an estimated delivery time, cost, and risk level.
Design Principles
- Keep each piece doing one job
Instead of putting all the AI logic in one big class, I split it into three focused pieces:AIPromptService— only builds the promptGeminiClient— only calls the external APIAIResponseParser— only parses the responseAIDeliveryAnalysisService— ties these three together
- I split it this way so that if I ever swap Gemini for a different model, or change the prompt, I don't have to touch the other parts of the code.
- Don't trust AI output blindly
AI responses aren't always perfectly formatted. So in the prompt, I explicitly told the model to return JSON only — and as a backup,AIResponseParserstill search for the first{and last}to safely pull out just the JSON, in case extra text sneaks in anyway. - Make every AI call traceable
Since calling an external API can fail, I save anAIRequestLogentry before making the call, just to record that the request happened. After the call, I update that same log with the result — whether it succeeded or failed. This way, I can always look back and see exactly what the AI decided for any given order. - Turn AI insight into a real action
The analysis isn't just stored and forgotten — if the result comes back asHIGHrisk, the system automatically sends an urgent Slack alert. This connects the AI's judgment directly to something the team actually sees and can act on. - Handle failures clearly
API failures and JSON parsing failures each get their own distinctErrorCode, so if something breaks, it's immediately clear where it broke.

Code Implementation
1. Order / Delivery Domain
Inventory Concurrency Control
I implemented locking with SETNX + TTL, and used a Lua script to release the lock only when the value (owner) matches.


Saga Pattern for Order-Delivery State Management
OrderEventProducerpublishesorder.createdandorder.canceledevents

- OrderSagaConsumer listens to the
delivery.created/started/completed/failedqueues to update order state

- On delivery failure, it calls
catalogClient.restoreStock()to roll back inventory. - Compensating transaction.

2. RabbitMQ Configuration
Topic Exchange with routing-key-based queue bindings
I enabled setObservationsEnabled(true) on both the RabbitTemplate and the listener container factory.
=> This solves the common problem of trace context breaking in async messaging. (In this case, it was Zipkin traces propagating across the message queue boundary.)

In addition to the above, I’ve successfully integrated and configured a prompt for Gemini AI to notify delivery men of the shortest routes between hubs.
AIPromptServicetemplates the prompt and enforces a JSON-only response through prompt engineeringAIResponseParsersafely extracts and parses JSON from the AI response, throwing a custom exception on failure- The
AIRequestLogentity logs AI requests/responses to the database for traceability - When the analysis result is
RiskLevel.HIGH, it automatically triggers a Slack urgent-delivery alert — an AI-to-notification integration
You can check the full code below.
LogiBox/…/order/…
🧾📥 You can also download the PDF file (report file) from here.



