Functional Specifications (In-Scope)
- Strict Finite State Machine: Defines valid transitions between states and throws errors on illegal moves.
- Compensating Saga Transactions: Restores physical stock balances and triggers payment refunds if order flow fails.
- Audit log & Event Stream: Records transitions to build structural tracking logs and emit domain events.
- Idempotency Guarantees: Avoids executing repeat actions for identical status inputs.
Out-of-Scope Boundaries
- Payment Gateway Handshakes: Excludes live Stripe/PayPal API endpoints, utilizing mock decorators.
- Warehousing Carrier Routing: Excludes actual dynamic logistics matching or warehouse pickup slips.
Production reference implementations demonstrating order state validation, audit log capture, and Saga compensations:
// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;
enum OrderStatus {
PLACED,
CONFIRMED,
PACKED,
SHIPPED,
DELIVERED,
CANCELLED,
REFUNDED
}
class OrderItem {
private final String productId;
private final int quantity;
private final double unitPrice;
public OrderItem(String productId, int quantity, double unitPrice) {
this.productId = productId;
this.quantity = quantity;
this.unitPrice = unitPrice;
}
public String getProductId() { return productId; }
public int getQuantity() { return quantity; }
public double getUnitPrice() { return unitPrice; }
}
class Order {
private final String orderId;
private final List<OrderItem> items;
private OrderStatus status;
private final double totalAmount;
public Order(String orderId, List<OrderItem> items) {
this.orderId = orderId;
this.items = items;
this.status = OrderStatus.PLACED;
this.totalAmount = items.stream().mapToDouble(i -> i.getQuantity() * i.getUnitPrice()).sum();
}
public String getOrderId() { return orderId; }
public List<OrderItem> getItems() { return items; }
public OrderStatus getStatus() { return status; }
public double getTotalAmount() { return totalAmount; }
public void setStatus(OrderStatus status) {
this.status = status;
}
}
class InvalidTransitionException extends RuntimeException {
public InvalidTransitionException(String message) {
super(message);
}
}
class OrderEvent {
private final String eventId;
private final String orderId;
private final OrderStatus fromStatus;
private final OrderStatus toStatus;
private final long timestamp;
public OrderEvent(String orderId, OrderStatus fromStatus, OrderStatus toStatus) {
this.eventId = UUID.randomUUID().toString();
this.orderId = orderId;
this.fromStatus = fromStatus;
this.toStatus = toStatus;
this.timestamp = System.currentTimeMillis();
}
public String getEventId() { return eventId; }
public String getOrderId() { return orderId; }
public OrderStatus getFromStatus() { return fromStatus; }
public OrderStatus getToStatus() { return toStatus; }
public long getTimestamp() { return timestamp; }
}
interface OrderEventPublisher {
void publish(OrderEvent event);
}
class AuditLogEntry {
private final String orderId;
private final OrderStatus fromStatus;
private final OrderStatus toStatus;
private final String actor;
private final long timestamp;
public AuditLogEntry(String orderId, OrderStatus fromStatus, OrderStatus toStatus, String actor) {
this.orderId = orderId;
this.fromStatus = fromStatus;
this.toStatus = toStatus;
this.actor = actor;
this.timestamp = System.currentTimeMillis();
}
public String getOrderId() { return orderId; }
public OrderStatus getFromStatus() { return fromStatus; }
public OrderStatus getToStatus() { return toStatus; }
public String getActor() { return actor; }
public long getTimestamp() { return timestamp; }
}
class AuditService {
private final List<AuditLogEntry> logs = new CopyOnWriteArrayList<>();
public void logTransition(String orderId, OrderStatus from, OrderStatus to, String actor) {
logs.add(new AuditLogEntry(orderId, from, to, actor));
}
public List<AuditLogEntry> getLogsForOrder(String orderId) {
List<AuditLogEntry> result = new ArrayList<>();
for (AuditLogEntry entry : logs) {
if (entry.getOrderId().equals(orderId)) {
result.add(entry);
}
}
return result;
}
}
class CompensationService {
public boolean triggerPaymentRefund(String orderId, double amount) {
System.out.println("SAGA COMPENSATOR: Refunding $" + amount + " to customer card for Order ID: " + orderId);
return true;
}
public boolean triggerInventoryRestoration(String orderId, List<OrderItem> items) {
for (OrderItem item : items) {
System.out.println("SAGA COMPENSATOR: Restoring Qty " + item.getQuantity() + " for Product ID: " + item.getProductId());
}
return true;
}
}
class OrderStateMachine {
private final Map<OrderStatus, Set<OrderStatus>> validTransitions = new ConcurrentHashMap<>();
public OrderStateMachine() {
validTransitions.put(OrderStatus.PLACED, Set.of(OrderStatus.CONFIRMED, OrderStatus.CANCELLED));
validTransitions.put(OrderStatus.CONFIRMED, Set.of(OrderStatus.PACKED, OrderStatus.CANCELLED));
validTransitions.put(OrderStatus.PACKED, Set.of(OrderStatus.SHIPPED, OrderStatus.CANCELLED));
validTransitions.put(OrderStatus.SHIPPED, Set.of(OrderStatus.DELIVERED, OrderStatus.CANCELLED));
validTransitions.put(OrderStatus.DELIVERED, Set.of(OrderStatus.REFUNDED));
validTransitions.put(OrderStatus.CANCELLED, Set.of());
validTransitions.put(OrderStatus.REFUNDED, Set.of());
}
public boolean isValidTransition(OrderStatus from, OrderStatus to) {
Set<OrderStatus> allowed = validTransitions.get(from);
return allowed != null && allowed.contains(to);
}
}
class OrderManager {
private final Map<String, Order> orderRepository = new ConcurrentHashMap<>();
private final OrderStateMachine stateMachine;
private final OrderEventPublisher eventPublisher;
private final AuditService auditService;
private final CompensationService compensationService;
public OrderManager(
OrderStateMachine stateMachine,
OrderEventPublisher eventPublisher,
AuditService auditService,
CompensationService compensationService
) {
this.stateMachine = stateMachine;
this.eventPublisher = eventPublisher;
this.auditService = auditService;
this.compensationService = compensationService;
}
public void registerOrder(Order order) {
orderRepository.put(order.getOrderId(), order);
auditService.logTransition(order.getOrderId(), null, OrderStatus.PLACED, "Customer");
}
public synchronized void transitionTo(String orderId, OrderStatus nextStatus, String actor) {
Order order = orderRepository.get(orderId);
if (order == null) {
throw new IllegalArgumentException("Order not found: " + orderId);
}
OrderStatus currentStatus = order.getStatus();
if (currentStatus == nextStatus) {
return;
}
if (!stateMachine.isValidTransition(currentStatus, nextStatus)) {
throw new InvalidTransitionException("Illegal state transition from " + currentStatus + " to " + nextStatus);
}
order.setStatus(nextStatus);
auditService.logTransition(orderId, currentStatus, nextStatus, actor);
OrderEvent event = new OrderEvent(orderId, currentStatus, nextStatus);
eventPublisher.publish(event);
if (nextStatus == OrderStatus.CANCELLED || nextStatus == OrderStatus.REFUNDED) {
compensationService.triggerPaymentRefund(orderId, order.getTotalAmount());
compensationService.triggerInventoryRestoration(orderId, order.getItems());
}
}
}
}
public class Main {
public static void main(String[] args) {
System.out.println("=== JAVA ORDER MANAGEMENT SYSTEM SIMULATION ===");
OrderStateMachine stateMachine = new OrderStateMachine();
AuditService auditService = new AuditService();
CompensationService compensationService = new CompensationService();
OrderEventPublisher publisher = event -> {
System.out.println("🔊 EVENT EMITTED: Order ID " + event.getOrderId() +
" transitioned from " + event.getFromStatus() +
" to " + event.getToStatus());
};
OrderManager manager = new OrderManager(stateMachine, publisher, auditService, compensationService);
List<OrderItem> items = new ArrayList<>();
items.add(new OrderItem("laptop", 1, 1200.0));
items.add(new OrderItem("mouse", 2, 50.0));
Order order = new Order("ORD-12345", items);
manager.registerOrder(order);
System.out.println("Initial Order Status: " + order.getStatus());
System.out.println("Total Amount: $" + order.getTotalAmount());
// Confirmed order
manager.transitionTo("ORD-12345", OrderStatus.CONFIRMED, "Operator");
System.out.println("Current Order Status: " + order.getStatus());
// Attempt invalid transition
try {
System.out.println("\nAttempting illegal transition from CONFIRMED to DELIVERED...");
manager.transitionTo("ORD-12345", OrderStatus.DELIVERED, "Operator");
} catch (InvalidTransitionException e) {
System.out.println("Caught Expected Error: " + e.getMessage());
}
// Cancel order to trigger compensating Saga transactions
System.out.println("\nCancelling order to test compensating transaction...");
manager.transitionTo("ORD-12345", OrderStatus.CANCELLED, "Customer");
System.out.println("Final Order Status: " + order.getStatus());
System.out.println("\nAudit Log History:");
for (AuditLogEntry log : auditService.getLogsForOrder("ORD-12345")) {
System.out.println(" - Status changed from " + log.getFromStatus() +
" to " + log.getToStatus() + " by " + log.getActor());
}
System.out.println("=== END OF JAVA SIMULATION ===");
}
}