Java 访问bean时执行Spring状态机操作会导致状态机终止
我正在尝试创建一个状态机,它将通过一系列状态触发特定状态的进入操作,并与状态转换拦截器相结合 为了测试这个状态机,我创建了一个springboot集成测试,它向一个集成通道提供一条消息,该通道反过来调用这个状态机。我注意到的是,当操作发生时,当它开始与“存储库”bean交互时,它将导致状态机退出,集成测试失败。我在日志中没有看到任何错误,但是当我引入“error”操作时,状态机操作的行为与预期的一样 我曾尝试将断点应用于拦截器,但我注意到,当测试由于断点而停止时,在到达repository.save(entity)行时,它将允许测试向前移动,就像我在断点上点击play一样,但调试器本身在操作中保持不变 当我引入errorAction()时,状态机将正常工作。我真的不知道为什么错误操作会导致机器正常完成 配置如下Java 访问bean时执行Spring状态机操作会导致状态机终止,java,spring,spring-statemachine,Java,Spring,Spring Statemachine,我正在尝试创建一个状态机,它将通过一系列状态触发特定状态的进入操作,并与状态转换拦截器相结合 为了测试这个状态机,我创建了一个springboot集成测试,它向一个集成通道提供一条消息,该通道反过来调用这个状态机。我注意到的是,当操作发生时,当它开始与“存储库”bean交互时,它将导致状态机退出,集成测试失败。我在日志中没有看到任何错误,但是当我引入“error”操作时,状态机操作的行为与预期的一样 我曾尝试将断点应用于拦截器,但我注意到,当测试由于断点而停止时,在到达repository.sa
@Configuration
@EnableStateMachineFactory
public class NotificationStateMachineConfiguration
extends StateMachineConfigurerAdapter<NotificationState, NotificationEvent> {
private static final Logger LOGGER =
LoggerFactory.getLogger(NotificationStateMachineConfiguration.class);
@Autowired
private SendingAction sendingAction;
@Autowired
private TransformationAction transformationAction;
@Override
public void configure(
StateMachineConfigurationConfigurer<NotificationState, NotificationEvent> config)
throws Exception {
config.withConfiguration()
.autoStartup(false)
.taskExecutor(new SyncTaskExecutor())
.listener(new StateMachineListenerAdapter<NotificationState, NotificationEvent>() {
@Override
public void stateChanged(State<NotificationState, NotificationEvent> from,
State<NotificationState, NotificationEvent> to) {
LOGGER.trace("StateChanged - From: {}, To: {}", from, to);
}
});
}
@Override
public void configure(
StateMachineStateConfigurer<NotificationState, NotificationEvent> states) throws Exception {
states.withStates()
.initial(NotificationState.NEW)
.state(NotificationState.NEW)
.state(NotificationState.TRANSFORMING,transformationAction,errorAction())
.state(NotificationState.TRANSFORMATION_FAILED)
.state(NotificationState.SENDING,sendingAction, errorAction())
.state(NotificationState.STAGED)
.state(NotificationState.AWAITING)
.end(NotificationState.NOT_SENT)
.end(NotificationState.RESPONSE_RECEIVED)
.end(NotificationState.ERRORS)
.end(NotificationState.NEGATIVE_RESPONCE_RECIEVED)
.end(NotificationState.SENT);
}
@Override
public void configure(
StateMachineTransitionConfigurer<NotificationState, NotificationEvent> transitions)
throws Exception {
transitions
.withExternal()
.source(NotificationState.NEW).target(NotificationState.TRANSFORMING)
.event(NotificationEvent.TRANSFORMATION_REQUESTED)
.and()
.withExternal()
.source(NotificationState.TRANSFORMING).target(NotificationState.SENDING)
.event(NotificationEvent.TRANSFORMATION_SUCCESSFULL)
.and()
.withExternal()
.source(NotificationState.TRANSFORMING).target(NotificationState.TRANSFORMATION_FAILED)
.event(NotificationEvent.TRANSFORMATION_FAILURE)
.and()
.withExternal()
.source(NotificationState.SENDING).target(NotificationState.AWIATING)
.event(NotificationEvent.PROOF_OF_DELIVERY_RELEASE_REQUESTED)
.and()
.withExternal()
.source(NotificationState.SENDING).target(NotificationState.SENT)
.event(NotificationEvent.RELEASE_REQUESTED)
.and()
.withExternal()
.source(NotificationState.SENDING).target(NotificationState.STAGED)
.event(NotificationEvent.STAGE_NOTIFICATION_REQUESTED);
}
<!-- if i remove this bean the state machine dies within the interceptor when i try to utilize the repository -->
@Bean
public Action<NotificationState, NotificationEvent> errorAction() {
return context -> {
// RuntimeException("MyError") added to context
Exception exception = context.getException();
LOGGER.error(Optional.ofNullable(exception).map(Exception::getMessage)
.orElse("NO ERROR"));
};
}
}
@配置
@EnableStateMachineFactory
公共类通知状态机配置
扩展StateMachineConfigureAdapter{
专用静态最终记录器=
getLogger(NotificationStateMachineConfiguration.class);
@自动连线
私有发送操作发送操作;
@自动连线
私人转型行动转型行动;
@凌驾
公共无效配置(
StateMachineConfiguration配置器(配置)
抛出异常{
config.withConfiguration()
.AutoStart(错误)
.taskExecutor(新的SyncTaskExecutor())
.listener(新StateMachineListenerAdapter(){
@凌驾
公共无效状态已更改(状态从,
国家(至){
trace(“StateChanged-From:{},To:{}”,From,To);
}
});
}
@凌驾
公共无效配置(
StateMachineStateConfigurer状态)引发异常{
states.with states()
.首字母(NotificationState.NEW)
.state(NotificationState.NEW)
.state(NotificationState.TRANSFORMING、transformationAction、errorAction())
.state(NotificationState.TRANSFORMATION_失败)
.state(NotificationState.SENDING、sendingAction、errorAction())
.state(NotificationState.STAGED)
.state(NotificationState.waiting)
.end(NotificationState.NOT_SENT)
.end(NotificationState.RESPONSE_已收到)
.end(NotificationState.ERRORS)
.end(NotificationState.NEGATIVE\u Response\u Received)
.end(NotificationState.SENT);
}
@凌驾
公共无效配置(
StateMachineTransitionConfigurer转换)
抛出异常{
过渡
.withExternal()
.source(NotificationState.NEW).target(NotificationState.TRANSFORMING)
.event(NotificationEvent.TRANSFORMATION_请求)
.及()
.withExternal()
.source(NotificationState.TRANSFORMING).target(NotificationState.SENDING)
.event(NotificationEvent.TRANSFORMATION_成功)
.及()
.withExternal()
.source(NotificationState.TRANSFORMING).target(NotificationState.TRANSFORMATION_失败)
.event(NotificationEvent.TRANSFORMATION_失败)
.及()
.withExternal()
.source(NotificationState.SENDING).target(NotificationState.AWIATING)
.事件(通知事件.要求提供交货证明和放行证明)
.及()
.withExternal()
.source(NotificationState.SENDING).target(NotificationState.SENT)
.event(NotificationEvent.RELEASE_请求)
.及()
.withExternal()
.source(NotificationState.SENDING).target(NotificationState.STAGED)
.事件(通知事件。请求阶段通知);
}
@豆子
公共行动{
返回上下文->{
//已将运行时异常(“MyError”)添加到上下文中
Exception=context.getException();
LOGGER.error(可选)of nullable(exception).map(exception::getMessage)
.orElse(“无错误”);
};
}
}
拦截豆
@Component
public class NotificationStateInterceptor extends
StateMachineInterceptorAdapter<NotificationState, NotificationEvent> {
private static final Logger logger =
LoggerFactory.getLogger(NotificationStateInterceptor.class.getName());
private final NotificationRepository repository ;
public NotificationStateInterceptor(NotificationRepository repository) {
this.repository = eventProducrepositoryer;
}
/**
* Persist the notification that just changed state.
*
* @param state the notification has just changed to.
* @param message that triggered the state change.
* @param transition that was triggered during the stage change.
* @param stateMachine that is managing the notification's state.
*/
@Override
public void postStateChange(
State<NotificationState, NotificationEvent> state,
Message<NotificationEvent> message,
Transition<NotificationState, NotificationEvent> transition,
StateMachine<NotificationState, NotificationEvent> stateMachine) {
/* trigger the more descriptive version */
this.postStateChange(state, message, transition, stateMachine, null);
}
/**
* Persist the notification that just changed state.
*
* @param state the notification has just changed to.
* @param message that triggered the state change.
* @param transition that was triggered during the stage change.
* @param stateMachine that is managing the notification's state.
* @param rootStateMachine in the event that this is a nested state machine.
*/
@Override
public void postStateChange(
State<NotificationState, NotificationEvent> state,
Message<NotificationEvent> message,
Transition<NotificationState, NotificationEvent> transition,
StateMachine<NotificationState, NotificationEvent> stateMachine,
StateMachine<NotificationState, NotificationEvent> rootStateMachine) {
Notification notification = getNotification(stateMachine);
if (transition.getKind() != TransitionKind.INITIAL) {
if (notification != null) {
logger.debug(
"Transitioning Notification: " + notification.getId()
+ " to State: " + state.getId());
notification.applyNewState(state.getId());
repository.save(notification);
}
}
}
}
@组成部分
公共类NotificationStateInterceptor扩展
StateMachineInterceptor适配器{
专用静态最终记录器=
LoggerFactory.getLogger(NotificationStateInterceptor.class.getName());
私有最终通知存储库;
公共NotificationStateInterceptor(NotificationRepository存储库){
this.repository=eventProducrepositoryer;
}
/**
*保留刚刚更改状态的通知。
*
*@param状态通知刚更改为。
*@param触发状态更改的消息。
*在阶段更改期间触发的@param转换。
*@param stateMachine正在管理通知的状态。
*/
@凌驾
公共无效状态更改(
国家,,
消息消息,
过渡,,
状态机(StateMachine){
/*触发更具描述性的版本*/
this.postStateChange(状态、消息、转换、状态机、null);
}
/**
*保留刚刚更改状态的通知。
*
*@param状态通知刚更改为。
*@param触发状态更改的消息。
*在阶段更改期间触发的@param转换。
*@param stateMachine正在管理通知的状态。
*@param rootStateMachine,如果这是嵌套状态机。
*/
@凌驾
公共无效状态更改(
国家,,
消息消息,
过渡,,
状态机状态机,
状态机(根状态机){
通知