Implementing an Order State Machine with Spring Statemachine: Concepts, Persistence, and Testing
This article explains the fundamentals of finite state machines, introduces Spring Statemachine, shows how to define states, events, and transitions for an order lifecycle, demonstrates memory and Redis persistence, provides full Java code for controller, service, listeners, and discusses testing, error handling, and AOP logging.
The article begins by defining a state (State) and a finite-state machine (FSM), using a simple automatic door example to illustrate states (open/closed), events, actions, and transitions.
It then outlines the four core concepts of a state machine: State, Event, Action, and Transition.
Next, it introduces Spring Statemachine as a framework for applying state‑machine concepts in Spring applications, listing its main features such as flat and hierarchical state machines, guards, actions, and Redis persistence.
Quick start includes a MySQL table definition for orders and Maven dependencies for spring‑statemachine‑redis and spring‑statemachine‑starter.
Enum definitions for OrderStatus (WAIT_PAYMENT, WAIT_DELIVER, WAIT_RECEIVE, FINISH) and OrderStatusChangeEvent (PAYED, DELIVERY, RECEIVED) are provided.
State machine configuration is shown with a @Configuration class extending StateMachineConfigurerAdapter , configuring initial state, all states, and external transitions for payment, delivery, and receipt.
Persistence is demonstrated in two ways: an in‑memory StateMachinePersister using a HashMap and a Redis‑based persister using RedisStateMachineContextRepository and RedisStateMachinePersister .
Controller layer provides REST endpoints for creating orders, paying, delivering, and receiving, delegating to OrderService .
Service layer contains methods to create an order and to trigger state‑machine events (pay, deliver, receive) via a synchronized sendEvent method that starts the machine, restores persisted state, sends the event, and persists the new state.
Listeners annotated with @OnTransition update the order status in the database and optionally throw exceptions to simulate business errors.
Testing steps show how to create an order and invoke the REST endpoints in sequence, noting that repeated payment attempts raise errors.
Problem analysis reveals that state‑machine exceptions are swallowed, making it impossible to detect failures from sendEvent results.
Solutions include storing execution results in the state machine’s extended state variables, using AOP to capture method outcomes, and customizing the sendEvent logic to check these variables before persisting.
Additional code snippets illustrate a custom @LogResult annotation, an aspect that records success (1) or failure (0) in the extended state, and updated listener methods that use this annotation.
The article concludes with promotional messages and references, but the technical content provides a comprehensive guide to building, persisting, testing, and debugging a Spring Statemachine‑based order workflow.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.