Association with @EnableStateMachine and @WithStateMachine
- Fix bug where multiple machines and beans with @WithStateMachine didn't properly separate calling methods with @OnTransition. - Some polish - Fixes #116
This commit is contained in:
@@ -25,6 +25,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -77,7 +78,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectSupport implements
|
||||
StateMachineFactory<S, E> {
|
||||
StateMachineFactory<S, E>, BeanNameAware {
|
||||
|
||||
private final StateMachineTransitions<S, E> stateMachineTransitions;
|
||||
|
||||
@@ -89,6 +90,8 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
|
||||
private boolean handleAutostartup = false;
|
||||
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* Instantiates a new enum state machine factory.
|
||||
*
|
||||
@@ -102,6 +105,11 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
this.stateMachineTransitions = stateMachineTransitions;
|
||||
this.stateMachineStates = stateMachineStates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@@ -178,7 +186,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
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());
|
||||
resolveTaskExecutor(), resolveTaskScheduler(), beanName);
|
||||
machine = m;
|
||||
}
|
||||
} else {
|
||||
@@ -196,7 +204,7 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
|
||||
if (machine instanceof LifecycleObjectSupport) {
|
||||
((LifecycleObjectSupport)machine).setAutoStartup(stateMachineConfigurationConfig.isAutoStart());
|
||||
}
|
||||
|
||||
|
||||
// set top-level machine as relay
|
||||
final StateMachine<S, E> fmachine = machine;
|
||||
fmachine.getStateMachineAccessor().doWithAllRegions(new StateMachineFunction<StateMachineAccess<S, E>>() {
|
||||
@@ -536,8 +544,9 @@ 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);
|
||||
StateMachine<S, E> machine = buildStateMachineInternal(states, transitions, initialState, initialTransition,
|
||||
null, defaultExtendedState, historyState, contextEvents, beanFactory, taskExecutor, taskScheduler,
|
||||
beanName);
|
||||
return machine;
|
||||
}
|
||||
|
||||
@@ -545,7 +554,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);
|
||||
TaskScheduler taskScheduler, String beanName);
|
||||
|
||||
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);
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.statemachine.config;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
@@ -56,7 +57,7 @@ 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) {
|
||||
TaskScheduler taskScheduler, String beanName) {
|
||||
ObjectStateMachine<S, E> machine = new ObjectStateMachine<S, E>(states, transitions, initialState, initialTransition, initialEvent,
|
||||
extendedState);
|
||||
machine.setHistoryState(historyState);
|
||||
@@ -72,6 +73,9 @@ public class ObjectStateMachineFactory<S, E> extends AbstractStateMachineFactory
|
||||
if (taskScheduler != null) {
|
||||
machine.setTaskScheduler(taskScheduler);;
|
||||
}
|
||||
if (machine instanceof BeanNameAware) {
|
||||
((BeanNameAware)machine).setBeanName(beanName);
|
||||
}
|
||||
machine.afterPropertiesSet();
|
||||
return machine;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.springframework.statemachine.annotation.WithStateMachine;
|
||||
import org.springframework.statemachine.processor.StateMachineAnnotationPostProcessor;
|
||||
|
||||
/**
|
||||
* Configuration for annotation port processor which is needed i.e. when
|
||||
* Configuration for annotation post processor which is needed i.e. when
|
||||
* {@link WithStateMachine} is used.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
@@ -68,11 +69,12 @@ public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> ext
|
||||
|
||||
private static class StateMachineDelegatingFactoryBean<S extends Enum<S>, E extends Enum<E>>
|
||||
extends BeanDelegatingFactoryBean<StateMachine<S, E>,StateMachineConfigBuilder<S, E>,StateMachineConfig<S, E>>
|
||||
implements SmartLifecycle {
|
||||
implements SmartLifecycle, BeanNameAware {
|
||||
|
||||
private String clazzName;
|
||||
private Boolean contextEvents;
|
||||
private SmartLifecycle lifecycle;
|
||||
private String beanName;
|
||||
|
||||
public StateMachineDelegatingFactoryBean(StateMachineConfigBuilder<S, E> builder, Class<StateMachine<S, E>> clazz,
|
||||
String clazzName, Boolean contextEvents) {
|
||||
@@ -80,6 +82,11 @@ public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> ext
|
||||
this.clazzName = clazzName;
|
||||
this.contextEvents = contextEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -97,6 +104,7 @@ public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> ext
|
||||
stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
|
||||
stateMachineFactory.setBeanFactory(getBeanFactory());
|
||||
stateMachineFactory.setContextEventsEnabled(contextEvents);
|
||||
stateMachineFactory.setBeanName(beanName);
|
||||
StateMachine<S, E> stateMachine = stateMachineFactory.getStateMachine();
|
||||
this.lifecycle = (SmartLifecycle) stateMachine;
|
||||
setObject(stateMachine);
|
||||
|
||||
@@ -34,6 +34,7 @@ public interface MethodAnnotationPostProcessor<T extends Annotation> {
|
||||
* <code>null</code>. Caller of this method is then responsible to handle
|
||||
* newly created object.
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param bean the bean
|
||||
* @param beanName the bean name
|
||||
* @param method the method
|
||||
@@ -41,6 +42,6 @@ public interface MethodAnnotationPostProcessor<T extends Annotation> {
|
||||
* @param annotation the annotation
|
||||
* @return the post processed object
|
||||
*/
|
||||
Object postProcess(Object bean, String beanName, Method method, T metaAnnotation, Annotation annotation);
|
||||
Object postProcess(Class<?> beanClass, Object bean, String beanName, Method method, T metaAnnotation, Annotation annotation);
|
||||
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ public class StateMachineActivatorAnnotationPostProcessor implements MethodAnnot
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcess(Object bean, String beanName, Method method, OnTransition metaAnnotation, Annotation annotation) {
|
||||
StateMachineHandler<Object, Object> handler = new StateMachineOnTransitionHandler<Object, Object>(bean, method, metaAnnotation, annotation);
|
||||
public Object postProcess(Class<?> beanClass, Object bean, String beanName, Method method, OnTransition metaAnnotation, Annotation annotation) {
|
||||
StateMachineHandler<Object, Object> handler = new StateMachineOnTransitionHandler<Object, Object>(beanClass, bean, method, metaAnnotation, annotation);
|
||||
|
||||
Integer order = findOrder(bean, method);
|
||||
if (order != null) {
|
||||
|
||||
@@ -133,7 +133,7 @@ public class StateMachineAnnotationPostProcessor implements BeanPostProcessor, B
|
||||
.get(metaAnnotation.annotationType()) : null;
|
||||
|
||||
if (postProcessor != null && shouldCreateHandler(annotation)) {
|
||||
Object result = postProcessor.postProcess(bean, beanName, method, metaAnnotation, annotation);
|
||||
Object result = postProcessor.postProcess(beanClass, bean, beanName, method, metaAnnotation, annotation);
|
||||
|
||||
if (result != null && result instanceof StateMachineHandler) {
|
||||
String endpointBeanName = generateBeanName(beanName, method, annotation.annotationType());
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.springframework.statemachine.annotation.WithStateMachine;
|
||||
*/
|
||||
public class StateMachineHandler<S, E> implements Ordered {
|
||||
|
||||
private final Class<?> beanClass;
|
||||
|
||||
private final StateMachineRuntimeProcessor<?, S, E> processor;
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
@@ -40,30 +42,34 @@ public class StateMachineHandler<S, E> implements Ordered {
|
||||
/**
|
||||
* Instantiates a new container handler.
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param target the target bean
|
||||
* @param method the method
|
||||
*/
|
||||
public StateMachineHandler(Object target, Method method) {
|
||||
this(new MethodInvokingStateMachineRuntimeProcessor<Object, S, E>(target, method));
|
||||
public StateMachineHandler(Class<?> beanClass, Object target, Method method) {
|
||||
this(beanClass, new MethodInvokingStateMachineRuntimeProcessor<Object, S, E>(target, method));
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new container handler.
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param target the target bean
|
||||
* @param methodName the method name
|
||||
*/
|
||||
public StateMachineHandler(Object target, String methodName) {
|
||||
this(new MethodInvokingStateMachineRuntimeProcessor<Object, S, E>(target, methodName));
|
||||
public StateMachineHandler(Class<?> beanClass, Object target, String methodName) {
|
||||
this(beanClass, new MethodInvokingStateMachineRuntimeProcessor<Object, S, E>(target, methodName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new container handler.
|
||||
*
|
||||
* @param <T> the generic type
|
||||
* @param beanClass the bean class
|
||||
* @param processor the processor
|
||||
*/
|
||||
public <T> StateMachineHandler(MethodInvokingStateMachineRuntimeProcessor<T, S, E> processor) {
|
||||
public <T> StateMachineHandler(Class<?> beanClass, MethodInvokingStateMachineRuntimeProcessor<T, S, E> processor) {
|
||||
this.beanClass = beanClass;
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@@ -71,6 +77,15 @@ public class StateMachineHandler<S, E> implements Ordered {
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bean class.
|
||||
*
|
||||
* @return the bean class
|
||||
*/
|
||||
public Class<?> getBeanClass() {
|
||||
return beanClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the order used get value from {@link #getOrder()}.
|
||||
|
||||
@@ -36,13 +36,14 @@ public class StateMachineOnTransitionHandler<S, E> extends StateMachineHandler<S
|
||||
/**
|
||||
* Instantiates a new state machine on transition handler.
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param target the target
|
||||
* @param method the method
|
||||
* @param metaAnnotation the meta annotation
|
||||
* @param annotation the annotation
|
||||
*/
|
||||
public StateMachineOnTransitionHandler(Object target, Method method, OnTransition metaAnnotation, Annotation annotation) {
|
||||
super(target, method);
|
||||
public StateMachineOnTransitionHandler(Class<?> beanClass, Object target, Method method, OnTransition metaAnnotation, Annotation annotation) {
|
||||
super(beanClass, target, method);
|
||||
this.metaAnnotation = metaAnnotation;
|
||||
this.annotation = annotation;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.springframework.statemachine.access.StateMachineAccess;
|
||||
import org.springframework.statemachine.access.StateMachineAccessor;
|
||||
import org.springframework.statemachine.access.StateMachineFunction;
|
||||
import org.springframework.statemachine.annotation.OnTransition;
|
||||
import org.springframework.statemachine.annotation.WithStateMachine;
|
||||
import org.springframework.statemachine.listener.StateMachineListener;
|
||||
import org.springframework.statemachine.processor.StateMachineHandler;
|
||||
import org.springframework.statemachine.processor.StateMachineOnTransitionHandler;
|
||||
@@ -64,6 +65,7 @@ import org.springframework.statemachine.transition.TransitionKind;
|
||||
import org.springframework.statemachine.trigger.DefaultTriggerContext;
|
||||
import org.springframework.statemachine.trigger.Trigger;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -890,9 +892,9 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
Assert.state(beanFactory instanceof ListableBeanFactory, "Bean factory must be instance of ListableBeanFactory");
|
||||
|
||||
if (!handlersInitialized) {
|
||||
Map<String, StateMachineOnTransitionHandler> handlersx = ((ListableBeanFactory) beanFactory)
|
||||
Map<String, StateMachineOnTransitionHandler> handlersMap = ((ListableBeanFactory) beanFactory)
|
||||
.getBeansOfType(StateMachineOnTransitionHandler.class);
|
||||
for (Entry<String, StateMachineOnTransitionHandler> entry : handlersx.entrySet()) {
|
||||
for (Entry<String, StateMachineOnTransitionHandler> entry : handlersMap.entrySet()) {
|
||||
handlers.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
handlersInitialized = true;
|
||||
@@ -901,9 +903,13 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
|
||||
List<StateMachineHandler<S, E>> handlersList = new ArrayList<StateMachineHandler<S, E>>();
|
||||
|
||||
for (Entry<String, StateMachineOnTransitionHandler<S, E>> entry : handlers.entrySet()) {
|
||||
// add only matching names from beanName and WithStateMachine name field
|
||||
WithStateMachine withStateMachine = AnnotationUtils.findAnnotation(entry.getValue().getBeanClass(), WithStateMachine.class);
|
||||
if (withStateMachine == null || !ObjectUtils.nullSafeEquals(withStateMachine.name(), getBeanName())) {
|
||||
continue;
|
||||
}
|
||||
OnTransition metaAnnotation = entry.getValue().getMetaAnnotation();
|
||||
Annotation annotation = entry.getValue().getAnnotation();
|
||||
|
||||
if (transitionHandlerMatch(metaAnnotation, annotation, sourceState, targetState)) {
|
||||
handlersList.add(entry.getValue());
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
@@ -38,7 +39,7 @@ import org.springframework.util.Assert;
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public abstract class StateMachineObjectSupport<S, E> extends LifecycleObjectSupport {
|
||||
public abstract class StateMachineObjectSupport<S, E> extends LifecycleObjectSupport implements BeanNameAware {
|
||||
|
||||
private static final Log log = LogFactory.getLog(StateMachineObjectSupport.class);
|
||||
|
||||
@@ -52,7 +53,24 @@ public abstract class StateMachineObjectSupport<S, E> extends LifecycleObjectSup
|
||||
|
||||
private final StateMachineInterceptorList<S, E> interceptors =
|
||||
new StateMachineInterceptorList<S, E>();
|
||||
|
||||
private String beanName;
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
beanName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bean name known to context per contract
|
||||
* with {@link BeanNameAware}.
|
||||
*
|
||||
* @return a bean name
|
||||
*/
|
||||
protected String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state machine event publisher.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2015 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.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.statemachine.AbstractStateMachineTests;
|
||||
import org.springframework.statemachine.ObjectStateMachine;
|
||||
import org.springframework.statemachine.annotation.OnTransition;
|
||||
import org.springframework.statemachine.annotation.WithStateMachine;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
|
||||
public class ClassAnnotationTests extends AbstractStateMachineTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testClassAnnotations() throws Exception {
|
||||
AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(BaseConfig.class, BeanConfig.class, FooConfig.class, BarConfig.class);
|
||||
|
||||
ObjectStateMachine<TestStates,TestEvents> fooMachine =
|
||||
context.getBean("fooMachine", ObjectStateMachine.class);
|
||||
|
||||
ObjectStateMachine<TestStates,TestEvents> barMachine =
|
||||
context.getBean("barMachine", ObjectStateMachine.class);
|
||||
|
||||
assertThat(context.containsBean("fooMachine"), is(true));
|
||||
assertThat(context.containsBean("barMachine"), is(true));
|
||||
fooMachine.start();
|
||||
barMachine.start();
|
||||
|
||||
FooBean fooBean = context.getBean(FooBean.class);
|
||||
BarBean barBean = context.getBean(BarBean.class);
|
||||
|
||||
fooBean.resetMethodLatch();
|
||||
|
||||
// this event should cause 'FooBean.fooMethod' to get called
|
||||
fooMachine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build());
|
||||
|
||||
assertThat(fooBean.onFooMethodLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
assertThat(barBean.onBarMethodLatch.await(2, TimeUnit.SECONDS), is(false));
|
||||
|
||||
fooBean.resetMethodLatch();
|
||||
|
||||
// this event should cause 'BarBean.barMethod' to get called
|
||||
barMachine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build());
|
||||
|
||||
assertThat(fooBean.onFooMethodLatch.await(2, TimeUnit.SECONDS), is(false));
|
||||
assertThat(barBean.onBarMethodLatch.await(2, TimeUnit.SECONDS), is(true));
|
||||
|
||||
context.close();
|
||||
}
|
||||
|
||||
@WithStateMachine(name = "fooMachine")
|
||||
static class FooBean {
|
||||
|
||||
CountDownLatch onFooMethodLatch;
|
||||
|
||||
public void resetMethodLatch() {
|
||||
onFooMethodLatch = new CountDownLatch(1);
|
||||
}
|
||||
|
||||
@OnTransition(source = "S1", target = "S2")
|
||||
public void fooMethod() {
|
||||
onFooMethodLatch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@WithStateMachine(name = "barMachine")
|
||||
static class BarBean {
|
||||
|
||||
CountDownLatch onBarMethodLatch = new CountDownLatch(1);
|
||||
|
||||
@OnTransition(source = "S1", target = "S2")
|
||||
public void barMethod() {
|
||||
onBarMethodLatch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BeanConfig {
|
||||
|
||||
@Bean
|
||||
public FooBean fooBean() {
|
||||
return new FooBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BarBean barBean() {
|
||||
return new BarBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine(name = "fooMachine")
|
||||
static class FooConfig extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(TestStates.S1)
|
||||
.state(TestStates.S2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<TestStates, TestEvents> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(TestStates.S1)
|
||||
.target(TestStates.S2)
|
||||
.event(TestEvents.E1)
|
||||
.guard(testGuard())
|
||||
.action(testAction());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestGuard testGuard() {
|
||||
return new TestGuard();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestAction testAction() {
|
||||
return new TestAction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine(name = "barMachine")
|
||||
static class BarConfig extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(TestStates.S1)
|
||||
.state(TestStates.S2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<TestStates, TestEvents> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(TestStates.S1)
|
||||
.target(TestStates.S2)
|
||||
.event(TestEvents.E1)
|
||||
.guard(testGuard())
|
||||
.action(testAction());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestGuard testGuard() {
|
||||
return new TestGuard();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestAction testAction() {
|
||||
return new TestAction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user