Open ymyfrank opened 6 years ago
ObjectState:149, the "exit action" looks like having the same behavior. I can not find "state action" exception processing code, and don't know if if has the same issue
AbstractTransition:111, similarly when exception occurs in Guard, the Guard return false, state machine will continue running to transition without guard(suppose there are 2 transitions for the choice state, one transition has a guard, the other has no guard), and state machine caller does not know the exception, which causes business logic error. Because the Guard result is not really false. My personal expected behavior is: state machine stops running immediately. Let state machine caller knows the exception. (I'm not sure if throw the exception after AbstractTransition:111 can help)
I'm ready to modify or enhance this behaviour if we come up with a good and clear way to do it. I think first question is that how possible exception in a Guard
would get reflected back to a user?
I disagree that with guard throwing exception it would not evaluate to false
. UML spec is quite clear that a guard must either evaluate to true
or false
and as with exception it surely is not true
it must be false
. I do agree with you that it's not a good thing that we silently eat that exception and should come up with something better. Question is just what?
Have tried but could not get exception https://docs.spring.io/spring-statemachine/docs/1.2.7.RELEASE/reference/htmlsingle/#sm-error-handling Our helper method code: private void addInterceptor(StateMachine<String, String> stateMachine) {
ExtendedState extendedState = stateMachine.getExtendedState();
Map<Object, Object> variables = extendedState.getVariables();
stateMachine.getStateMachineAccessor()
.doWithRegion(new StateMachineFunction<StateMachineAccess<String, String>>() {
@Override
public void apply(StateMachineAccess<String, String> function) {
function.addStateMachineInterceptor(
new StateMachineInterceptorAdapter<String, String>() {
@Override
public Exception stateMachineError(StateMachine<String, String> stateMachine,
Exception exception) {
variables.put(ControllerConstants.KEY_EXCEPTION, exception);
return exception;
}
});
}
});
}
I do agree with you that it's not a good thing that we silently eat that exception and should come up with something better. Question is just what?
For that we have the Log4j or any other logging system or not, if an exception occurs in Guard condition, guard condition returns false, you log it and diagnose it from logs and ensure that no Exception occurs in guard condition.
A guard condition throwing exception can't be a normal behavior.
At least log it is a good start. I think I just thought about not having too much noise in logs or generally speaking didn't thought about it that much. I have had some thought about exception handler and concepts around it but don't really know how that would get implemented.
I use Papyrus neo to design state machine definition. The language used: SPEL Entry action is used because of bug: https://github.com/spring-projects/spring-statemachine/issues/474 My personal expectation is: add "throw e;" after ObjectState:161, so that state machine stops running immediately and state machine caller (who sends event to start the state machine) can easily know exception occurred during state machine processing(simply add catch exception block), Actual behavior is: state machine continues running when exception occurs, and state machine caller never knows if exception occurs. Especially when SPEL syntax error, null pointer error. Currently we can partially work around this by catch all exceptions and add them into state machine context, state machine caller checks the context to see if exception happens. Probably there are other way to let state machine caller knows the exceptions, please ignore this issue and let me know.