假设我们具有以下状态机配置:
transitions.withExternal()
.source(FIRST)
.target(SECOND)
.event(STEP_EVENT)
.and()
.source(SECOND)
.target(EXIT)
.event(EXIT_EVENT)
事件列表:STEP_EVENT,EXIT_EVENT,UNUSED_EVENT
stateMachine.init();
// FIRST state
stateMachine.sendEvent(STEP_EVENT);
/* state moves to SECOND
because there is a transition with current state as a source
and STEP_EVENT as transition event */
stateMachine.sendEvent(UNUSED_EVENT);
/* no state change.
This will trigger "eventNotAccepted(Message<Events> event)"
in state machine listener,
because UNUSED_EVENT is never mentioned in SM config */
stateMachine.sendEvent(STEP_EVENT);
/* nothing will happen!!!
No state change, as there is no transition
which has current state (SECOND) as source
and STEP_EVENT as transition event,
and no eventNotAccepted call.
But I need it, I want to fail here! */
stateMachine.sendEvent(EXIT_EVENT);
// state will move to EXIT
问题是,当我发送事件(该事件是配置的一部分,但不适用于当前状态)时,什么也没发生。
我不知道状态是否由于警卫而改变,或者因为当前状态和事件没有过渡。
有什么办法可以处理这种情况?
答案 0 :(得分:0)
要记录不适用于您当前状态的事件,可以使用StateMachine侦听器。每次在状态机中传递事件时都会调用一种方法,该方法不满足定义的转换和事件。
在状态机配置中,您需要覆盖:
public void configure(StateMachineConfigurationConfigurer<State, Event> config) {
config.withConfiguration()
.listener(customListener());
}
并实现自己的侦听器-最简单的方法是使用StateMachineListenerAdapter
并覆盖eventNotAccepted(Message event)
方法:
private StateMachineListenerAdapter<State, Event> customListener() {
return new StateMachineEventListenerAdapter<State, Event>() {
@Override
public void eventNotAccepted(Message event) {
//LOG which event was not accepted etc.
}
}
}
要记录警卫的结果-在警卫本身中使用日志消息。
如果要在警卫之外公开原因,则可以构造一个键值对,并使用StateMachine的扩展上下文记录警卫名称以及拒绝事件的原因。 上下文可用于构造自定义异常或将发生的情况传达给调用者代码。
答案 1 :(得分:0)
解决了!通常,解决方案对我来说太简单了:(。因此,将事件发送给SM的方法将布尔值作为返回参数。如果事件被处理,则返回true,否则返回false。
就这样-只需检查返回值即可!