Reputation: 87
I am using a state machine builder to build state machine in my app. Also the application has Action classes which implements org.springframework.statemachine.action.Action. These Action classes are for executing entry actions for each stages. If any exception is thrown from these Action classes, ie from execute(StateContext paramStateContext) method, I wanted to catch that exception and send an event(Terminated) and drive the state machine to End state, after updating the db with error details. I tried to use state machine listener by overriding stateMachineError(StateMachine stateMachine, Exception e) method. But unfortunately this is not working. Any other spring state machine component to catch exceptions, before I go to wrap the entire code in Action classes with try catch, and inside catch block sending the Terminated event so that state machine would navigate End state. Here is the builder Iam using.
Builder<String, String> builder = StateMachineBuilder
.<String, String> builder();
builder.configureConfiguration()
.withConfiguration()
.autoStartup(false)
.listener(listener())
.beanFactory(
this.applicationContext.getAutowireCapableBeanFactory());
private StateMachineListener<String, String> listener() {
return new StateMachineListenerAdapter<String, String>() {
@Override
public void stateChanged(
org.springframework.statemachine.state.State<String, String> from,
org.springframework.statemachine.state.State<String, String> to) {
LOGGER.debug("State change to " + to.getId());
}
@Override
public void stateMachineError(
StateMachine<String, String> stateMachine, Exception e) {
e.printStackTrace();
LOGGER.debug("Ah... I am not getting executed when exception occurs from entry actions");
LOGGER.debug("Error occured from " + stateMachine.getState()
+ "and the error is" + e.toString());
}
};
}
Iam using 1.1.0.RELEASE version of spring-statemachine-core
Upvotes: 0
Views: 1826
Reputation: 20061
You're correct, neither stateMachineError
or a method annotated with @onStateMachineError
are executed on an error. This is addressed in version 1.2, which is at milestone 1 right now. They introduced errorAction
which is executed with the state machine context:
User can always catch exceptions manually but with actions defined for transitions it is possible to define error action which is called if exception is raised. Exception is then available from a StateContext passed to that action.
All that's needed is to specify an error action along with the desired action when defining a transition in the state machine configuration class. From the example in the documentation:
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.S1)
.target(States.S2)
.event(Events.E1)
.action(action(), errorAction());
}
A detailed discussion of this can be found in Spring Statemachine issue #240.
Upvotes: 0