Reputation: 1047
I'm not sure I clearly understand how to use substates. I didn't find any good explained example of correct spring state machine configuration, so I would be glad if somebody can share it we me.
On the picture below there is dummy representation of spring machine i'm currently working on (actual number of states is much bigger). Logically inner states may be grouped into 3 parent states: registration, user configuration and admin configuration.
Question #1. Is this correct usage of substates? I can write it without substates, but I feel like it may and should be grouped. Second picture is a diagram of SM from the spring docs and it looks pretty the same what i have in my own SM: https://docs.spring.io/spring-statemachine/docs/current/reference/index.html#configuring-hierarchical-states
Question #2. There is some output in logs I can't understand.
This is part of my transitions config:
.external(TestState.SELECT_TYPE, TestState.CHOICE_SELECT_TYPE, TestEvent.TYPE_SELECTED)
.choice(
TestState.CHOICE_SELECT_TYPE,
TestState.EMPLOYEE,
TestState.SEARCHER,
registrationStateService::isEmployeeUserTypeSelected
)
.external(
TestState.ADMIN_ROLE,
TestState.ADMIN_SMTH,
TestEvent.ADMIN_ROLE_SELECTED
)
.external(
TestState.ADMIN_SMTH,
TestState.ADMIN_SMTH_ELSE,
TestEvent.ADMIN_SMTH_SELECTED
)
And states config:
.and()
.withStates()
.parent(TestState.ADMIN)
.initial(TestState.ADMIN_ROLE)
So ADMIN is a parent state, and initial state of this submachine is ADMIN_ROLE.
This is the logs of my SM execution:
...
State changed from: FILL_SURNAME to SELECT_TYPE by NAME_FILLED
State entered: SELECT_TYPE
State changed from: SELECT_TYPE to CHOICE_SELECT_TYPE by TYPE_SELECTED
State entered: ADMIN
State changed from: null to ADMIN_ROLE by null
State entered: ADMIN_ROLE
State changed from: ADMIN_ROLE to ADMIN_SMTH by ADMIN_ROLE_SELECTED <-BREAK POINT 1
State entered: ADMIN_SMTH
State changed from: ADMIN_SMTH to ADMIN_SMTH_ELSE by ADMIN_SMTH_SELECTED <-BREAK POINT 2
State entered: ADMIN_SMTH_ELSE
...
I put breakpoints before sending event to state machine. And for the first BP, the result of statemachine.state.id was ADMIN - state that marked as parent. However, before that I see in logs we already entered into ADMIN_ROLE state. Ok, I understood this as state.id is a currentState of main SM. For breakpoint #2, result of statemachine.state.id was ADMIN_SMTH. So the question is, why in case 1 I see state of main state machine, and for case 2 the result is state of submachine? Maybe I did something wrong?
Upvotes: 1
Views: 1791
Reputation: 1863
Now this is not directly an answer to your question but Sub State Machines are mainly is to deal with the following problem which I explained in my blog.
Sub Machines / State Explosion Problem
The main idea, instead of having an one huge State Machine (which is unmaintainable), you divide and conquer your State Machine to smaller ones :)
Upvotes: 0
Reputation: 1067
The top level state machine will only expose top level states. To identify a state within a submachine you must get a reference to it. This technique of accessing the submachine can be found inside the state machine core library abstract method Usage example
/* If we are currently in a submachine */
if (machine.getState().isSubmachineState() && machine.getState().getStates().size() > 0) {
StateMachine<String, String> submachine = ((AbstractState<String, String>) machine.getState()).getSubmachine();
log.info("Submachine state is {}",submachine.getState().getId());
}
Upvotes: 1
Reputation: 1047
Ok, thats because i put:
.states(State.values().toSet())
So my submachine states were duplicated into main machine. And thats why transitions were working unexpectable. Be careful with this.
Upvotes: 0