#OnStateChanged for sequential state transitions in spring state machine - spring-statemachine

I want to define a sequential transition for my spring state machine. My state transitions are A -> B -> C. My business case is as below
I have single event E for transition to B from A and there is no event for B to C. I just want to define that if at all I am in B state I should perform the necessary actions and then move to state C without any event.
Below is the code snippet that I am using
transitions.withExternal().source(A).target(B).event(E)
transitions.withExternal().source(B).target(C)
The above transitions are taking state machine to C from A but the below onStateChanged method is first detecting change from B to C and then A to B.
Are the above transitions are correct or do we need other way to define those transitions
#OnStateChanged
public void anyStateChange() {}

Related

How to control the propagation range of signals in a Mode4

How to control the propagation range of signals in a Mode4 instance of the source code provided in OpenCV2X-Mode 4.

How to retry a failed action?

I went through Spring Statemachine documentation but did not find clear answers for some scenarios. I will greatly appreciate if some one can clarify my questions.
Scenario1: How to retry errors related to action failures? Lets say I have the following states S1, S2 and S3 and when we transition from S1 to S2 I want to perform action A2. If action A2 fails I want to retry it with some time intervals. Is that possible using Spring StateMachine?
Consider AWS state machine Step Functions for example. All work in the step functions States are done using Task. And Task can be configured for retry.
transitions
.withExternal()
.source(States.S1)
.target(States.S2)
.event(Events.E1)
.action(action());
Scenario 2: Lets say Statemachine has states S1, S2 and S3. The current state is S2. If the server goes down on startup will the Statemachine execution pick up from where it left off or we will have to do it all over again?
Scenario 3: When a Guard returns false (possibly because of error condition) and prevents a transition what happens next?
How to retry a failed action?
There are two types of actions in Spring State Machine - transition actions and state actions. In scenario 1 you're talking about transition action.
When you specify a transition action, you can also specify an error handler if the action fails. This is clearly documented in the spring state machine documentation.
.withExternal()
.source(States.S1)
.target(States.S2)
.event(Events.E1)
.action(action(), errorAction());
In your errorAction() method you can implement your logic.
Possible options are:
transition to an earlier state and go the same path
transition to a specific state (e.g. retry state) where you can have your retry logic (e.g. Task/Executor that retries the action N times, and transition to other states (e.g. action success => go normal flow; action failed after N retries => transition to a failure terminal state)
There's also the official Tasks example, that demonstrates recovery/retry logic (source code).

How to change the target state in a state machine

First, I'm not quite sure whether my case is suitable to use spring state machine.
Here're my case:
I have a big mutable object and a set of logic unit which will manipulate this mutable object in a certain sequence.
For a normal flow: A.exec -> B.exec -> C.exec -> Done
For a bad flow that exception throws from A: A -> Error - > Done (B and C is bypassed)
For a bad flow that exception throws from B: A -> B - > Another Flow
I guess A, B, C could be modeled as a state while an action could be used to perform real biz logic when transit from A to B.
How can I capture possible thrown exception from A and change the target to another state instead of B?
Thanks
Leon
I'd use junction or choice and define guards for outgoing transitions. Something what is discussed in gh240. Then you can catch your exceptions and i.e. store something in an extended state and then from your guards you are free to evaluate different conditions.
Choice is pretty much if/elseif/else structure to define which branch machine will follow for transitions.
There's also deploy sample which is modelled with same concepts.

[BOOST][MSM] Can Guard be a post condition of the Action, instead of precondition

I am new to MSM, and also UML state machine standards as well. I had some state machine design before, using State Design Pattern, but this time I want to learn to use BOOST MSM, instead of cooking things up again.
One thing that really confused me a lot is the Guard. I want to do this, in State S1, I receive a event E1, then perform some Action A1, based on the result of action A1, I should either transit to new State S2, or stay in same state S1.
Using MSM, I cannot specify Guard G1 to be the result of Action A1, as in MSM's concept, G1 is the precondition whether A1 should be executed or not, rather than a result of executing A1.
Two solutions I can think of are:
Introduce a pseudo choice state, post_S1, where in its on_entry I perform the Action A1, and have a guard G1 testing the result of this action, then either go back to S1, or proceed to S2.
// Start Event Action Next Guard
S1 E1 none post_S1 none
post_S1 none none S2 G1
post_S1 none none S1 G1'(which is reverse of G1)
2.
Move Action A1 code to Guard G1 (Afterall, A1 is a function call, which I can make it return boolean). so basically my transition row would be
// Start Event Action Next Guard
S1 E1 none S2 G1=A1
Am I using MSM right? Is there any better practice for solving this problem? In my application, I would have A LOT of these pseudo choice states, which I really tries to avoid.
Thanks!
Zongjun
This is what the UML Standard defines, guards are preconditions.
You have several ways to your goal, my personal taste in this case would be:
Within State S1, add an internal transition on event E1.
This transition would have A1 as an action. Within A1, execute the action, then check the result.
If result means "stay where you are", stop
Else call (still within A1) fsm.template process_event(E2); where E2 is a new event moving you to S2.
I suggest this way because it will save you some compile-time, states are expensive ;-)
This is the easiest way. Again, there are others, like using eUML to make A1 return a result, then adding a if_ in the transition table, but this is much more advanced.
HTH,
Christophe
// Start Event Action Next Guard
S1 E1 none S2 Result_of_A1
Inside the Guard function itself, we are performing the action A1, then returning True or False based on A1's result. This way, if guard is false, then stay in S1; otherwise, move to S2.
This saves the pseudo choice state, which is useful but if there are a lot of states where its transition to next state is a "post condition" rather than "pre condition", then there will be lots of these pseudo choice states inside the transition table. Compared to the above transition table, it is more messy.

Handling Events in a State Machine

I have a state machine for my npcs that is structured like the following,
execute state
[[[pred1 pred2....] state1]
[[pred3 pred4....] state2]
[[pred5 pred6....] staten]]
What happens is after current state completes, it starts iterating through the states/predicates list and as soon as a list of predicates that returns all true it will jump to the state that it is associated with.
Certain events can happen during all states, say player commands npc to go somewhere. Just like any other state transition I can check for a predicate and change state but adding the same piece of code to every state seems a bit lame. So I was wondering how people deal with events in state machines?
Just make a data structure like:
state1 -> event1, event2
state2 -> event1
state3 -> event2, event3
By the way, what you have outlined doesn't look like a state machine. In state machine, next state depends on the previous one, so it would look like:
[state1, condition1] -> state2
[state1, condition2] -> state3
...
(condition is your set of predicates). You must also somehow assure that the transition is unique, i.e. that condition1 and condition2 cannot be fulfilled at the same time. Or take the first one which is true.
Try to use pattern called "State" - http://en.wikipedia.org/wiki/State_pattern
Define abstract superclass (e.g. class AbsatractState, put there code of methods that common for all states), and all classes that represents real states must been subclassed from it.
When you have a particular action that can be undertaken from all possible states, do as you would do in mathematics : factor it!
i.e : 4*10 + 5*10 + 6*10 + 4*20 + 5*20 + 6*20 = (4+5+6)*(10+20)
i.e : your (oblivion) npc can be sleeping, or at work, or eating. In all three cases, it must react to some events (be talked to, be attacked, ...). Build two FSM : Daily activity = [sleep, work, eat]. Reaction state : {Undisturbed, Talked to, Attacked, ...}. Then forward the events only to the second FSM
And you can keep on factoring FSM, as long as you're factoring independant things. For example, the mood of the npc (happy, neutral, angry, ...) is independant from it's daily activity and its reaction state. I mean "independant" in the sense "the npc can be at work, talked to, and angry, and there's no contradiction". Of course FSM influence each other, npc that are attacked tend to be angry.
So you could add a third FSM for the Mood state, instead of incorporating it in every single node
Use a hierarchical state machine (HSM). HSMs are exactly designed to factor out the common behavior into superstates and make it reusable for all substates. To learn more about HSMs, you can start with the Wikipedia article "UML State Machine" at http://en.wikipedia.org/wiki/UML_state_machine.

Resources