我正在尝试将弹簧状态机的 Persist 示例扩展到两种不同的状态机配置。 http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#statemachine-examples-persist
为此我
- 添加了新架构
- 添加了一些测试数据
- 复制了 Persist 和 PersistCommand 的代码,并根据我的情况对其进行了调整
到目前为止没什么大不了的。现在到配置:
- 我删除了 StateMachineConfig(以及 @EnableStateMachine 注释)
- 将 StateMachineConfiguration 作为 Bean 添加到 PersistHandlerConfig 中并使用 Builder
- 复制该配置并将其调整为我的用例
- 显然,我为我的案子上了一个像 Order 这样的课程
此外,我调整了 AbstractStateMachineCommands 类并在其中自动装配状态机列表。start/stop 和 state 方法现在启动/停止和打印每个状态机的状态(这里我不关心打印、变量)。
出现的问题是:
- 持久化不再起作用
- 我可以启动应用程序和两个状态机
- 我可以使用所有 persist 和 myUseCase 调用,但没有处理持久数据。
- 例如,如果我调用持久化进程 1,应用程序将底层 SM 的状态更改为 PROCESSING,但持久化的数据不会改变。
- 在调试中,我能够在 LifecycleObjectSupport 中解决 getTaskExecutor 方法返回 null 的问题(而在原始示例中,bean 工厂返回 SyncTaskExecutor 的实例)。
- 此外,似乎 TestEventListener 不再适用于任何状态机
- 当我在任何包含状态机 bean 的配置中使用 @EnableStateMachine 时,会在 StateMachineConfiguration 的 afterPropertiesSet 处发生 NPE。
那么,谁能告诉我我在哪里搞砸了?还是 Persist 配方不适用于两个状态机?
非常感谢。
代码示例:Application.java 现在包含这些配置和实体:
@Configuration
static class PersistHandlerConfig {
@Bean
public Persist persist() throws Exception {
return new Persist(persistStateMachineHandler());
}
@Bean
public PersistStateMachineHandler persistStateMachineHandler() throws Exception {
return new PersistStateMachineHandler(persistSm());
}
@Bean
public StateMachine<String, String> persistSm() throws Exception{
Builder<String, String> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial("PLACED")
.state("PROCESSING")
.state("SENT")
.state("DELIVERED");
builder.configureTransitions()
.withExternal()
.source("PLACED").target("PROCESSING")
.event("PROCESS")
.and()
.withExternal()
.source("PROCESSING").target("SENT")
.event("SEND")
.and()
.withExternal()
.source("SENT").target("DELIVERED")
.event("DELIVER");
return builder.build();
}
}
@Configuration
static class TicketPersistHandlerConfig {
@Bean
public TicketPersist ticketPersist() throws Exception {
return new TicketPersist(ticketPersistStateMachineHandler());
}
@Bean
public PersistStateMachineHandler ticketPersistStateMachineHandler() throws Exception {
return new PersistStateMachineHandler(buildMachine());
}
@Bean
public StateMachine<String, String> buildMachine() throws Exception {
Builder<String, String> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial("PRINTED")
.state("BOOKED")
.state("SOLD")
.state("DELIVERED");
builder.configureTransitions()
.withExternal()
.source("PRINTED").target("BOOKED")
.event("BOOK")
.and()
.withExternal()
.source("BOOKED").target("SOLD")
.event("SELL")
.and()
.withExternal()
.source("SOLD").target("DELIVERED")
.event("DELIVER");
return builder.build();
}
}
public static class Order {
int id;
String state;
public Order(int id, String state) {
this.id = id;
this.state = state;
}
@Override
public String toString() {
return "Order [id=" + id + ", state=" + state + "]";
}
}
public static class Ticket {
int id;
String state;
public Ticket(int id, String state) {
this.id = id;
this.state = state;
}
@Override
public String toString() {
return "Ticket [id=" + id + ", state=" + state + "]";
}
}
TicketPersist.java 和 TicketPersistCommands.java 与订单的相同(只是将订单替换为票证)。我通过以下方式调整了 AbstractStateMachineCommands:
@Autowired
private List<StateMachine<S, E>> stateMachines;
@CliCommand(value = "sm start", help = "Start a state machine")
public String start() {
for (StateMachine<S, E> stateMachine : stateMachines)
{
stateMachine.start();
}
return "State machines started";
}
@CliCommand(value = "sm stop", help = "Stop a state machine")
public String stop() {
for (StateMachine<S, E> stateMachine : stateMachines)
{
stateMachine.stop();
}
return "State machines stopped";
}