Весной государственная машина застряла в состоянии соединения

Я пытаюсь смоделировать машину для приема наличных.

Моя конфигурация 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 ответ

Решение

Не могли бы вы попробовать две вещи отдельно

  1. Измените эти конечные состояния на нормальные состояния.
  2. Вместо присоединения по конечным состояниям присоедините их по родительскому состоянию (ACCEPTING_CASH).

Я еще не проверял, есть ли тесты для этого конкретного варианта использования, чтобы проверить, должен ли он работать или нет. Теория заключается в том, что конечные состояния не могут иметь исходящие переходы, поэтому объединение может не работать.

Другие вопросы по тегам