Support for scopes in a state machine is very limited but it is possible
to enable use of session scope using a normal spring @Scope
annotation.
Firstly if state machine is build manually via a builder and returned into
context as @Bean
, and secondly via a configuration adapter. Both of
these simply needs an a @Scope
to be present where scopeName is set to
session and proxyMode to ScopedProxyMode.TARGET_CLASS
. Examples for
both use cases are shown below.
Tip | |
---|---|
See sample Chapter 45, Scope how to use session scoping. |
@Configuration public class Config3 { @Bean @Scope(scopeName="session", proxyMode=ScopedProxyMode.TARGET_CLASS) StateMachine<String, String> stateMachine() throws Exception { Builder<String, String> builder = StateMachineBuilder.builder(); builder.configureConfiguration() .withConfiguration() .autoStartup(true) .taskExecutor(new SyncTaskExecutor()); builder.configureStates() .withStates() .initial("S1") .state("S2"); builder.configureTransitions() .withExternal() .source("S1") .target("S2") .event("E1"); StateMachine<String, String> stateMachine = builder.build(); return stateMachine; } }
@Configuration @EnableStateMachine @Scope(scopeName="session", proxyMode=ScopedProxyMode.TARGET_CLASS) public static class Config4 extends StateMachineConfigurerAdapter<String, String> { @Override public void configure(StateMachineConfigurationConfigurer<String, String> config) throws Exception { config .withConfiguration() .autoStartup(true); } @Override public void configure(StateMachineStateConfigurer<String, String> states) throws Exception { states .withStates() .initial("S1") .state("S2"); } @Override public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception { transitions .withExternal() .source("S1") .target("S2") .event("E1"); } }
Once you have scoped state machine into session
, autowiring it into
a @Controller
will give new state machine instance per session.
State machine is then destroyed when HttpSession
is invalidated.
@Controller public class StateMachineController { @Autowired StateMachine<String, String> stateMachine; @RequestMapping(path="/state", method=RequestMethod.POST) public HttpEntity<Void> setState(@RequestParam("event") String event) { stateMachine.sendEvent(event); return new ResponseEntity<Void>(HttpStatus.ACCEPTED); } @RequestMapping(path="/state", method=RequestMethod.GET) @ResponseBody public String getState() { return stateMachine.getState().getId(); } }
Note | |
---|---|
Using state machines in a |
Note | |
---|---|
Spring Statemachine poms don’t have any dependencies to Spring MVC classes which you will need to work with session scope. But if you’re working with a web application, you’ve already pulled those deps directly from Spring MVC or Spring Boot. |