2

With spring state machine, we have states and events. I could not find any documentation on whether it is possible to attach static data to a state during configuration.

For example, if there are the states S1 and S2

public void configure(StateMachineStateConfigurer<String, String> states) throws Exception  {
    states.withStates()
                .initial("INIT")
                .end("END")
                .state("S1", null, exitAction())
                .state("S2", entryAction());
}

If we could attach static data during the above configuration (like a java Map for example), it could be useful in the actions that are triggered (like entryAction and exitAction above)

I don't know if it is possible to do somehow.

sat
  • 5,489
  • 10
  • 63
  • 81

1 Answers1

5

This is achieved with two objects in the state machine - StateContext and ExtendedState.

StateContext is like a current snapshot of the State Machine - it's passed around in various methods and callbacks, including actions and guards.

ExtendedState is basically a map with variables.

You can get the ExtendedState from the StateContext:

    context.getExtendedState()
        .getVariables().put("mykey", "myvalue");

As it is passed around as part of the context, you can access the ExtendedState in every action, transition, guard etc. The StateMachine object itself also has a getExtendedState() method.

This is the canonical way to pass static data around in the StateMachine.

hovanessyan
  • 30,580
  • 6
  • 55
  • 83
  • I follwed this cto achieve a scenario where Action2 need data from Action1. Is it OK to do that? passing large objects into context? thanks – Pascoal Eddy Bayonne Aug 12 '22 at 09:45
  • @PascoalEddyBayonne as most answers: it depends. How often does that happen (e.g. what's your load on that SM instance?). How large is large? Best way is to measure the mem footprint and do some load testing. Do you have alternatives - e.g. writing that state to in-mem cache or other type of storage in Action1 and retrieving it in Action2? How the 2 approaches compare under load testing that matches your real-world scenario? – hovanessyan Aug 12 '22 at 12:20
  • thanks for quick answers. Well actually what i am doing is using the Actions to do some business-logic. The only question is passing data between Actions. Large object i mean any java Object for example CreateCreditCardRequest which has more objects inside. Let's suppose i want to use CreateCreditCardRequest on Action2 but i need to enrich it with data originated form Action1. Just it. I am using context to pass data (any size of data) between various Actions. What is your advice? Thanks again – Pascoal Eddy Bayonne Aug 12 '22 at 14:23
  • What I've done some years back - similar to your case - is only transfer an identifier pointing to my object in the SM context - and in every event + action in the SM definition - get the identifier - retrieve the object (it was from L1 JPA cache or DB read -depending) - modify the object - persist the object. If I have to do it nowadays I will probably have a stream of events + event log, applying the modification to the object in-mem and persisting the object to storage occasionally. Obviously events will be going into a write-ahead type of event log. – hovanessyan Aug 12 '22 at 18:13