【问题标题】:Spring State Machine - Change state based on conditionsSpring State Machine - 根据条件更改状态
【发布时间】:2021-11-21 06:34:34
【问题描述】:

我正在尝试创建一个简单的状态机,如下所示

为此,我有以下配置

 @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);
}

及以下过渡

@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);
}

我正在尝试纠正一个条件,即在打包或处理订单时,如果遇到任何错误,订单的状态应该是错误状态。 我注意到在配置转换时可以添加转换操作,如下所示

public Action<States, Events> packageAction() {
  // Packaging logic
  if(packed){
    return context -> context.getStateMachine().sendEvent(Events.process);  
  }else{
    return context -> context.getStateMachine().sendEvent(Events.error);
  }
}

但运行应用程序后它不起作用。 这是有条件地发布事件的正确方法吗?

【问题讨论】:

  • 你能发布错误日志吗?

标签: spring spring-boot spring-statemachine


【解决方案1】:

没有看到堆栈跟踪很难说,但我在您的配置中注意到的一件事是您不能有两个最终状态,因为它会破坏有限状态机。

关于转换逻辑的问题,正确的做法是使用choice() 伪状态和守卫。警卫是应该包含逻辑的接口,以允许选择转换来定义它应该进入哪个状态。在你的情况下,它会是这样的:

@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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-23
    • 2021-09-25
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    相关资源
    最近更新 更多