In all examples I have looked up online, the StateMachine is configured statically
@Override
public void configure(StateMachineTransitionConfigurer<BookStates, BookEvents> transitions) throws Exception {
transitions
.withExternal()
.source(BookStates.AVAILABLE)
.target(BookStates.BORROWED)
.event(BookEvents.BORROW)
.and()
.withExternal()
.source(BookStates.BORROWED)
.target(BookStates.AVAILABLE)
.event(BookEvents.RETURN)
.and()
.withExternal()
.source(BookStates.AVAILABLE)
.target(BookStates.IN_REPAIR)
.event(BookEvents.START_REPAIR)
.and()
.withExternal()
.source(BookStates.IN_REPAIR)
.target(BookStates.AVAILABLE)
.event(BookEvents.END_REPAIR);
}
I would like to configure the StateMachine "dynamically" by fetching the source,target,event from a Database and loop through the List to configure this in a "fluid" manner.
Is this possible?
Yes it is possible through a custom implementation of StateMachineModelFactory
. You can hook it using StateMachineModelConfigurer
like so:
@Configuration
@EnableStateMachine
public static class Config1 extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
model
.withModel()
.factory(modelFactory());
}
@Bean
public StateMachineModelFactory<String, String> modelFactory() {
return new CustomStateMachineModelFactory();
}
}
In your implementation you can dynamically load whatever is needed for the SM model from external services. Below is an example from the official doc:
public static class CustomStateMachineModelFactory implements StateMachineModelFactory<String, String> {
@Override
public StateMachineModel<String, String> build() {
ConfigurationData<String, String> configurationData = new ConfigurationData<>();
Collection<StateData<String, String>> stateData = new ArrayList<>();
stateData.add(new StateData<String, String>("S1", true));
stateData.add(new StateData<String, String>("S2"));
StatesData<String, String> statesData = new StatesData<>(stateData);
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
transitionData.add(new TransitionData<String, String>("S1", "S2", "E1"));
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<String, String>(configurationData,
statesData, transitionsData);
return stateMachineModel;
}
@Override
public StateMachineModel<String, String> build(String machineId) {
return build();
}
}
You can easily load the states and transitions dynamically from the DB and populate the ConfigurationData
.
来源:https://stackoverflow.com/questions/54823162/spring-statemachine-configure-from-database