I want to go from status REPEATED_EXPORT_TO_A to status EXPORT_TO_A_AGAIN with a delay but action reexportEvent() has not execute. I have the following state machine :
public StateMachineBuilder.Builder<StatusId, ActionId> construct(StateMachineBuilder.Builder<StatusId, ActionId> builder) throws Exception {
builder.configureStates().withStates()
.states(ImmutableSet.of(OBTAINED_BY_B, FOR_EXPORT_TO_A, EXPORTING_TO_A,
EXPORT_TO_A_ERROR, EXPORTING_TO_A_TIMEOUT,
RECEIVED_BY_A, NOT_RECEIVED_BY_A, RECEIVED_A_ERROR, REPEATED_EXPORT_TO_A))
.state(FOR_EXPORT_TO_A, checkPassedAction(), null)
.state(EXPORTING_TO_A, exportedAction(), null)
.choice(EXPORTED_TO_A_OR_NOT)
.choice(EXPORT_TO_A_AGAIN);
builder.configureTransitions().withExternal()
.source(OBTAINED_BY_B).target(FOR_EXPORT_TO_A)
.and().withExternal()
.source(FOR_EXPORT_TO_A).target(EXPORTED_TO_A_OR_NOT)
.and().withChoice()
.source(EXPORTED_TO_A_OR_NOT)
.first(EXPORTING_TO_A, exportingToAGuardSsm)
.last(REPEATED_EXPORT_TO_A)
.and().withExternal()
.source(REPEATED_EXPORT_TO_A)
.target(EXPORT_TO_A_AGAIN)
.event(REEXPORT_TO_A)
.and().withChoice()
.source(EXPORT_TO_A_AGAIN)
.first(EXPORTING_TO_A, exportingToAGuardSsm)
.then(EXPORT_TO_A_ERROR, checkRepeatExportGuard)
.then(REPEATED_EXPORT_TO_A, repeatExportToBGuardSsm)
.last(EXPORT_TO_A_ERROR)
This internal transition for delay
.and().withInternal()
.source(REPEATED_EXPORT_TO_A)
.action(reexportEvent())
.timerOnce(5000)
but this action has not execute
private Action<StatusId, ActionId> reexportEvent() {
//some code
return context -> {
Doc doc = SsmUtil.getDoc(context);
doc.setRepeatCount(doc.getRepeatCount() + 1);
context.getStateMachine().sendEvent(REEXPORT_TO_A);
};
}
There's one key thing to understand for triggers in Spring State Machine - they are associated with a state and you need to remain in that state for the trigger to execute. The delay starts the moment you enter the state - if you exit from the state before the delay time is reached, the trigger does not execute.
Example:
specify a trigger for state "A" with a 5 second delay
enter state "A"
on 2nd second exit state "A"
The trigger will not execute, because you've exited from state "A" before the defined time delay has expired.
Checkout a unit test (TestTriggersDelay) that demos this behavior here.