Конечный автомат Spring — привязка статических данных к состояниям

#spring-statemachine

#spring-statemachine

Вопрос:

С конечным автоматом spring у нас есть состояния и события. Я не смог найти никакой документации о том, возможно ли привязать статические данные к состоянию во время настройки.

Например, если существуют состояния S1 и S2

 public void configure(StateMachineStateConfigurer<String, String> states) throws Exception  {
    states.withStates()
                .initial("INIT")
                .end("END")
                .state("S1", null, exitAction())
                .state("S2", entryAction());
}
  

Если бы мы могли присоединять статические данные во время приведенной выше конфигурации (например, java Map), это могло бы быть полезно в запускаемых действиях (например, entryAction и ExitAction выше)

Я не знаю, возможно ли это как-то сделать.

Ответ №1:

Это достигается с помощью двух объектов в конечном автомате — StateContext и ExtendedState.

StateContext подобен текущему снимку конечного автомата — он передается с помощью различных методов и обратных вызовов, включая действия и средства защиты.

ExtendedState — это, по сути, отображение с переменными.

Вы можете получить ExtendedState из StateContext :

     context.getExtendedState()
        .getVariables().put("mykey", "myvalue");
  

Поскольку они передаются как часть контекста, вы можете получить доступ к ExtendedState при каждом действии, переходе, защите и т.д.
Сам объект StateMachine также имеет getExtendedState() метод.

Это канонический способ передачи статических данных в StateMachine.

Комментарии:

1. Я следил за этим техническим специалистом, чтобы создать сценарий, в котором Action2 нужны данные из Action1. Нормально ли это делать? передача больших объектов в контекст? Спасибо

2. @PascoalEddyBayonne как и большинство ответов: это зависит. Как часто это происходит (например, какова ваша нагрузка на этот экземпляр SM?). Насколько велико значение large? Лучший способ — измерить объем памяти и провести некоторое нагрузочное тестирование. Есть ли у вас альтернативы — например, запись этого состояния в кэш памяти или другой тип хранилища в Action1 и извлечение его в Action2? Как сравниваются два подхода при нагрузочном тестировании, которое соответствует вашему реальному сценарию?

3. спасибо за быстрые ответы. Ну, на самом деле то, что я делаю, — это использую Действия для выполнения некоторой бизнес-логики. Единственный вопрос заключается в передаче данных между действиями. Большой объект я имею в виду любой объект Java, например CreateCreditCardRequest, внутри которого больше объектов. Предположим, я хочу использовать CreateCreditCardRequest в Action2, но мне нужно дополнить его данными, полученными из Action1. Просто это. Я использую контекст для передачи данных (любого размера) между различными действиями. Что вы посоветуете? Еще раз спасибо

4. То, что я делал несколько лет назад — аналогично вашему случаю — это только передавал идентификатор, указывающий на мой объект в контексте SM — и при каждом событии действии в определении SM — получал идентификатор — извлекал объект (это было из кэша JPA L1 или из базы данных для чтения — в зависимости) — изменял объект — сохранял объект. Если мне придется делать это сейчас, у меня, вероятно, будет поток событий журнал событий, применяющий модификацию к объекту в памяти и периодически сохраняющий объект в хранилище. Очевидно, что события будут записываться в журнал событий с опережением записи.