Reputation: 372
I am trying to create a simple state machine as shown below
For this I have below config
@Override
public void configure(final StateMachineStateConfigurer<States, Events> states) throws Exception {
states
.withStates()
.states(EnumSet.allOf(States.class))
.initial(States.NEW)
.end(States.ERROR)
.end(States.DELIVER);
}
and below transitions
@Override
public void configure(final StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.NEW).target(States.PACKAGED).event(Events.pack)
.and()
.withExternal()
.source(States.PACKAGED).target(States.PROCESS).event(Events.process)
.and()
.withExternal()
.source(States.PACKAGED).target(States.ERROR).event(Events.error)
.and()
.withExternal()
.source(States.PROCESS).target(States.DELIVER).event(Events.deliver)
.and()
.withExternal()
.source(States.PROCESS).target(States.ERROR).event(Events.error);
}
I am trying to right a condition such that when packaging or processing the order, if any error is encountered the state of the order should be error state. I noticed that there are transition action that can be added while configuring the transition as below
public Action<States, Events> packageAction() {
// Packaging logic
if(packed){
return context -> context.getStateMachine().sendEvent(Events.process);
}else{
return context -> context.getStateMachine().sendEvent(Events.error);
}
}
But after running the application it doesn't work. Is this the right way to publish events conditionally?
Upvotes: 0
Views: 1946
Reputation: 896
Its hard to say without seeing the stacktrace, but one thing I noticed in your configuration is that you cannot have two end states since it breaks a Finite State Machine.
Regarding you question about the transition logic, the right way of doing it is with a choice() pseudo state and guards. Guards are interfaces that should contain logic to allow a choice transition to define which state it should enter. In your case, it would be something like this:
@Override
public void configure(final StateMachineStateConfigurer<> states)
throws
Exception {
.withStates()
.states(EnumSet.allOf(States.class))
.initial(States.NEW)
.choice(States.PROCESS)
.end(States.DELIVER);
}
@Override
public void configure(final StateMachineTransitionConfigurer<> transitions)
throws
Exception {
//Configs
.and()
.withChoice()
.source(States.PROCESS)
//you can replace the guard with a lambda expression
//for multiple options, use .then
.first(States.ERROR, hasErrorGuard)
.last(States.DELIVER, successAction, errorAction)
Upvotes: 2