15. Using Extended State

Let’s assume that we’d need to create a state machine tracking how many times a user is pressing a key on a keyboard and then terminate when keys are pressed 1000 times. Possible but a really naive solution would be to create a new state for each 1000 key presses. Going even worse combinations you might suddenly have astronomical number of states which naturally is not very practical.

This is where extended state variables comes into rescue by not having a necessity to add more states to drive state machine changes, instead a simple variable change can be done during a transition.

StateMachine has a method getExtendedState() which returns an interface ExtendedState which gives an access to extended state variables. You can access variables directly via a state machine or StateContext during a callback from actions or transitions.

public Action<String, String> myVariableAction() {
    return new Action<String, String>() {

        @Override
        public void execute(StateContext<String, String> context) {
            context.getExtendedState()
                .getVariables().put("mykey", "myvalue");
        }
    };
}

If there is a need to get notified for extended state variable changes, there are two options; either use StateMachineListener and listen extendedStateChanged(key, value) callbacks:

public class ExtendedStateVariableListener
        extends StateMachineListenerAdapter<String, String> {

    @Override
    public void extendedStateChanged(Object key, Object value) {
        // do something with changed variable
    }
}

Or implement a Spring Application context listeners for OnExtendedStateChanged. Naturally as mentioned in Chapter 18, Listening State Machine Events you can also listen all StateMachineEvent events.

public class ExtendedStateVariableEventListener
        implements ApplicationListener<OnExtendedStateChanged> {

    @Override
    public void onApplicationEvent(OnExtendedStateChanged event) {
        // do something with changed variable
    }
}