Fixing auto-start via @EnableStateMachineFactory

- Machine is now started automatically if it's requested
  from a factory and flag is set.
- Fixes #113
This commit is contained in:
Janne Valkealahti
2015-10-16 11:08:08 +01:00
parent cabee70593
commit d5c71bb776
6 changed files with 142 additions and 12 deletions

View File

@@ -69,7 +69,7 @@ import org.springframework.statemachine.trigger.Trigger;
import org.springframework.util.ObjectUtils;
/**
* {@link StateMachineFactory} implementation using enums to build {@link StateMachine}s.
* Base {@link StateMachineFactory} implementation building {@link StateMachine}s.
*
* @author Janne Valkealahti
*
@@ -226,10 +226,21 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
return delegateAutoStartup(machine);
}
/**
* Instructs this factory to handle auto-start flag manually
* by calling lifecycle start method.
*
* @param handleAutostartup the new handle autostartup
*/
public void setHandleAutostartup(boolean handleAutostartup) {
this.handleAutostartup = handleAutostartup;
}
/**
* Instructs this factory to enable application context events.
*
* @param contextEvents the new context events enabled
*/
public void setContextEventsEnabled(Boolean contextEvents) {
this.contextEvents = contextEvents;
}

View File

@@ -33,7 +33,8 @@ import org.springframework.statemachine.config.configuration.StateMachineConfigu
import org.springframework.statemachine.config.configuration.StateMachineConfigurationImportSelector;
/**
* Example annotation which imports @{@link Configuration}s.
* Annotation which imports @{@link Configuration}s related to
* building state machines.
*
* @author Janne Valkealahti
*

View File

@@ -33,7 +33,8 @@ import org.springframework.statemachine.config.configuration.StateMachineConfigu
import org.springframework.statemachine.config.configuration.StateMachineFactoryConfiguration;
/**
* Example annotation which imports @{@link Configuration}s.
* Annotation which imports @{@link Configuration}s related to
* building state machine factories.
*
* @author Janne Valkealahti
*

View File

@@ -110,11 +110,17 @@ public class StateMachineFactoryConfiguration<S extends Enum<S>, E extends Enum<
StateMachineConfig<S, E> stateMachineConfig = builder.getOrBuild();
StateMachineTransitions<S, E> stateMachineTransitions = stateMachineConfig.getTransitions();
StateMachineStates<S, E> stateMachineStates = stateMachineConfig.getStates();
StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig = stateMachineConfig.getStateMachineConfigurationConfig();
ObjectStateMachineFactory<S,E> enumStateMachineFactory = new ObjectStateMachineFactory<S, E>(stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
enumStateMachineFactory.setBeanFactory(beanFactory);
enumStateMachineFactory.setContextEventsEnabled(contextEvents);
this.stateMachineFactory = enumStateMachineFactory;
StateMachineConfigurationConfig<S, E> stateMachineConfigurationConfig = stateMachineConfig
.getStateMachineConfigurationConfig();
ObjectStateMachineFactory<S, E> objectStateMachineFactory = new ObjectStateMachineFactory<S, E>(
stateMachineConfigurationConfig, stateMachineTransitions, stateMachineStates);
objectStateMachineFactory.setBeanFactory(beanFactory);
objectStateMachineFactory.setContextEventsEnabled(contextEvents);
// explicitly tell factory to handle auto-start because
// machine is not created as a bean so factory need to
// call lifecycle methods manually
objectStateMachineFactory.setHandleAutostartup(true);
this.stateMachineFactory = objectStateMachineFactory;
}
@Override

View File

@@ -16,9 +16,13 @@
package org.springframework.statemachine;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.util.EnumSet;
import org.junit.Test;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -28,30 +32,63 @@ import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.ObjectStateMachineFactory;
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 StateMachineFactoryTests extends AbstractStateMachineTests {
@Override
protected AnnotationConfigApplicationContext buildContext() {
return new AnnotationConfigApplicationContext();
}
@SuppressWarnings({ "unchecked" })
@Test
public void testMachineFromFactory() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
context.register(Config1.class);
context.refresh();
ObjectStateMachineFactory<TestStates, TestEvents> stateMachineFactory =
ctx.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINEFACTORY, ObjectStateMachineFactory.class);
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINEFACTORY, ObjectStateMachineFactory.class);
StateMachine<TestStates,TestEvents> machine = stateMachineFactory.getStateMachine();
machine.start();
assertThat(machine.getState().getIds(), contains(TestStates.S1));
machine.sendEvent(MessageBuilder.withPayload(TestEvents.E1).build());
assertThat(machine.getState().getIds(), contains(TestStates.S2));
ctx.close();
}
@SuppressWarnings({ "unchecked" })
@Test
public void testAutoStartFlagOn() throws Exception {
context.register(Config2.class);
context.refresh();
StateMachineFactory<TestStates, TestEvents> stateMachineFactory =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINEFACTORY, StateMachineFactory.class);
StateMachine<TestStates,TestEvents> machine = stateMachineFactory.getStateMachine();
assertThat(((SmartLifecycle)machine).isAutoStartup(), is(true));
assertThat(((SmartLifecycle)machine).isRunning(), is(true));
}
@SuppressWarnings({ "unchecked" })
@Test
public void testAutoStartFlagOff() throws Exception {
context.register(Config3.class);
context.refresh();
StateMachineFactory<TestStates, TestEvents> stateMachineFactory =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINEFACTORY, StateMachineFactory.class);
StateMachine<TestStates,TestEvents> machine = stateMachineFactory.getStateMachine();
assertThat(((SmartLifecycle)machine).isAutoStartup(), is(false));
assertThat(((SmartLifecycle)machine).isRunning(), is(false));
}
@Configuration
@EnableStateMachineFactory
static class Config extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
@@ -78,4 +115,46 @@ public class StateMachineFactoryTests extends AbstractStateMachineTests {
}
@Configuration
@EnableStateMachineFactory
public static class Config2 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineConfigurationConfigurer<TestStates, TestEvents> config) throws Exception {
config
.withConfiguration()
.autoStartup(true);
}
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
states
.withStates()
.initial(TestStates.S1)
.states(EnumSet.allOf(TestStates.class));
}
}
@Configuration
@EnableStateMachineFactory
public static class Config3 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineConfigurationConfigurer<TestStates, TestEvents> config) throws Exception {
config
.withConfiguration()
.autoStartup(false);
}
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
states
.withStates()
.initial(TestStates.S1)
.states(EnumSet.allOf(TestStates.class));
}
}
}

View File

@@ -125,6 +125,17 @@ public class ConfigurationTests extends AbstractStateMachineTests {
assertThat(machine.isRunning(), is(true));
}
@SuppressWarnings({ "unchecked" })
@Test
public void testAutoStartFlagOff() throws Exception {
context.register(Config11.class);
context.refresh();
ObjectStateMachine<TestStates,TestEvents> machine =
context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, ObjectStateMachine.class);
assertThat(machine.isAutoStartup(), is(false));
assertThat(machine.isRunning(), is(false));
}
@SuppressWarnings({ "unchecked" })
@Test
public void testRegisterListeners() throws Exception {
@@ -502,4 +513,25 @@ public class ConfigurationTests extends AbstractStateMachineTests {
}
@Configuration
@EnableStateMachine
public static class Config11 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
@Override
public void configure(StateMachineConfigurationConfigurer<TestStates, TestEvents> config) throws Exception {
config
.withConfiguration()
.autoStartup(false);
}
@Override
public void configure(StateMachineStateConfigurer<TestStates, TestEvents> states) throws Exception {
states
.withStates()
.initial(TestStates.S1)
.states(EnumSet.allOf(TestStates.class));
}
}
}