I am trying to extend the Persist sample of spring statemachine to two different state machine configurations. http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#statemachine-examples-persist
Therefor I
- added a new schema
- addded some test data
- duplicated the code for Persist, PersistCommand and adapted them to my case
No big deal so far. Now to the Configuration:
- I removed the StateMachineConfig (and with it the @EnableStateMachine Annotation)
- addded the StateMachineConfiguration into PersistHandlerConfig as a Bean and use the Builder
- duplicated that config and adapted it to my use case
- obviously crated me a class like Order for my case
Furthermore I adapted the AbstractStateMachineCommands class and autowire a list of statemachines in there. The start/stop and state methods now start/stop and print state of every state machine (here I do not care about print, variables).
The occuring problem is:
- The persisting does not work any longer
- I can start the application and both state machines
- I can use all persist and myUseCase calls but there are not working on the persistent data.
- If I e.g. call persist process 1, the application change the state of the underlying SM to PROCESSING, but the peristed data does not change.
- In debugging I was able to resolve that in LifecycleObjectSupport the getTaskExecutor method returns null (while in the original example the bean factory returns an instance of SyncTaskExecutor).
- Besides it seems that the TestEventListener does not work any longer for any of the state machines
- When I use @EnableStateMachine at any of the configurations containing a state machine bean, an NPE occurs at afterPropertiesSet of StateMachineConfiguration.
So, can anybody tell me where I messed it up? Or is the Persist recipe not applicable to two state machines?
Thanks a lot.
Code Examples: The Application.java now contains these configs and entities:
@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 and TicketPersistCommands.java are the same like the ones for orders (just replaced order(s) with ticket(s)). I adapted AbstractStateMachineCommands in the following way:
@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";
}