春天状态机卡在加入状态

时间:2017-06-30 14:49:01

标签: spring-statemachine

我正在尝试为现金接收机器建模。

我的StateMachine配置如下。我省略了一些不重要的状态和事件。

@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
    states
        .withStates()
            .initial(States.INIT, initAction())
            .state(States.CONNECTED)
            .and()
            .withStates()
                .parent(States.CONNECTED)
                .initial(States.READY)
                .state(States.READY)
                .fork(States.ACCEPTING_CASH_FORK)
                .state(States.ACCEPTING_CASH)
                .join(States.ACCEPTING_CASH_JOIN)
                .choice(States.PROCESSING_CASH)
                .state(States.PRINTING_RECEIPT, printingReceiptAction(), null)
            .and()
            .withStates()
                .parent(States.ACCEPTING_CASH)
                .initial(States.BNR_CASH_IN_START)
                .state(States.BNR_CASH_IN_END)
                .end(States.BNR_CASH_IN_EXIT)
            .and()
            .withStates()
                .parent(States.ACCEPTING_CASH)
                .initial(States.CNR_CASH_IN_START)
                .state(States.CNR_CASH_IN_END)
                .end(States.CNR_CASH_IN_EXIT)
            .and();
}

@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
    transitions
        .withExternal()
            .source(States.INIT).target(States.CONNECTED)
            .and()
        .withExternal()
            .source(States.READY)
            .target(States.ACCEPTING_CASH_FORK)
            .event(Events.ACCEPT_CASH)
            .and()
        .withFork()
            .source(States.ACCEPTING_CASH_FORK)
            .target(States.BNR_CASH_IN_START).target(States.CNR_CASH_IN_START)
            .and()
        .withExternal()
            .source(States.BNR_CASH_IN_END)
            .target(States.BNR_CASH_IN_EXIT)
            .event(Events.BNR_CASH_IN_END_COMPLETED)
            .and()
        .withExternal()
            .source(States.CNR_CASH_IN_END)
            .target(States.CNR_CASH_IN_EXIT)
            .event(Events.CNR_CASH_IN_END_COMPLETED)
            .and()
        .withJoin()
            .source(States.BNR_CASH_IN_EXIT).source(States.CNR_CASH_IN_EXIT).target(States.ACCEPTING_CASH_JOIN)
            .and()
        .withExternal()
            .source(States.ACCEPTING_CASH_JOIN)
            .target(States.PROCESSING_CASH)
            .and()
        .withChoice()
            .source(States.PROCESSING_CASH)
            .first(States.DISPENSING_CASH_FORK, dispensingCashGuard(), dispensingCashAction())
            .last(States.PRINTING_RECEIPT)
            .and();
}

我还配置了一个监听器以进行调试。

@Bean
public StateMachineListener<States, Events> listener() {
    return new StateMachineListenerAdapter<States, Events>() {
        @Override
        public void stateChanged(State<States, Events> from, State<States, Events> to) {
            log.info("State change from " + (from != null ? from.getId() : from) + " to " + to.getId());
        }

        @Override
        public void stateMachineStarted(StateMachine<States, Events> stateMachine) {
            log.info("StateMachine uuid " + stateMachine.getUuid() + " state " + stateMachine.getState().getId());
        }

        @Override
        public void transition(Transition<States, Events> transition) {
            Trigger<States, Events> trigger = transition.getTrigger();
            State<States, Events> source = transition.getSource();
            State<States, Events> target = transition.getTarget();
            log.info("Transition trigger " + (trigger != null ? trigger.getEvent() : trigger) + 
                " source " + (source != null ? source.getId() : source) + 
                " target " + (target != null ? target.getId() : target) + " kind " + transition.getKind());
        }

    };
}

问题出在 ACCEPTING_CASH_JOIN 加入当达到2个状态 BNR_CASH_IN_EXIT CNR_CASH_IN_EXIT 时,该状态机应该处于哪个状态。但是在日志中,statemachine没有达到它。

2017-06-30 19:59:06.891  INFO 3776 --- [       Thread-9] k.d.c.config.StateMachineConfiguration   : StateMachine uuid 52e51cf0-06f0-4efa-8d05-1717bf869239 state CONNECTED
2017-06-30 19:59:06.891  INFO 3776 --- [       Thread-9] k.d.c.config.StateMachineConfiguration   : State change from null to CNR_CASH_IN_END
2017-06-30 19:59:06.892  INFO 3776 --- [       Thread-8] k.d.c.config.StateMachineConfiguration   : Transition trigger CNR_CASH_IN_END_COMPLETED source CNR_CASH_IN_END target CNR_CASH_IN_EXIT kind EXTERNAL
2017-06-30 19:59:06.892  INFO 3776 --- [       Thread-8] k.d.c.config.StateMachineConfiguration   : State change from CNR_CASH_IN_END to CNR_CASH_IN_EXIT

2017-06-30 19:59:06.924  INFO 3776 --- [       Thread-8] k.d.c.config.StateMachineConfiguration   : StateMachine uuid 52e51cf0-06f0-4efa-8d05-1717bf869239 state CONNECTED
2017-06-30 19:59:06.924  INFO 3776 --- [       Thread-8] k.d.c.config.StateMachineConfiguration   : State change from null to BNR_CASH_IN_END
2017-06-30 19:59:07.146  INFO 3776 --- [       Thread-8] k.d.c.config.StateMachineConfiguration   : Transition trigger BNR_CASH_IN_END_COMPLETED source BNR_CASH_IN_END target BNR_CASH_IN_EXIT kind EXTERNAL
2017-06-30 19:59:07.146  INFO 3776 --- [       Thread-8] k.d.c.config.StateMachineConfiguration   : State change from BNR_CASH_IN_END to BNR_CASH_IN_EXIT

2017-06-30 19:59:27.239 DEBUG 3776 --- [  XNIO-2 task-4] k.d.c.w.rest.StateMachineQueryResource   : [CONNECTED, ACCEPTING_CASH, BNR_CASH_IN_EXIT, CNR_CASH_IN_EXIT]

最后一行是我通过在statemachine stateMachine.getState()上调用方法来检查当前状态的方法.getIds()

1 个答案:

答案 0 :(得分:0)

你介意分开尝试两件事吗

  1. 将这些结束状态更改为正常状态。
  2. 不是通过最终状态加入,而是通过其父状态(ACCEPTING_CASH)加入。
  3. 我还没有检查是否有针对此特定用例的测试来验证它是否应该起作用。理论是终端状态不能具有传出转换,因此连接可能不起作用。