(UML) Spring-Statemachine 在 statemachine.stop() 之后仍然是 运行
(UML) Spring-Statemachine is still running after a statemachine.stop()
我的 Spring-Statemachine 中有一个守卫。
@Bean
public Guard<String, String> myGuard() {
return context -> {
try {
String x = null;
x.length();
return true;
} catch (Exception e) {
context.getStateMachine().setStateMachineError(e);
context.getStateMachine().stop();
throw e;
}
};
}
这当然是java.lang.NullPointerException
。
所以,在我做了一个 context.getStateMachine().stop();
之后,我期待状态机停止。
2017-11-24 18:02:55.783 INFO 30652 --- [nio-8080-exec-1] o.s.s.support.LifecycleObjectSupport : stopped org.springframework.statemachine.support.DefaultStateMachineExecutor@367d6b09
所以,它停止了。
但比所有其他守卫、状态和动作都在之后调用。
但是当出现错误时,我绝对不希望守卫只是切换到false
,我真的很想退出机器
只有一个地区。所以,据我了解,它应该停止。
有什么办法可以解决这个问题吗?或者在发生这种情况时有什么方法可以调用 "Exit event" 之类的东西吗?
感谢您提供任何处理此问题的想法。
使用:
spring-boot: 1.5.8
spring-statemachine-uml 1.2.6
我不确定在这种情况下当有人试图阻止机器时会发生什么。老实说,我什至从未尝试过,因为您尝试做的事情毫无意义。回顾一下我最初是如何选择将上下文暴露给守卫的,可以访问机器本身,从而使停止方法可见。当机器为 运行 时,我不会尝试通过内部逻辑停止机器。我早就该考虑这个了:)
不过话虽如此,守卫实际上只有一个作用,那就是保护过渡,它应该 return 是对还是错。当调用守卫时,我们确实处理捕获异常(我们将其评估为 false,afaik),但从守卫中抛出一些东西通常是未定义的行为。
假设您执行的某些操作出现错误,那么您应该执行一些与错误相关的操作。我会即创建一个终端状态,设置转换到该终端状态,然后您可以从操作(在 catch 内)发送事件以指示机器进入该状态。通常这种错误处理不会在单根级别机器中完成,因为它通常会导致状态爆炸(您需要开始设置从所有状态到错误状态的转换)。这就是为什么通常使用子状态来处理正确的错误处理。
但是,如果您再公开一点您的用例以及您想要完成的目标,我可以尝试提供更好的示例。错误处理始终是一个特定的主题,因为它通常需要构建到您的机器设计中。从下面的状态图中可以看到我目前正在使用 spring-cloud-skipper
处理的更复杂的错误处理。这可能超出了您的问题范围,但为您接下来的评论提供了一些背景知识。
我现在正在使用这个 SpringAOP 函数捕获所有错误:
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Aspect
@Component
public class ErrorInterceptor {
@Autowired
private StateMachine<String, String> myStateMachine;
@AfterThrowing(pointcut = "execution(* org.springframework.statemachine.guard.Guard.evaluate(*))", throwing = "ex")
public void errorInterceptorGuard(Exception ex) {
log.info("Error on Guard: " + myStateMachine.getState().getId() + " with Exception " + ex.toString());
myStateMachine.setStateMachineError(ex);
}
@AfterThrowing(pointcut = "execution(* org.springframework.statemachine.action.Action.execute(*))", throwing = "ex")
public void errorInterceptorAction(Exception ex) {
log.info("Error on Action: " + myStateMachine.getState().getId() + " with Exception " + ex.toString());
myStateMachine.setStateMachineError(ex);
}
}
在我启动 StateMachine 的控制器中,我做了类似的事情:
if(myStateMachine.hasStateMachineError()) {
// do something which is returning the ERROR.
}
仍然不是我想要的 100%,因为 statemachine.stop 从内部无法正常工作,但我正在处理它。
我的 Spring-Statemachine 中有一个守卫。
@Bean
public Guard<String, String> myGuard() {
return context -> {
try {
String x = null;
x.length();
return true;
} catch (Exception e) {
context.getStateMachine().setStateMachineError(e);
context.getStateMachine().stop();
throw e;
}
};
}
这当然是java.lang.NullPointerException
。
所以,在我做了一个 context.getStateMachine().stop();
之后,我期待状态机停止。
2017-11-24 18:02:55.783 INFO 30652 --- [nio-8080-exec-1] o.s.s.support.LifecycleObjectSupport : stopped org.springframework.statemachine.support.DefaultStateMachineExecutor@367d6b09
所以,它停止了。 但比所有其他守卫、状态和动作都在之后调用。
但是当出现错误时,我绝对不希望守卫只是切换到false
,我真的很想退出机器
只有一个地区。所以,据我了解,它应该停止。
有什么办法可以解决这个问题吗?或者在发生这种情况时有什么方法可以调用 "Exit event" 之类的东西吗?
感谢您提供任何处理此问题的想法。
使用:
spring-boot: 1.5.8
spring-statemachine-uml 1.2.6
我不确定在这种情况下当有人试图阻止机器时会发生什么。老实说,我什至从未尝试过,因为您尝试做的事情毫无意义。回顾一下我最初是如何选择将上下文暴露给守卫的,可以访问机器本身,从而使停止方法可见。当机器为 运行 时,我不会尝试通过内部逻辑停止机器。我早就该考虑这个了:)
不过话虽如此,守卫实际上只有一个作用,那就是保护过渡,它应该 return 是对还是错。当调用守卫时,我们确实处理捕获异常(我们将其评估为 false,afaik),但从守卫中抛出一些东西通常是未定义的行为。
假设您执行的某些操作出现错误,那么您应该执行一些与错误相关的操作。我会即创建一个终端状态,设置转换到该终端状态,然后您可以从操作(在 catch 内)发送事件以指示机器进入该状态。通常这种错误处理不会在单根级别机器中完成,因为它通常会导致状态爆炸(您需要开始设置从所有状态到错误状态的转换)。这就是为什么通常使用子状态来处理正确的错误处理。
但是,如果您再公开一点您的用例以及您想要完成的目标,我可以尝试提供更好的示例。错误处理始终是一个特定的主题,因为它通常需要构建到您的机器设计中。从下面的状态图中可以看到我目前正在使用 spring-cloud-skipper
处理的更复杂的错误处理。这可能超出了您的问题范围,但为您接下来的评论提供了一些背景知识。
我现在正在使用这个 SpringAOP 函数捕获所有错误:
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Aspect
@Component
public class ErrorInterceptor {
@Autowired
private StateMachine<String, String> myStateMachine;
@AfterThrowing(pointcut = "execution(* org.springframework.statemachine.guard.Guard.evaluate(*))", throwing = "ex")
public void errorInterceptorGuard(Exception ex) {
log.info("Error on Guard: " + myStateMachine.getState().getId() + " with Exception " + ex.toString());
myStateMachine.setStateMachineError(ex);
}
@AfterThrowing(pointcut = "execution(* org.springframework.statemachine.action.Action.execute(*))", throwing = "ex")
public void errorInterceptorAction(Exception ex) {
log.info("Error on Action: " + myStateMachine.getState().getId() + " with Exception " + ex.toString());
myStateMachine.setStateMachineError(ex);
}
}
在我启动 StateMachine 的控制器中,我做了类似的事情:
if(myStateMachine.hasStateMachineError()) {
// do something which is returning the ERROR.
}
仍然不是我想要的 100%,因为 statemachine.stop 从内部无法正常工作,但我正在处理它。