Allow user to use machine id
- change original id to uuid. - This new id is now for user disposal. - Currently only meant for a top-level machine. - Can be set via annotation config, model classes or via new StateMachineFactory.getStateMachine(String). - Is persisted with DefaultStateMachinePersister and StateMachineContext. - Related new tests in ConfigurationTests and StateMachinePersistTests3. - Fixes #186
This commit is contained in:
@@ -28,6 +28,13 @@ import java.util.Map;
|
||||
*/
|
||||
public interface StateMachineContext<S, E> {
|
||||
|
||||
/**
|
||||
* Gets the machine id.
|
||||
*
|
||||
* @return the machine id
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Gets the child contexts if any.
|
||||
*
|
||||
|
||||
@@ -112,9 +112,14 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StateMachine<S, E> getStateMachine() {
|
||||
return getStateMachine(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StateMachine<S, E> getStateMachine(String machineId) {
|
||||
if (stateMachineModel.getConfigurationData().isVerifierEnabled()) {
|
||||
StateMachineModelVerifier<S, E> verifier = stateMachineModel.getConfigurationData().getVerifier();
|
||||
if (verifier == null) {
|
||||
@@ -173,7 +178,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
for (Collection<StateData<S, E>> regionStateDatas : regionsStateDatas) {
|
||||
machine = buildMachine(machineMap, stateMap, regionStateDatas, transitionsData, resolveBeanFactory(),
|
||||
contextEvents, defaultExtendedState, stateMachineModel.getTransitionsData(), resolveTaskExecutor(),
|
||||
resolveTaskScheduler());
|
||||
resolveTaskScheduler(), machineId);
|
||||
regionStack.push(new MachineStackItem<S, E>(machine));
|
||||
}
|
||||
|
||||
@@ -192,14 +197,16 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
Collection<State<S, E>> states = new ArrayList<State<S, E>>();
|
||||
states.add(rstate);
|
||||
Transition<S, E> initialTransition = new InitialTransition<S, E>(rstate);
|
||||
StateMachine<S, E> m = buildStateMachineInternal(states, new ArrayList<Transition<S, E>>(), rstate,
|
||||
initialTransition, null, defaultExtendedState, null, contextEvents, resolveBeanFactory(),
|
||||
resolveTaskExecutor(), resolveTaskScheduler(), beanName);
|
||||
StateMachine<S, E> m = buildStateMachineInternal(states, new ArrayList<Transition<S, E>>(), rstate, initialTransition,
|
||||
null, defaultExtendedState, null, contextEvents, resolveBeanFactory(), resolveTaskExecutor(),
|
||||
resolveTaskScheduler(), beanName,
|
||||
machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId());
|
||||
machine = m;
|
||||
}
|
||||
} else {
|
||||
machine = buildMachine(machineMap, stateMap, stateDatas, transitionsData, resolveBeanFactory(),
|
||||
contextEvents, defaultExtendedState, stateMachineModel.getTransitionsData(), resolveTaskExecutor(), resolveTaskScheduler());
|
||||
machine = buildMachine(machineMap, stateMap, stateDatas, transitionsData, resolveBeanFactory(), contextEvents,
|
||||
defaultExtendedState, stateMachineModel.getTransitionsData(), resolveTaskExecutor(), resolveTaskScheduler(),
|
||||
machineId);
|
||||
if (peek.isInitial() || (!peek.isInitial() && !machineMap.containsKey(peek.getParent()))) {
|
||||
machineMap.put(peek.getParent(), machine);
|
||||
}
|
||||
@@ -395,7 +402,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
Collection<StateData<S, E>> stateDatas, Collection<TransitionData<S, E>> transitionsData,
|
||||
BeanFactory beanFactory, Boolean contextEvents, DefaultExtendedState defaultExtendedState,
|
||||
TransitionsData<S, E> stateMachineTransitions, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheduler) {
|
||||
TaskScheduler taskScheduler, String machineId) {
|
||||
State<S, E> state = null;
|
||||
State<S, E> initialState = null;
|
||||
PseudoState<S, E> historyState = null;
|
||||
@@ -579,7 +586,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
Transition<S, E> initialTransition = new InitialTransition<S, E>(initialState, initialAction);
|
||||
StateMachine<S, E> machine = buildStateMachineInternal(states, transitions, initialState, initialTransition,
|
||||
null, defaultExtendedState, historyState, contextEvents, beanFactory, taskExecutor, taskScheduler,
|
||||
beanName);
|
||||
beanName, machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId());
|
||||
return machine;
|
||||
}
|
||||
|
||||
@@ -587,7 +594,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
Collection<Transition<S, E>> transitions, State<S, E> initialState, Transition<S, E> initialTransition,
|
||||
Message<E> initialEvent, ExtendedState extendedState, PseudoState<S, E> historyState,
|
||||
Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheduler, String beanName);
|
||||
TaskScheduler taskScheduler, String beanName, String machineId);
|
||||
|
||||
protected abstract State<S, E> buildStateInternal(S id, Collection<E> deferred, Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions,
|
||||
PseudoState<S, E> pseudoState);
|
||||
|
||||
@@ -59,9 +59,10 @@ public class ObjectStateMachineFactory<S, E> extends AbstractStateMachineFactory
|
||||
Collection<Transition<S, E>> transitions, State<S, E> initialState, Transition<S, E> initialTransition,
|
||||
Message<E> initialEvent, ExtendedState extendedState, PseudoState<S, E> historyState,
|
||||
Boolean contextEventsEnabled, BeanFactory beanFactory, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheduler, String beanName) {
|
||||
TaskScheduler taskScheduler, String beanName, String machineId) {
|
||||
ObjectStateMachine<S, E> machine = new ObjectStateMachine<S, E>(states, transitions, initialState, initialTransition, initialEvent,
|
||||
extendedState);
|
||||
machine.setId(machineId);
|
||||
machine.setHistoryState(historyState);
|
||||
if (contextEventsEnabled != null) {
|
||||
machine.setContextEventsEnabled(contextEventsEnabled);
|
||||
@@ -73,7 +74,7 @@ public class ObjectStateMachineFactory<S, E> extends AbstractStateMachineFactory
|
||||
machine.setTaskExecutor(taskExecutor);
|
||||
}
|
||||
if (taskScheduler != null) {
|
||||
machine.setTaskScheduler(taskScheduler);;
|
||||
machine.setTaskScheduler(taskScheduler);
|
||||
}
|
||||
if (machine instanceof BeanNameAware) {
|
||||
((BeanNameAware)machine).setBeanName(beanName);
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.springframework.statemachine.StateMachine;
|
||||
|
||||
/**
|
||||
* {@code StateMachineFactory} is a strategy interface building {@link StateMachine}s.
|
||||
*
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
@@ -29,9 +29,17 @@ public interface StateMachineFactory<S, E> {
|
||||
|
||||
/**
|
||||
* Build a new {@link StateMachine} instance.
|
||||
*
|
||||
*
|
||||
* @return a new state machine instance.
|
||||
*/
|
||||
StateMachine<S, E> getStateMachine();
|
||||
|
||||
/**
|
||||
* Build a new {@link StateMachine} instance
|
||||
* with a given machine id.
|
||||
*
|
||||
* @param machineId the machine id
|
||||
* @return a new state machine instance.
|
||||
*/
|
||||
StateMachine<S, E> getStateMachine(String machineId);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ public class StateMachineConfigurationBuilder<S, E>
|
||||
extends AbstractConfiguredAnnotationBuilder<ConfigurationData<S, E>, StateMachineConfigurationConfigurer<S, E>, StateMachineConfigurationBuilder<S, E>>
|
||||
implements StateMachineConfigurationConfigurer<S, E> {
|
||||
|
||||
private String machineId;
|
||||
private BeanFactory beanFactory;
|
||||
private TaskExecutor taskExecutor;
|
||||
private TaskScheduler taskScheculer;
|
||||
@@ -117,7 +118,16 @@ public class StateMachineConfigurationBuilder<S, E>
|
||||
protected ConfigurationData<S, E> performBuild() throws Exception {
|
||||
return new ConfigurationData<S, E>(beanFactory, taskExecutor, taskScheculer, autoStart, ensemble, listeners,
|
||||
securityEnabled, transitionSecurityAccessDecisionManager, eventSecurityAccessDecisionManager, eventSecurityRule,
|
||||
transitionSecurityRule, verifierEnabled, verifier);
|
||||
transitionSecurityRule, verifierEnabled, verifier, machineId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the machine id.
|
||||
*
|
||||
* @param machineId the new machine id
|
||||
*/
|
||||
public void setMachineId(String machineId) {
|
||||
this.machineId = machineId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.statemachine.config.configurers;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerBuilder;
|
||||
import org.springframework.statemachine.listener.StateMachineListener;
|
||||
@@ -33,6 +34,15 @@ import org.springframework.statemachine.listener.StateMachineListener;
|
||||
public interface ConfigurationConfigurer<S, E> extends
|
||||
AnnotationConfigurerBuilder<StateMachineConfigurationConfigurer<S, E>> {
|
||||
|
||||
/**
|
||||
* Specify a machine identifier.
|
||||
*
|
||||
* @param id the machine identifier
|
||||
* @return configurer for chaining
|
||||
* @see StateMachine#getId()
|
||||
*/
|
||||
ConfigurationConfigurer<S, E> machineId(String id);
|
||||
|
||||
/**
|
||||
* Specify a {@link BeanFactory}.
|
||||
*
|
||||
|
||||
@@ -39,6 +39,7 @@ public class DefaultConfigurationConfigurer<S, E>
|
||||
extends AnnotationConfigurerAdapter<ConfigurationData<S, E>, StateMachineConfigurationConfigurer<S, E>, StateMachineConfigurationBuilder<S, E>>
|
||||
implements ConfigurationConfigurer<S, E> {
|
||||
|
||||
private String machineId;
|
||||
private BeanFactory beanFactory;
|
||||
private TaskExecutor taskExecutor;
|
||||
private TaskScheduler taskScheculer;
|
||||
@@ -47,6 +48,7 @@ public class DefaultConfigurationConfigurer<S, E>
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationBuilder<S, E> builder) throws Exception {
|
||||
builder.setMachineId(machineId);
|
||||
builder.setBeanFactory(beanFactory);
|
||||
builder.setTaskExecutor(taskExecutor);
|
||||
builder.setTaskScheculer(taskScheculer);
|
||||
@@ -54,6 +56,12 @@ public class DefaultConfigurationConfigurer<S, E>
|
||||
builder.setStateMachineListeners(listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationConfigurer<S, E> machineId(String id) {
|
||||
this.machineId = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationConfigurer<S, E> beanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.statemachine.security.SecurityRule;
|
||||
*/
|
||||
public class ConfigurationData<S, E> {
|
||||
|
||||
private final String machineId;
|
||||
private final BeanFactory beanFactory;
|
||||
private final TaskExecutor taskExecutor;
|
||||
private final TaskScheduler taskScheduler;
|
||||
@@ -60,7 +61,7 @@ public class ConfigurationData<S, E> {
|
||||
*/
|
||||
public ConfigurationData() {
|
||||
this(null, new SyncTaskExecutor(), new ConcurrentTaskScheduler(), false, null, new ArrayList<StateMachineListener<S, E>>(), false,
|
||||
null, null, null, null, true, new DefaultStateMachineModelVerifier<S, E>());
|
||||
null, null, null, null, true, new DefaultStateMachineModelVerifier<S, E>(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,13 +80,14 @@ public class ConfigurationData<S, E> {
|
||||
* @param transitionSecurityRule the transition security rule
|
||||
* @param verifierEnabled the verifier enabled flag
|
||||
* @param verifier the state machine model verifier
|
||||
* @param machineId the machine id
|
||||
*/
|
||||
public ConfigurationData(BeanFactory beanFactory, TaskExecutor taskExecutor,
|
||||
TaskScheduler taskScheduler, boolean autoStart, StateMachineEnsemble<S, E> ensemble,
|
||||
List<StateMachineListener<S, E>> listeners, boolean securityEnabled,
|
||||
AccessDecisionManager transitionSecurityAccessDecisionManager, AccessDecisionManager eventSecurityAccessDecisionManager,
|
||||
SecurityRule eventSecurityRule, SecurityRule transitionSecurityRule, boolean verifierEnabled,
|
||||
StateMachineModelVerifier<S, E> verifier) {
|
||||
StateMachineModelVerifier<S, E> verifier, String machineId) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.taskExecutor = taskExecutor;
|
||||
this.taskScheduler = taskScheduler;
|
||||
@@ -99,6 +101,11 @@ public class ConfigurationData<S, E> {
|
||||
this.transitionSecurityRule = transitionSecurityRule;
|
||||
this.verifierEnabled = verifierEnabled;
|
||||
this.verifier = verifier;
|
||||
this.machineId = machineId;
|
||||
}
|
||||
|
||||
public String getMachineId() {
|
||||
return machineId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.statemachine.ensemble;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -105,7 +106,7 @@ public class DistributedStateMachine<S, E> extends LifecycleObjectSupport implem
|
||||
// adding state machine id to the message so that
|
||||
// listeners can know from where a state change originates
|
||||
return delegate.sendEvent(MessageBuilder.fromMessage(event)
|
||||
.setHeader(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER, delegate.getId()).build());
|
||||
.setHeader(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER, delegate.getUuid()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,6 +169,11 @@ public class DistributedStateMachine<S, E> extends LifecycleObjectSupport implem
|
||||
return delegate.getStateMachineAccessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return delegate.getUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return delegate.getId();
|
||||
@@ -198,7 +204,7 @@ public class DistributedStateMachine<S, E> extends LifecycleObjectSupport implem
|
||||
}
|
||||
// only handle if state change originates from this dist machine
|
||||
if (message != null
|
||||
&& ObjectUtils.nullSafeEquals(delegate.getId(),
|
||||
&& ObjectUtils.nullSafeEquals(delegate.getUuid(),
|
||||
message.getHeaders().get(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER))) {
|
||||
ensemble.setState(new DefaultStateMachineContext<S, E>(transition.getTarget().getId(), message
|
||||
.getPayload(), message.getHeaders(), stateMachine.getExtendedState()));
|
||||
@@ -220,7 +226,7 @@ public class DistributedStateMachine<S, E> extends LifecycleObjectSupport implem
|
||||
// only handle if state change originates from this dist machine
|
||||
if (stateContext.getTransition() != null
|
||||
&& stateContext.getTransition().getKind() == TransitionKind.INTERNAL
|
||||
&& ObjectUtils.nullSafeEquals(delegate.getId(),
|
||||
&& ObjectUtils.nullSafeEquals(delegate.getUuid(),
|
||||
stateContext.getMessageHeader(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER))) {
|
||||
StateMachineContext<S, E> current = ensemble.getState();
|
||||
if (current != null) {
|
||||
@@ -276,7 +282,7 @@ public class DistributedStateMachine<S, E> extends LifecycleObjectSupport implem
|
||||
});
|
||||
}
|
||||
log.info("Requesting to start delegating state machine " + delegate);
|
||||
log.info("Delegating machine id " + delegate.getId());
|
||||
log.info("Delegating machine id " + delegate.getUuid());
|
||||
delegate.start();
|
||||
}
|
||||
}
|
||||
@@ -292,7 +298,7 @@ public class DistributedStateMachine<S, E> extends LifecycleObjectSupport implem
|
||||
@Override
|
||||
public void stateChanged(StateMachineContext<S, E> context) {
|
||||
// do not pass if state change was originated from this dist machine
|
||||
if (!ObjectUtils.nullSafeEquals(delegate.getId(),
|
||||
if (!ObjectUtils.nullSafeEquals(delegate.getUuid(),
|
||||
context.getEventHeaders().get(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER))) {
|
||||
delegate.sendEvent(MessageBuilder.withPayload(context.getEvent())
|
||||
.copyHeaders(context.getEventHeaders()).build());
|
||||
|
||||
@@ -129,6 +129,6 @@ public abstract class AbstractStateMachinePersister<S, E, T> implements StateMac
|
||||
}
|
||||
}
|
||||
}
|
||||
return new DefaultStateMachineContext<S, E>(childs, id, null, null, extendedState, historyStates);
|
||||
return new DefaultStateMachineContext<S, E>(childs, id, null, null, extendedState, historyStates, stateMachine.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.statemachine.region;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.statemachine.listener.StateMachineListener;
|
||||
@@ -38,6 +39,15 @@ public interface Region<S, E> {
|
||||
*
|
||||
* @return the region and state machine unique id
|
||||
*/
|
||||
UUID getUuid();
|
||||
|
||||
/**
|
||||
* Gets the region and state machine id. This identifier
|
||||
* is provided for users disposal and can be set from
|
||||
* a various ways to build a machines.
|
||||
*
|
||||
* @return the region and state machine id
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,7 +100,9 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
|
||||
private Boolean initialEnabled = null;
|
||||
|
||||
private String id = UUID.randomUUID().toString();
|
||||
private UUID uuid = UUID.randomUUID();
|
||||
|
||||
private String id;
|
||||
|
||||
private volatile Message<E> forwardedInitialEvent;
|
||||
|
||||
@@ -490,6 +492,8 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
if (currentState != null) {
|
||||
buf.append(StringUtils.collectionToCommaDelimitedString(currentState.getIds()));
|
||||
}
|
||||
buf.append(" / uuid=");
|
||||
buf.append(uuid);
|
||||
buf.append(" / id=");
|
||||
buf.append(id);
|
||||
return buf.toString();
|
||||
@@ -507,6 +511,7 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Request to reset state machine: stateMachine=[" + this + "] stateMachineContext=[" + stateMachineContext + "]");
|
||||
}
|
||||
setId(stateMachineContext.getId());
|
||||
S state = stateMachineContext.getState();
|
||||
boolean stateSet = false;
|
||||
// handle state reset
|
||||
@@ -622,11 +627,25 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
stateMachineExecutor.addStateMachineInterceptor(interceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the machine id.
|
||||
*
|
||||
* @param id the new machine id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
protected synchronized boolean acceptEvent(Message<E> message) {
|
||||
if ((currentState != null && currentState.shouldDefer(message))) {
|
||||
log.info("Current state " + currentState + " deferred event " + message);
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.statemachine.StateMachineContext;
|
||||
*/
|
||||
public class DefaultStateMachineContext<S, E> implements StateMachineContext<S, E> {
|
||||
|
||||
private final String id;
|
||||
private final List<StateMachineContext<S, E>> childs;
|
||||
private final S state;
|
||||
private final Map<S, S> historyStates;
|
||||
@@ -66,6 +67,21 @@ public class DefaultStateMachineContext<S, E> implements StateMachineContext<S,
|
||||
this(new ArrayList<StateMachineContext<S, E>>(), state, event, eventHeaders, extendedState, historyStates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new default state machine context.
|
||||
*
|
||||
* @param state the state
|
||||
* @param event the event
|
||||
* @param eventHeaders the event headers
|
||||
* @param extendedState the extended state
|
||||
* @param historyStates the history state mappings
|
||||
* @param id the machine id
|
||||
*/
|
||||
public DefaultStateMachineContext(S state, E event, Map<String, Object> eventHeaders, ExtendedState extendedState,
|
||||
Map<S, S> historyStates, String id) {
|
||||
this(new ArrayList<StateMachineContext<S, E>>(), state, event, eventHeaders, extendedState, historyStates, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new default state machine context.
|
||||
*
|
||||
@@ -92,12 +108,34 @@ public class DefaultStateMachineContext<S, E> implements StateMachineContext<S,
|
||||
*/
|
||||
public DefaultStateMachineContext(List<StateMachineContext<S, E>> childs, S state, E event,
|
||||
Map<String, Object> eventHeaders, ExtendedState extendedState, Map<S, S> historyStates) {
|
||||
this(childs, state, event, eventHeaders, extendedState, historyStates, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new default state machine context.
|
||||
*
|
||||
* @param childs the child state machine contexts
|
||||
* @param state the state
|
||||
* @param event the event
|
||||
* @param eventHeaders the event headers
|
||||
* @param extendedState the extended state
|
||||
* @param historyStates the history state mappings
|
||||
* @param id the machine id
|
||||
*/
|
||||
public DefaultStateMachineContext(List<StateMachineContext<S, E>> childs, S state, E event,
|
||||
Map<String, Object> eventHeaders, ExtendedState extendedState, Map<S, S> historyStates, String id) {
|
||||
this.childs = childs;
|
||||
this.state = state;
|
||||
this.event = event;
|
||||
this.eventHeaders = eventHeaders;
|
||||
this.extendedState = extendedState;
|
||||
this.historyStates = historyStates != null ? historyStates : new HashMap<S, S>();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,7 +170,7 @@ public class DefaultStateMachineContext<S, E> implements StateMachineContext<S,
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DefaultStateMachineContext [childs=" + childs + ", state=" + state + ", historyStates=" + historyStates + ", event=" + event
|
||||
+ ", eventHeaders=" + eventHeaders + ", extendedState=" + extendedState + "]";
|
||||
return "DefaultStateMachineContext [id=" + id + ", childs=" + childs + ", state=" + state + ", historyStates=" + historyStates
|
||||
+ ", event=" + event + ", eventHeaders=" + eventHeaders + ", extendedState=" + extendedState + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -405,7 +405,7 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
|
||||
if (!map.containsKey(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER)) {
|
||||
// don't set sm id if it's already present because
|
||||
// we want to keep the originating sm id
|
||||
map.put(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER, stateMachine.getId());
|
||||
map.put(StateMachineSystemConstants.STATEMACHINE_IDENTIFIER, stateMachine.getUuid());
|
||||
}
|
||||
return new DefaultStateContext<S, E>(Stage.TRANSITION, message, new MessageHeaders(map), stateMachine.getExtendedState(), transition, stateMachine, null, null, null);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertThat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -173,6 +174,11 @@ public class StateMachineAccessTests {
|
||||
public void setInitialEnabled(boolean enabled) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return null;
|
||||
|
||||
@@ -242,6 +242,31 @@ public class ConfigurationTests extends AbstractStateMachineTests {
|
||||
assertThat(bfFromMachine, sameInstance(Config16.beanFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMachineIdFlat() {
|
||||
context.register(Config17.class);
|
||||
context.refresh();
|
||||
@SuppressWarnings("unchecked")
|
||||
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getId(), is("testid1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMachineIdViaFactory() {
|
||||
context.register(Config18.class);
|
||||
context.refresh();
|
||||
@SuppressWarnings("unchecked")
|
||||
StateMachineFactory<String, String> stateMachineFactory = context.getBean(StateMachineFactory.class);
|
||||
StateMachine<String,String> stateMachine = stateMachineFactory.getStateMachine();
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getId(), is("testid1"));
|
||||
|
||||
stateMachine = stateMachineFactory.getStateMachine("testid2");
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getId(), is("testid2"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
|
||||
@@ -731,4 +756,62 @@ public class ConfigurationTests extends AbstractStateMachineTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class Config17 {
|
||||
|
||||
public static BeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
@Bean
|
||||
StateMachine<String, String> stateMachine() throws Exception {
|
||||
Builder<String, String> builder = StateMachineBuilder.builder();
|
||||
builder.configureConfiguration()
|
||||
.withConfiguration()
|
||||
.machineId("testid1")
|
||||
.autoStartup(false)
|
||||
.beanFactory(beanFactory);
|
||||
builder.configureStates()
|
||||
.withStates()
|
||||
.initial("S1").state("S2");
|
||||
builder.configureTransitions()
|
||||
.withExternal()
|
||||
.source("S1").target("S2").event("E1")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2").target("S1").event("E2");
|
||||
StateMachine<String, String> stateMachine = builder.build();
|
||||
return stateMachine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory
|
||||
public static class Config18 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<String, String> config) throws Exception {
|
||||
config
|
||||
.withConfiguration()
|
||||
.machineId("testid1")
|
||||
.autoStartup(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("S1")
|
||||
.state("S2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("S1")
|
||||
.target("S2")
|
||||
.event("E1");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class StateMachineModelTests {
|
||||
|
||||
ConfigurationData<String, String> configurationData = new ConfigurationData<>(beanFactory, taskExecutor, taskScheduler, autoStart,
|
||||
ensemble, listeners, securityEnabled, transitionSecurityAccessDecisionManager, eventSecurityAccessDecisionManager,
|
||||
eventSecurityRule, transitionSecurityRule, verifierEnabled, verifier);
|
||||
eventSecurityRule, transitionSecurityRule, verifierEnabled, verifier, null);
|
||||
|
||||
Collection<StateData<String, String>> stateData = new ArrayList<>();
|
||||
StateData<String, String> stateData1 = new StateData<String, String>(null, null, "S1", null, null, null);
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.statemachine.persist;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.statemachine.AbstractStateMachineTests;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.StateMachineContext;
|
||||
import org.springframework.statemachine.StateMachinePersist;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.StateMachineFactory;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
|
||||
public class StateMachinePersistTests3 extends AbstractStateMachineTests {
|
||||
|
||||
@Override
|
||||
protected AnnotationConfigApplicationContext buildContext() {
|
||||
return new AnnotationConfigApplicationContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistMachineId() throws Exception {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
InMemoryStateMachinePersist1 stateMachinePersist = new InMemoryStateMachinePersist1();
|
||||
StateMachinePersister<String, String, String> persister = new DefaultStateMachinePersister<>(stateMachinePersist);
|
||||
@SuppressWarnings("unchecked")
|
||||
StateMachineFactory<String, String> stateMachineFactory = context.getBean(StateMachineFactory.class);
|
||||
|
||||
StateMachine<String,String> stateMachine = stateMachineFactory.getStateMachine("testid2");
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getId(), is("testid2"));
|
||||
|
||||
persister.persist(stateMachine, "xxx");
|
||||
|
||||
stateMachine = stateMachineFactory.getStateMachine();
|
||||
assertThat(stateMachine, notNullValue());
|
||||
assertThat(stateMachine.getId(), nullValue());
|
||||
|
||||
stateMachine = persister.restore(stateMachine, "xxx");
|
||||
assertThat(stateMachine.getId(), is("testid2"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory
|
||||
public static class Config1 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<String, String> config) throws Exception {
|
||||
config
|
||||
.withConfiguration()
|
||||
.autoStartup(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial("S1")
|
||||
.state("S2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source("S1")
|
||||
.target("S2")
|
||||
.event("E1");
|
||||
}
|
||||
}
|
||||
|
||||
static class InMemoryStateMachinePersist1 implements StateMachinePersist<String, String, String> {
|
||||
|
||||
private final HashMap<String, StateMachineContext<String, String>> contexts = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void write(StateMachineContext<String, String> context, String contextOjb) throws Exception {
|
||||
contexts.put(contextOjb, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateMachineContext<String, String> read(String contextOjb) throws Exception {
|
||||
return contexts.get(contextOjb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
@@ -209,6 +210,11 @@ public class StateContextExpressionMethodsTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return null;
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -756,6 +757,11 @@ public class ZookeeperStateMachineEnsembleTests extends AbstractZookeeperTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user