坚持与坚持在Spring Statemachine中恢复当前状态 [英] Persisting & Restoring Current State in Spring Statemachine

查看:448
本文介绍了坚持与坚持在Spring Statemachine中恢复当前状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将Spring Statemachine引入现有项目中,希望合并和阐明我们的业务逻辑.我们有各种具有互连状态的JPA实体,我在将持久状态设置为现有状态机的当前状态时遇到了一些麻烦.

I'm introducing Spring Statemachine into an existing project, with the hope of amalgamating and clarifying our business logic. We have various JPA entities with interconnected states and I'm having some trouble with setting a persisted state as the current state of an existing state machine.

我正在使用StateMachineFactory为每个实体实例创建一个新的StateMachine实例.我将StateMachine的当前状态存储在一个单独的字段中,以使Hibernate能够持久保存,并且理想情况下需要将持久化字段的值与StateMachine同步.我的问题是在Spring Statemachine中通常应如何实现.

I'm using a StateMachineFactory to create a new StateMachine instance for each entity instance. I'm storing the current state of the StateMachine in a separate field for Hibernate to persist and ideally need to sync the value of the persisted field with the StateMachine. My question is around how this should be typically achieved in Spring Statemachine.

@Entity
@EntityListeners(MyEntityListener.class)
public class MyEntity {

    @Column
    private MyState internalState; // Using AttributeConverter

    @Transient
    private StateMachine<MyState, Event> stateMachine;

}

public class MyEntityListener {

    @PostLoad
    public void postLoad(MyEntity entity) {
        // TODO Set StateMachine's current state to entity's internal state
    );

}

  1. 一种方法可能是定义局部转换,以将初始状态移动到持久状态.然后,我可以进行条件检查,以找到与本地转换相关的事件,该事件会将源状态转换为目标状态.对我来说,这似乎有些混乱,我想保持状态机的配置尽可能整洁.

  1. One approach may be to define local transitions to move the initial state into the persisted state. I could then do a conditional check to find an event tied to a local transition, which would move the source state into the target state. This seems a little messy to me and I'd like to keep my state machine's configuration as clean as possible.

我看不到如何通过公共API设置StateMachine的当前状态而不进行过渡,因此,我探索的另一种方法是包装StateMachine实例以暴露以下方法(因为它很方便默认范围):

I can't see how I can set the StateMachine's current state through a public API without moving through a transition and so another approach I explored is to wrap the StateMachine instance to expose the following method (as it's conveniently default scope):

package org.springframework.statemachine.support;

public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSupport<S, E> implements StateMachine<S, E>, StateMachineAccess<S, E> {

    void setCurrentState(State<S, E> state, Message<E> message, Transition<S, E> transition, boolean exit, StateMachine<S, E> stateMachine)

}

package org.springframework.statemachine.support;

public class MyStateMachineWrapper<S, E> {

    private AbstractStateMachine<S, E> stateMachine;

    public MyStateMachineWrapper(StateMachine<S, E> stateMachine) {
        if (stateMachine instanceof AbstractStateMachine) {
            this.stateMachine = (AbstractStateMachine<S, E>)stateMachine;
        } else {
            throw new IllegalArgumentException("Provided StateMachine is not a valid type");
        }
    }

    public void setCurrentState(S status) {
        stateMachine.setCurrentState(findState(status), null, null, false, stateMachine);
    }

    private State<S, E> findState(S status) {
        for (State<S, E> state : stateMachine.getStates()) {
            if (state.getId() == status) {
                return state;
            }
        }

        throw new IllegalArgumentException("Specified status does not equate to valid State");
    }
}

然后我可以将以下代码放入 MyEntityListener.postLoad 中:

I could then throw the following code into MyEntityListener.postLoad:

MyStateMachineWrapper<MyState, Event> myStateMachineWrapper = new MyStateMachineWrapper<>(entity.getStateMachine());
myStateMachineWrapper.setCurrentState(entity.getInternalState());

上述方法似乎可以正常工作,但是我无法想象这就是它预期的工作方式.当然,有一种更清洁的方法可以实现这一目标,或者该项目还不够成熟并且还不包括此功能?

The above approach seems to work fine but I can't imagine this is how it was envisioned to work. Surely there's a cleaner method to achieve this or maybe the project isn't mature enough and doesn't include this functionality yet?

感谢您的任何想法和意见.

Thanks for any thoughts and opinions.

推荐答案

我已经清理了上面的选项#2,将包装器类更改为utils类.需要明确的是,这种方法利用了具有默认访问器的setCurrentState方法的优势,因此这可能最终是一个脆弱的解决方案.

I've cleaned up option #2 above, changing the wrapper class to a utils class. To be clear, this approach takes advantage of the setCurrentState method having a default accessor and so this may end up being a brittle solution.

package org.springframework.statemachine.support;

public abstract class MyStateMachineUtils extends StateMachineUtils {

    public static <S, E> void setCurrentState(StateMachine<S, E> stateMachine, S state) {
        if (stateMachine instanceof AbstractStateMachine) {
            setCurrentState((AbstractStateMachine<S, E>)stateMachine, state);
        } else {
            throw new IllegalArgumentException("Provided StateMachine is not a valid type");
        }
    }

    public static <S, E> void setCurrentState(AbstractStateMachine<S, E> stateMachine, S state) {
        stateMachine.setCurrentState(findState(stateMachine, state), null, null, false, stateMachine);
    }

    private static <S, E> State<S, E> findState(AbstractStateMachine<S, E> stateMachine, S stateId) {
        for (State<S, E> state : stateMachine.getStates()) {
            if (state.getId() == stateId) {
                return state;
            }
        }

        throw new IllegalArgumentException("Specified State ID is not valid");
    }
}

然后可以像这样很好地使用它:

This can then be used quite nicely like so:

MyStateMachineUtils.setCurrentState(entity.getStateMachine(), entity.getInternalState());

这篇关于坚持与坚持在Spring Statemachine中恢复当前状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆