Fix NPE with missing configurer
- Throw BeanDefinitionStoreException in favor of NPE if @EnableStateMachine or @EnableStateMachineFactory is used without a configurer meaning user is missing proper config adapter like EnumStateMachineConfigurerAdapter. - Polish StateMachineConfiguration and StateMachineFactoryConfiguration by removing wrong typed refs to Enum. - Fixes #119
This commit is contained in:
@@ -19,6 +19,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -30,6 +31,7 @@ import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.ObjectStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfig;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStates;
|
||||
@@ -38,8 +40,18 @@ import org.springframework.statemachine.config.common.annotation.AbstractImporti
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurer;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link Configuration} which gets imported from {@link EnableStateMachine} and registers
|
||||
* a {@link StateMachine} build from a {@link StateMachineConfigurerAdapter} via
|
||||
* a {@link BeanDefinition}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
@Configuration
|
||||
public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> extends
|
||||
public class StateMachineConfiguration<S, E> extends
|
||||
AbstractImportingAnnotationConfiguration<StateMachineConfigBuilder<S, E>, StateMachineConfig<S, E>> {
|
||||
|
||||
private final StateMachineConfigBuilder<S, E> builder = new StateMachineConfigBuilder<S, E>();
|
||||
@@ -67,7 +79,7 @@ public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> ext
|
||||
return types;
|
||||
}
|
||||
|
||||
private static class StateMachineDelegatingFactoryBean<S extends Enum<S>, E extends Enum<E>>
|
||||
private static class StateMachineDelegatingFactoryBean<S, E>
|
||||
extends BeanDelegatingFactoryBean<StateMachine<S, E>,StateMachineConfigBuilder<S, E>,StateMachineConfig<S, E>>
|
||||
implements SmartLifecycle, BeanNameAware {
|
||||
|
||||
@@ -82,7 +94,7 @@ 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;
|
||||
@@ -90,6 +102,12 @@ public class StateMachineConfiguration<S extends Enum<S>, E extends Enum<E>> ext
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// do not continue without configurers, it would not work
|
||||
if (getConfigurers() == null || getConfigurers().size() == 0) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Cannot configure state machine due to missing configurers. Did you remember to use " +
|
||||
"@EnableStateMachine with a StateMachineConfigurerAdapter.");
|
||||
}
|
||||
for (AnnotationConfigurer<StateMachineConfig<S, E>, StateMachineConfigBuilder<S, E>> configurer : getConfigurers()) {
|
||||
Class<?> clazz = configurer.getClass();
|
||||
if (ClassUtils.getUserClass(clazz).getName().equals(clazzName)) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
import org.springframework.statemachine.config.ObjectStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfig;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.StateMachineFactory;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfig;
|
||||
@@ -42,8 +44,18 @@ import org.springframework.statemachine.config.common.annotation.AbstractImporti
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurer;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link Configuration} which gets imported from {@link EnableStateMachineFactory} and registers
|
||||
* a {@link StateMachineFactory} build from a {@link StateMachineConfigurerAdapter} via
|
||||
* a {@link BeanDefinition}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
@Configuration
|
||||
public class StateMachineFactoryConfiguration<S extends Enum<S>, E extends Enum<E>> extends
|
||||
public class StateMachineFactoryConfiguration<S, E> extends
|
||||
AbstractImportingAnnotationConfiguration<StateMachineConfigBuilder<S, E>, StateMachineConfig<S, E>> {
|
||||
|
||||
private final StateMachineConfigBuilder<S, E> builder = new StateMachineConfigBuilder<S, E>();
|
||||
@@ -70,7 +82,7 @@ public class StateMachineFactoryConfiguration<S extends Enum<S>, E extends Enum<
|
||||
return types;
|
||||
}
|
||||
|
||||
private static class StateMachineFactoryDelegatingFactoryBean<S extends Enum<S>, E extends Enum<E>> implements
|
||||
private static class StateMachineFactoryDelegatingFactoryBean<S, E> implements
|
||||
FactoryBean<StateMachineFactory<S, E>>, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private final StateMachineConfigBuilder<S, E> builder;
|
||||
@@ -104,6 +116,12 @@ public class StateMachineFactoryConfiguration<S extends Enum<S>, E extends Enum<
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// do not continue without configurers, it would not work
|
||||
if (configurers == null || configurers.size() == 0) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Cannot configure state machine due to missing configurers. Did you remember to use " +
|
||||
"@EnableStateMachineFactory with a StateMachineConfigurerAdapter.");
|
||||
}
|
||||
for (AnnotationConfigurer<StateMachineConfig<S, E>, StateMachineConfigBuilder<S, E>> configurer : configurers) {
|
||||
Class<?> clazz = configurer.getClass();
|
||||
if (ClassUtils.getUserClass(clazz).getName().equals(clazzName)) {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.statemachine.config;
|
||||
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -149,6 +150,18 @@ public class ConfigurationTests extends AbstractStateMachineTests {
|
||||
assertThat(((List<?>)o3).size(), is(2));
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testEnableStateMachineNoAdapter() {
|
||||
context.register(Config12.class);
|
||||
context.refresh();
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testEnableStateMachineFactoryNoAdapter() {
|
||||
context.register(Config13.class);
|
||||
context.refresh();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config1 extends EnumStateMachineConfigurerAdapter<TestStates, TestEvents> {
|
||||
@@ -534,4 +547,14 @@ public class ConfigurationTests extends AbstractStateMachineTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config12 {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory
|
||||
public static class Config13 {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user