【问题标题】:Unable to Trigger an Event from Action无法通过操作触发事件
【发布时间】:2019-06-19 08:32:02
【问题描述】:

我正在设置 Spring 状态机事务,我想在 Event1 完成后启动 Event2

这些是我的状态

状态 -> “初始”、“第二”、“第三”

我已将事务配置为从 FIRST_EVENT 的操作发送 SECOND_EVENT,如下所示

transitions.withExternal()
    .source("INITIAL")
    .target("SECOND")
    .event("FIRST_EVENT")
    .action(new Action<String, String>() {
        @Override
        public void execute(StateContext<String, String> context) {
            System.out.println("FIRST_ACTION_EXECUTED");
            context.getStateMachine().sendEvent("SECOND_EVENT");
        }
    })
    .and()
    .withExternal()
    .source("SECOND")
    .target("THIRD")
    .event("SECOND_EVENT")
    .action(new Action<String, String>() {
        @Override
        public void execute(StateContext<String, String> context) {
            System.out.println("TEST SUCCESS");
        }
    });

这里我得到了 evenNotAccepted 异常,我知道原因是 statemachine.getState() 是 INITIAL,它不能直接将状态从 INITIAL 更改为 THIRD。

所以我的问题是,我是否可以将状态机配置为在第一个事件完成时自动触发第二个事件

【问题讨论】:

    标签: java spring-statemachine


    【解决方案1】:

    这是因为您使用的操作类型。 Spring SM 中有两种主要类型的动作 - transition 动作和 state 动作 - 它们在不同的时间解析。您可以看到解决这些操作的序列here

    为了触发事件进入下一个状态,您应该使用状态操作。

    您可以像这样配置状态操作:

       builder.configureStates()
                .withStates()
                .initial(SI)
                .state(F1, context -> context.getStateMachine().sendEvent(E2))
                .state(F2, context -> context.getStateMachine().sendEvent(E3))
                .end(SF);
    
        builder.configureTransitions()
                .withExternal().source(SI).target(F1).event(E1)
                .and()
                .withExternal().source(F1).target(F2).event(E2)
                .and()
                .withExternal().source(F2).target(SF).event(E3)
                    .action(context -> System.out.println("Completing SM!"));
    

    手动触发事件E1,将产生以下输出(事件E2E3通过状态动作自动触发):

    STATE ENTERED: SI
    STAGE TRANSITIONS From: null To: SI
    STATE EXITED: SI
    STATE ENTERED: F1
    STAGE TRANSITIONS From: SI To: F1
    21:45:39.153 [pool-2-thread-1] DEBUG org.springframework.statemachine.support.AbstractStateMachine - Queue event GenericMessage [payload=E2, headers={id=393a5636-a760-57d6-a98b-d31eb75f048e, timestamp=1560969939152}] SF F2 F1 SI  / F1 / uuid=4e8773c1-e755-40de-b431-e53a4b0ca64d / id=null
    STATE EXITED: F1
    STATE ENTERED: F2
    STAGE TRANSITIONS From: F1 To: F2
    21:45:39.161 [pool-2-thread-1] DEBUG org.springframework.statemachine.support.AbstractStateMachine - Queue event GenericMessage [payload=E3, headers={id=f5899e8b-e4a5-e079-3a30-66114a7accac, timestamp=1560969939161}] SF F2 F1 SI  / F2 / uuid=4e8773c1-e755-40de-b431-e53a4b0ca64d / id=null
    Completing SM!
    STATE EXITED: F2
    STATE ENTERED: SF
    STAGE TRANSITIONS From: F2 To: SF
    

    【讨论】:

    • 感谢您的回答,但我现在面临一个不同的问题,当我配置状态并发送事件时,它在调试模式下工作正常,但是当我在正常模式下运行时,它给出 eventNotAccepted 错误有时,有时它工作正常。所以现在我把它改成了: .initial(SI) .stateEntry(F1, context -> context.getStateMachine().sendEvent(E2)) .stateEntry(F2, context -> context.getStateMachine().sendEvent(E3) ) .end(SF);更改为 stateEntry 后,它按预期工作,但我现在想知道为什么会发生这种情况
    • 哦,我明白了,我想这是因为动作在 TaskExecutor 中排队,并且它们以非顺序方式执行。 stateEntry 可能在执行前经过一些检查,保证了执行的顺序。
    • 那么它是不是类似于线程调度程序,我们无法控制它?
    • 是的,但我相信在 SM 配置中您可以提供自己的 TaskExecutor 和 TaskScheduler。
    • 当然,你可以在配置常用设置中找到更多信息-docs.spring.io/spring-statemachine/docs/current/reference/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    相关资源
    最近更新 更多