StatefulJ FSM

The StatefulJ FSM is a lightweight Finite State Machine with support for Deterministic and Non-Determinstic Transitions. Stateful FSM is self-contained with minimal dependencies (just SLF4J for a logging facade).

Installation

Install StatefulJ FSM from Maven Central into your app by adding the following to your pom.xml:

<dependency>
	<groupId>org.statefulj</groupId>
	<artifactId>statefulj-fsm</artifactId>
	<version>3.0</version>
</dependency>

Or if you are feeling adventurous, you can download and build the latest from source.

Coding

To use StatefulJ FSM, you build State Models. A State Model is a set of States and Transitions which is associated with a Class. This Class is referred to as the Stateful Entity.

To create a State Model, you will need to:

Define your Stateful Entity

A Stateful Entity is a class that contains a State field which is managed by StatefulJ FSM. The type of the State Field is dependent on the Persister being used. The State field is defined by a @State annotation.


// Stateful Entity
//
public class Foo {

	@State
	String state;   // Memory Persister requires a String
	
	boolean bar;
	
	public String getState() {
		return state;
	}
	
	// Note: there is no setter for the state field 
	//       as the value is set by StatefulJ
	
	public void setBar(boolean bar) {
		this.bar = bar;
	}
	
	public boolean isBar() {
		return bar;
	}
	
}

Define your Events

Events in StatefulJ are Strings.

// Events
//
String eventA = "Event A";
String eventB = "Event B";

Define your States

A State defines the state value for an Entity and holds the mapping of all Transitions for that State.

// States
//
State<Foo> stateA = new StateImpl<Foo>("State A");
State<Foo> stateB = new StateImpl<Foo>("State B");
State<Foo> stateC = new StateImpl<Foo>("State C", true); // End State

Define your Actions

An Action is a Command object.

// Hello <what> Action
//
public class HelloAction<T> implements Action<T> {

	String what;
	
	public HelloAction(String what) {
		this.what = what;
	}

	public void execute(T stateful, 
	                    String event, 
	                    Object ... args) throws RetryException {
		System.out.println("Hello " + what);
	}	
}

// Actions
//
Action<Foo> actionA = new HelloAction("World");
Action<Foo> actionB = new HelloAction("Folks");

Define your Transitions

A Transition is a reaction to an Event directed at a Stateful Entity. The Transition can involve a possible change in State and a possible Action.

Transitions are referred as being either Deterministic or Non-Deterministic:

Transitions are added to a State and are mapped by an Event.

Deterministic Transitions

/* Deterministic Transitions */

// stateA(eventA) -> stateB/actionA
//
stateA.addTransition(eventA, stateB, actionA); 
	
// stateB(eventB) -> stateC/actionB
//
stateB.addTransition(eventB, stateC, actionB);

Non-Deterministic Transitions

/* Non-Deterministic Transitions */

//                   +--> stateB/NOOP  -- loop back on itself
//  stateB(eventA) --|
//                   +--> stateC/NOOP
//
stateB.addTransition(eventA, new Transition<Foo>() {
	
	public StateActionPair<Foo> getStateActionPair(Foo stateful) {
		State<Foo> next = null;
		if (stateful.isBar()) {
			next = stateB;
		} else {
			next = stateC;
		}
		
		// Move to the next state without taking any action
		//
		return new StateActionPairImpl<Foo>(next, null);
	}
});

Define your Persister

A Persister is a Class Responsible for persisting the State value for a Stateful Entity. A Persister implements the Persister interface and must ensure that updates are atomic, isolated and thread-safe. The Stateful FSM library comes with an in-memory Persister which maintains the State only on the in-memory Stateful Entity. If you need to persist to a database, you will need to use one of the Database Persisters or integrate the StatefulJ Framework.

// In-Memory Persister
//
List<State<Foo>> states = new LinkedList<State<Foo>>();
states.add(stateA);
states.add(stateB);
states.add(stateC);

MemoryPersisterImpl<Foo> persister = 
					new MemoryPersisterImpl<Foo>(
											states,   // Set of States 
											stateA);  // Start State

Construct the FSM

The final step is construct the FSM.

// FSM
//
FSM<Foo> fsm = new FSM<Foo>("Foo FSM", persister);

Using the FSM

Now that you have everything set up, you can drive your FSM by calling the onEvent method, passing in the Stateful Entity and the Event

// Instantiate the Stateful Entity
//
Foo foo = new Foo();

// Drive the FSM with a series of events: eventA, eventA, eventA
//
fsm.onEvent(foo, eventA);  // stateA(EventA) -> stateB/actionA

foo.setBar(true);

fsm.onEvent(foo, eventA);  // stateB(EventA) -> stateB/NOOP

foo.setBar(false);

fsm.onEvent(foo, eventA);  // stateB(EventA) -> stateC/NOOP