Initial reactive action support

- This first commit related to reactive action support basically changes internal
  logic away from original Action interface which really is just
  a Consumer<StateContext> but it originates pre jdk8 era.
  Reactive equivalent internally is now Function<StateContext<S, E>, Mono<Void>>.
- Essentially actions will now get executed with a reactor chain fully.
- Fix StateMachineExecutorTransit in AbstractStateMachine to be full reactive
  chain which were needed to get reactive actions working. This also put
  StateContextTests back to its original state.
- Add typesafe interface ReactiveAction which simply wraps
  Function<StateContext<S, E>, Mono<Void>> and add this to transitions with
  actionFunction() as a concept. This will be added to states in next
  commits if actionFunction() as a concept works.
- Polish various things and issues which were not addressed with initial reactive commit.
- Disable ActionSecurityTests for now as secured Action bean now breaks because it's
  internally wrapped into a Function and Spring Security doesn't see it anymore.
  Security like this needs a bit of a overhaul which can be done later.
- State do actions which are done via scheduling needs some work as now we just do
  a subscribe which is probably a bit wrong. There's going to be more work for
  scheduling so this also can be left later stages.
- Relates #743
This commit is contained in:
Janne Valkealahti
2019-05-06 15:23:31 +01:00
parent 07863c1c69
commit d8f1fc0155
52 changed files with 983 additions and 540 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 the original author or authors.
* Copyright 2016-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,11 +22,14 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.action.Actions;
import org.springframework.statemachine.action.SpelExpressionAction;
import org.springframework.statemachine.config.model.AbstractStateMachineModelFactory;
import org.springframework.statemachine.config.model.ChoiceData;
@@ -47,6 +50,8 @@ import org.springframework.statemachine.state.PseudoStateKind;
import org.springframework.statemachine.transition.TransitionKind;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
/**
* A generic {@link StateMachineModelFactory} which is backed by a Spring Data
* Repository abstraction.
@@ -89,7 +94,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
subStateMachineModel = build(submachineId);
}
Collection<Action<String, String>> stateActions = new ArrayList<Action<String, String>>();
Collection<Function<StateContext<String, String>, Mono<Void>>> stateActions = new ArrayList<>();
Set<? extends RepositoryAction> repositoryStateActions = s.getStateActions();
if (repositoryStateActions != null) {
for (RepositoryAction repositoryAction : repositoryStateActions) {
@@ -103,12 +108,12 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
action = new SpelExpressionAction<String, String>(parser.parseExpression(repositoryAction.getSpel()));
}
if (action != null) {
stateActions.add(action);
stateActions.add(Actions.from(action));
}
}
}
Collection<Action<String, String>> entryActions = new ArrayList<Action<String, String>>();
Collection<Function<StateContext<String, String>, Mono<Void>>> entryActions = new ArrayList<>();
Set<? extends RepositoryAction> repositoryEntryActions = s.getEntryActions();
if (repositoryEntryActions != null) {
for (RepositoryAction repositoryAction : repositoryEntryActions) {
@@ -122,12 +127,12 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
action = new SpelExpressionAction<String, String>(parser.parseExpression(repositoryAction.getSpel()));
}
if (action != null) {
stateActions.add(action);
stateActions.add(Actions.from(action));
}
}
}
Collection<Action<String, String>> exitActions = new ArrayList<Action<String, String>>();
Collection<Function<StateContext<String, String>, Mono<Void>>> exitActions = new ArrayList<>();
Set<? extends RepositoryAction> repositoryExitActions = s.getExitActions();
if (repositoryExitActions != null) {
for (RepositoryAction repositoryAction : repositoryExitActions) {
@@ -141,7 +146,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
action = new SpelExpressionAction<String, String>(parser.parseExpression(repositoryAction.getSpel()));
}
if (action != null) {
stateActions.add(action);
stateActions.add(Actions.from(action));
}
}
}
@@ -198,7 +203,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
for (RepositoryTransition t : transitionRepository.findByMachineId(machineId == null ? "" : machineId)) {
Collection<Action<String, String>> actions = new ArrayList<Action<String, String>>();
Collection<Function<StateContext<String, String>, Mono<Void>>> actions = new ArrayList<>();
Set<? extends RepositoryAction> repositoryActions = t.getActions();
if (repositoryActions != null) {
for (RepositoryAction repositoryAction : repositoryActions) {
@@ -212,7 +217,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
action = new SpelExpressionAction<String, String>(parser.parseExpression(repositoryAction.getSpel()));
}
if (action != null) {
actions.add(action);
actions.add(Actions.from(action));
}
}
}