gpt4 book ai didi

java - 未调用 join 后的 Spring Statemachine 内部转换操作

转载 作者:太空宇宙 更新时间:2023-11-04 09:49:28 25 4
gpt4 key购买 nike

我正在尝试使用forkjoin配置状态机。加入后,我想使用内部转换来调用加入状态上的操作。问题是为 withInternal() 配置的操作未触发。我尝试过 .guard(context -> true) hack,也尝试过 .timer().timerOnce(),但它也不起作用。

这里是配置的说明:

private void configureStates(StateMachineBuilder.Builder<String, String> builder) throws Exception {
builder.configureStates()
.withStates()
.initial("A")

.fork("B")
.join("C")

.state("A")
.state("B_")
.state("C")
.state("D")
.state("E")
.and()

.withStates()
.parent("B_")
.initial("B1")
.end("C1")
.and()

.withStates()
.parent("B_")
.initial("B2")
.end("C2")
.and()

.withStates()
.parent("B_")
.initial("B3")
.end("C3")

.end("E");
}

转换配置:

private void configureTransitions(StateMachineBuilder.Builder<String, String> builder) throws Exception {
builder.configureTransitions()
.withExternal()
.source("A")
.target("B")
.event("E0")
.action(context -> log.info("From A to B"))
.and()

.withInternal()
.source("B")
.guard(stateContext -> true)
.action(context -> log.info("At B"))
.timerOnce(50)
.and()

.withFork()
.source("B")
.target("B_")
.and()

.withExternal()
.source("B1")
.target("C1")
.event("E1")
.and()

.withExternal()
.source("B2")
.target("C2")
.event("E2")
.and()

.withExternal()
.source("B3")
.target("C3")
.and()

.withExternal()
.source("C3")
.target("A")
.event("E3")
.and()

.withJoin()
.source("B_")
.target("C")
.and()

.withInternal()
.source("C")
.guard(context -> true)
.action(context -> log.info("At C"))
.timerOnce(50)
.state("C")
.and()

.withExternal()
.source("C")
.target("D")
.action(context -> log.info("At D"))
.and()

.withInternal()
.source("D")
.guard(stateContext -> true)
.action(stateContext -> log.info("At internal D"))
.timer(10)
.and()

.withExternal()
.source("D")
.event("E4")
.target("E");
}

我还向状态机添加了一个监听器:

private StateMachineListener<String, String> listener() {
return new StateMachineListenerAdapter<String, String>() {
@Override
public void stateChanged(State<String, String> from, State<String, String> to) {
log.info("State transited from [{}] to [{}]",
from == null ? null : from.getId(),
to == null ? null : to.getId());
}
};
}

最终配置为:

private StateMachine<String, String> buildMachine() throws Exception {
StateMachineBuilder.Builder<String, String> builder = StateMachineBuilder.builder();

builder.configureConfiguration()
.withConfiguration()
.listener(listener())
.autoStartup(true);

configureStates(builder);

configureTransitions(builder);

return builder.build();
}

问题是没有调用任何内部转换操作。

我为给定的配置创建了一个小测试:

@Test
public void testForkJoin() throws Exception {
StateMachine<String, String> machine = buildMachine();

StateMachineTestPlan<String, String> plan = StateMachineTestPlanBuilder.<String, String>builder()
.defaultAwaitTime(3)
.stateMachine(machine)

.step()
.expectStates("A")
.and()

.step()
.sendEvent("E0")
.expectStates("B_", "B1", "B2", "C3")
.and()

.step()
.sendEvent("E1")
.expectStates("B_", "C1", "B2", "C3")
.and()

.step()
.sendEvent("E3")
.expectState("A")
.and()

.step()
.sendEvent("E0")
.expectStates("B_", "B1", "B2", "C3")
.and()

.step()
.sendEvent("E1")
.expectStates("B_", "C1", "B2", "C3")
.and()

.step()
.sendEvent("E2")
.expectStates("D")
.and()

.step()
.sendEvent("E4")
.expectState("E")
.and()

.build();

plan.test();
}

作为解决方法,我添加了几个外部转换(从 CD),但事实是我想省略状态 D 并通过执行现有操作作为内部转换操作来直接转换到 E

最佳答案

I would like to omit state D and transit directly to E by executingthe existing actions as an internal transition action.

简短回答:你不能。

Fork/Join 伪状态不应引入行为规范(例如 Action)。 Fork/Join 仅用于对 SM( transient 伪状态)中的并行操作(fork)和同步(join)进行建模。

Spring 状态机实现遵循 UML specification因此,与 fork/join 相关的操作不会被执行。

操作与特定的转换或状态相关联。

与转换相关的操作:

进行 JOIN 时,您可能有 N (>=2) 个源(J1E、J2E - 该其他区域的最后阶段),因此可以在从 J1E 过渡到 JOIN 阶段 (action=A1) 以及从 J2E 过渡到 JOIN 阶段 (action=A2) 时定义不同的操作。

与状态相关的操作:

如果您有一个需要在并行操作同步后执行的常见操作,您可以将其定义为下一个转换的一部分(例如,我相信您的 SM 案例是从 C 转换到 D 时)。

关于java - 未调用 join 后的 Spring Statemachine 内部转换操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54970154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com