InfoQ Homepage News Spring Releases Version 1.1 Statemachine Framework

# Spring Releases Version 1.1 Statemachine Framework

Spring’s recent release of  their state machine framework, dubbed Statemachine version 1.1, offers a host of new features including:

• Support for Spring Security
• Enhanced integration with @WithStateMachine
• Built-in support for Redis
• Support for UI modeling

According to the Spring Statemachine website, Spring Statemachine “is a framework for application developers to use state machine concepts with Spring applications.” Statemachine includes all of the usual core Spring framework components such as associating beans to a Finite State Machine (FSM) through Spring’s Inversion of Control.

Deploying an FSM in an application is useful where there are a fixed number of states and events that transition from one state to the next.  Statemachine uses triggers based on events or timers to make those transitions.

States and events can be implemented using two data types: String and Enumeration.

As an example, let’s develop a detailed turnstile, with the following state diagram:

In this turnstile FSM, the states are LOCKED and UNLOCKED, the events are InsertToken and PassThru, and the actions are Unlock, Lock, Alarm, and Refund.  The initial state is LOCKED as denoted in the diagram by the inner concentric circle within that state. Initiating the InsertToken event triggers an Unlock action and changes the state from LOCKED to UNLOCKED.  Once in the UNLOCKED state, initiating the PassThru event triggers the Lock action and the state of the turnstile is transitioned back to the LOCKED state.  The actions, Alarm and Refund, do not cause a change in state.

To keep the demo application simple, actions will not be defined.  States and events will be implemented using Enumeration:

static enum States {
LOCKED,
UNLOCKED
}
static enum Events {
INSERTTOKEN,
PASSTHRU
}

The next task is to configure the states and transitions through by defining a Spring @Configuration annotation context in our StateMachineConfigurer interface:

@Configuration
@EnableStateMachine
static class Config extends EnumStateMachineConfigurerAdapter<States,Events> {
@Override
public void configure(StateMachineStateConfigurer<States,Events> states)
throws Exception {
states
.withStates()
.initial(States.LOCKED)
.states(EnumSet.allOf(States.class));
}

@Override
public void configure(StateMachineTransitionConfigurer<States,Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.LOCKED)
.target(States.UNLOCKED)
.event(Events.InsertToken)
.and()
.withExternal()
.source(States.UNLOCKED)
.target(States.LOCKED)
.event(Events.PassThru);
}
}

The @EnableStateMachine annotation signals this context that the turnstile will immediately be built and started.

In this configuration, the initial state, LOCKED, is defined with the statement, states.withStates().initial(States.LOCKED).  Transitions are defined using the methods source(), target(), and event() as shown above.  This series of methods should be defined for all state transitions in an FSM. The method withExternal() is the standard way of changing states.  The method withInternal() would be used if an action does not require a change in state as with Alarm and Refund shown in the diagram.

A StateMachineListener is defined to monitor the turnstile FSM progress:

static class StateMachineListener extends StateMachineListenerAdapter<States,Events> {
@Override
public void stateChanged(State<States,Events> from,State<States,Events> to) {
System.out.println("State changed to: " + to.getId());
}
}

Finally, an instance of StateMachine is created and a run() method is defined to instantiate the listener, start the turnstile FSM, and send events.

@Autowired
StateMachine<States,Events> stateMachine;
@Override
public void run(String... args) throws Exception {
StateMachineListener listener = new StateMachineListener();
stateMachine.addStateListener(listener);
stateMachine.start();
stateMachine.sendEvent(Events.InsertToken);
stateMachine.sendEvent(Events.PassThru);
}

public static void main(String[] args) {
SpringApplication.run(org.redlich.statemachine.DemoApplication.class,args);
}

The entire project can be found on Github. A detailed reference guide can be found on the Spring Statemachine website.

Adoption
Style

## Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

## Community comments

• ##### TLA+

by Jean-Jacques Dubray /

• ##### Re: Java & Spring passion for abstraction

by Oliver Drotbohm /

• ##### TLA+

Your message is awaiting moderation. Thank you for participating in the discussion.

Dr Lamport provided a much better way to model state machines. I would certainly encourage anyone to read this article.

State machines can be described and manipulated with ordinary, everyday mathematics— that is, with sets, functions, and simple logic.

Petri Nets (the semantics we all learned in school) are somewhat of an approximation: actions do not decide of the resulting state. The connection between action and resulting state is "observed".

• ##### Re: Java & Spring passion for abstraction

Your message is awaiting moderation. Thank you for participating in the discussion.

Did you mean Bytebuddy? bytebuddy.net/#/#helloworld

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Is your profile up-to-date? Please take a moment to review and update.

Note: If updating/changing your email, a validation request will be sent

Company name:
Company role:
Company size:
Country/Zone:
State/Province/Region:
You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.