Find correct super type generics for configurer adapter

- Naively with StateMachineConfigurerAdapter or EnumStateMachineConfigurerAdapter
  only immediate super type were checked to find user level generics to
  instruct IOC for proper resolvable types. This worked with almost all cases
  except if user created new base type out from StateMachineConfigurerAdapter and
  bean id didn't match what what was trying to get autowired if multiple adapters
  were in use.
- Correctly find resolvable type as StateMachineConfigurerAdapter in ResolvableType
  which finds an exact correct type to get generics.
- Fixes #454
This commit is contained in:
Janne Valkealahti
2017-12-15 08:54:32 +00:00
parent 6147a81ea9
commit f4f904bb6e
3 changed files with 152 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2017 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.
@@ -121,7 +121,7 @@ public class StateMachineConfiguration<S, E> extends
private ResolvableType resolveFactoryObjectType(Class<?> enableStateMachineEnclosingClass) {
ResolvableType type = null;
try {
Class<?>[] generics = ResolvableType.forClass(enableStateMachineEnclosingClass).getSuperType().resolveGenerics();
Class<?>[] generics = ResolvableType.forClass(enableStateMachineEnclosingClass).as(StateMachineConfigurerAdapter.class).resolveGenerics();
if (generics != null && generics.length == 2) {
type = ResolvableType.forClassWithGenerics(StateMachine.class, generics);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2017 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.
@@ -96,7 +96,7 @@ public class StateMachineFactoryConfiguration<S, E> extends
private ResolvableType resolveFactoryObjectType(Class<?> enableStateMachineEnclosingClass) {
ResolvableType type = null;
try {
Class<?>[] generics = ResolvableType.forClass(enableStateMachineEnclosingClass).getSuperType().resolveGenerics();
Class<?>[] generics = ResolvableType.forClass(enableStateMachineEnclosingClass).as(StateMachineConfigurerAdapter.class).resolveGenerics();
if (generics != null && generics.length == 2) {
type = ResolvableType.forClassWithGenerics(StateMachineFactory.class, generics);
}

View File

@@ -81,6 +81,28 @@ public class MachineTypedTests extends AbstractStateMachineTests {
assertThat(myBean4.someMachineFactory1, not(sameInstance(myBean4.someMachineFactory2)));
}
@Test
public void testAutowireMachineFactoryByNewBaseTypeNameNotMatches() {
context.register(Config5.class, Config6.class, MyBean5Config.class);
context.refresh();
MyBean5 myBean5 = context.getBean(MyBean5.class);
assertThat(myBean5.someMachineFactory3, notNullValue());
assertThat(myBean5.someMachineFactory4, notNullValue());
assertThat(myBean5.someMachineFactory3, not(sameInstance(myBean5.someMachineFactory4)));
}
@Test
public void testAutowireMachineByNewBaseTypeNameNotMatches() {
context.register(Config7.class, Config8.class, MyBean6Config.class);
context.refresh();
MyBean6 myBean6 = context.getBean(MyBean6.class);
assertThat(myBean6.someMachine3, notNullValue());
assertThat(myBean6.someMachine4, notNullValue());
assertThat(myBean6.someMachine3, not(sameInstance(myBean6.someMachine4)));
}
@Configuration
public static class MyBean1Config {
@@ -117,6 +139,24 @@ public class MachineTypedTests extends AbstractStateMachineTests {
}
}
@Configuration
public static class MyBean5Config {
@Bean
public MyBean5 myBean5() {
return new MyBean5();
}
}
@Configuration
public static class MyBean6Config {
@Bean
public MyBean6 myBean6() {
return new MyBean6();
}
}
public static class MyBean1 {
@Autowired
@@ -153,6 +193,24 @@ public class MachineTypedTests extends AbstractStateMachineTests {
StateMachineFactory<MyTestStates2, MyTestEvents2> someMachineFactory2;
}
public static class MyBean5 {
@Autowired
StateMachineFactory<MyTestStates1, MyTestEvents1> someMachineFactory3;
@Autowired
StateMachineFactory<MyTestStates2, MyTestEvents2> someMachineFactory4;
}
public static class MyBean6 {
@Autowired
StateMachine<MyTestStates1, MyTestEvents1> someMachine3;
@Autowired
StateMachine<MyTestStates2, MyTestEvents2> someMachine4;
}
@Configuration
@EnableStateMachine(name = "machine1")
public static class Config1 extends EnumStateMachineConfigurerAdapter<MyTestStates1, MyTestEvents1> {
@@ -237,6 +295,96 @@ public class MachineTypedTests extends AbstractStateMachineTests {
}
}
@Configuration
@EnableStateMachineFactory(name = "machinefactory3")
public static class Config5 extends MyNewBaseAdapter1 {
@Override
public void configure(StateMachineStateConfigurer<MyTestStates1, MyTestEvents1> states) throws Exception {
states
.withStates()
.initial(MyTestStates1.S1)
.state(MyTestStates1.S2);
}
@Override
public void configure(StateMachineTransitionConfigurer<MyTestStates1, MyTestEvents1> transitions) throws Exception {
transitions
.withExternal()
.source(MyTestStates1.S1).target(MyTestStates1.S2)
.event(MyTestEvents1.E1);
}
}
@Configuration
@EnableStateMachineFactory(name = "machinefactory4")
public static class Config6 extends MyNewBaseAdapter2 {
@Override
public void configure(StateMachineStateConfigurer<MyTestStates2, MyTestEvents2> states) throws Exception {
states
.withStates()
.initial(MyTestStates2.S1)
.state(MyTestStates2.S2);
}
@Override
public void configure(StateMachineTransitionConfigurer<MyTestStates2, MyTestEvents2> transitions) throws Exception {
transitions
.withExternal()
.source(MyTestStates2.S1).target(MyTestStates2.S2)
.event(MyTestEvents2.E1);
}
}
@Configuration
@EnableStateMachine(name = "machine3")
public static class Config7 extends MyNewBaseAdapter1 {
@Override
public void configure(StateMachineStateConfigurer<MyTestStates1, MyTestEvents1> states) throws Exception {
states
.withStates()
.initial(MyTestStates1.S1)
.state(MyTestStates1.S2);
}
@Override
public void configure(StateMachineTransitionConfigurer<MyTestStates1, MyTestEvents1> transitions) throws Exception {
transitions
.withExternal()
.source(MyTestStates1.S1).target(MyTestStates1.S2)
.event(MyTestEvents1.E1);
}
}
@Configuration
@EnableStateMachine(name = "machine4")
public static class Config8 extends MyNewBaseAdapter2 {
@Override
public void configure(StateMachineStateConfigurer<MyTestStates2, MyTestEvents2> states) throws Exception {
states
.withStates()
.initial(MyTestStates2.S1)
.state(MyTestStates2.S2);
}
@Override
public void configure(StateMachineTransitionConfigurer<MyTestStates2, MyTestEvents2> transitions) throws Exception {
transitions
.withExternal()
.source(MyTestStates2.S1).target(MyTestStates2.S2)
.event(MyTestEvents2.E1);
}
}
public static class MyNewBaseAdapter1 extends EnumStateMachineConfigurerAdapter<MyTestStates1, MyTestEvents1> {
}
public static class MyNewBaseAdapter2 extends EnumStateMachineConfigurerAdapter<MyTestStates2, MyTestEvents2> {
}
public enum MyTestStates1 {
S1, S2;
}