Fix gateway proxy for generic interface in XML (#3935)

* Fix gateway proxy for generic interface in XML

Without a `FactoryBean.OBJECT_TYPE_ATTRIBUTE` the application context cannot determine a qualified
with generic an interface injection

* Set back `FactoryBean.OBJECT_TYPE_ATTRIBUTE` in the `GatewayParser`
when not in AOT mode.
Set a `targetType` when used in AOT

* * Remove unused import

* * Fix `GatewayParserTests` for new code base
This commit is contained in:
Artem Bilan
2022-11-02 11:45:41 -04:00
committed by GitHub
parent e3e55c3a85
commit eec5f4dc72
4 changed files with 46 additions and 35 deletions

View File

@@ -23,7 +23,9 @@ import java.util.Map;
import org.w3c.dom.Element;
import org.springframework.aot.AotDetector;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -253,8 +255,13 @@ public class GatewayParser implements BeanDefinitionParser {
}
RootBeanDefinition beanDefinition = (RootBeanDefinition) gatewayProxyBuilder.getBeanDefinition();
beanDefinition.setTargetType(
ResolvableType.forClassWithGenerics(GatewayProxyFactoryBean.class, serviceInterface));
if (AotDetector.useGeneratedArtifacts()) {
beanDefinition.setTargetType(
ResolvableType.forClassWithGenerics(GatewayProxyFactoryBean.class, serviceInterface));
}
else {
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, serviceInterface);
}
return new BeanDefinitionHolder(beanDefinition, id);
}

View File

@@ -36,12 +36,11 @@ import org.mockito.ArgumentMatchers;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.core.log.LogAccessor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.expression.Expression;
@@ -199,17 +198,17 @@ public class GatewayParserTests {
@Test
public void testFactoryBeanObjectTypeWithServiceInterface() {
ConfigurableListableBeanFactory beanFactory = ((GenericApplicationContext) context).getBeanFactory();
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition("&oneWay");
ResolvableType resolvableType = beanDefinition.getResolvableType();
assertThat(resolvableType.getGeneric(0).getRawClass()).isEqualTo(TestService.class);
Object attribute =
beanFactory.getMergedBeanDefinition("&oneWay").getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE);
assertThat(attribute).isEqualTo(TestService.class);
}
@Test
public void testFactoryBeanObjectTypeWithNoServiceInterface() {
ConfigurableListableBeanFactory beanFactory = ((GenericApplicationContext) context).getBeanFactory();
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition("&defaultConfig");
ResolvableType resolvableType = beanDefinition.getResolvableType();
assertThat(resolvableType.getGeneric(0).getRawClass()).isEqualTo(RequestReplyExchanger.class);
Object attribute =
beanFactory.getMergedBeanDefinition("&defaultConfig").getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE);
assertThat(attribute).isEqualTo(RequestReplyExchanger.class);
}
@Test

View File

@@ -5,7 +5,7 @@
xsi:schemaLocation="http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<int:gateway service-interface="org.springframework.integration.gateway.GatewayXmlAndAnnotationTests.AGateway"
<int:gateway service-interface="org.springframework.integration.gateway.GatewayXmlAndAnnotationTests$AGateway"
default-reply-timeout="123" default-request-channel="nullChannel">
<int:method name="explicitTimeoutShouldOverrideDefault" reply-timeout="456" />
</int:gateway>

View File

@@ -43,6 +43,9 @@ public class GatewayXmlAndAnnotationTests {
@Autowired
GatewayProxyFactoryBean<?> gatewayProxyFactoryBean;
@Autowired
AGateway<String> stringAGateway;
@Test
public void test() {
assertThat(TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyTimeout", Expression.class)
@@ -52,42 +55,44 @@ public class GatewayXmlAndAnnotationTests {
"gatewayMap", Map.class);
int assertions = 0;
for (Entry<Method, MessagingGatewaySupport> entry : gatewayMap.entrySet()) {
if (entry.getKey().getName().equals("annotationShouldntOverrideDefault")) {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(123L);
assertions++;
}
else if (entry.getKey().getName().equals("annotationShouldOverrideDefault")) {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(234L);
assertions++;
}
else if (entry.getKey().getName().equals("annotationShouldOverrideDefaultToInfinity")) {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(-1L);
assertions++;
}
else if (entry.getKey().getName().equals("explicitTimeoutShouldOverrideDefault")) {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(456L);
assertions++;
switch (entry.getKey().getName()) {
case "annotationShouldNotOverrideDefault" -> {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(123L);
assertions++;
}
case "annotationShouldOverrideDefault" -> {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(234L);
assertions++;
}
case "annotationShouldOverrideDefaultToInfinity" -> {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(-1L);
assertions++;
}
case "explicitTimeoutShouldOverrideDefault" -> {
assertThat(TestUtils.getPropertyValue(entry.getValue(),
"replyTimeout")).isEqualTo(456L);
assertions++;
}
}
}
assertThat(assertions).isEqualTo(4);
}
public interface AGateway {
public interface AGateway<T> {
@Gateway
String annotationShouldntOverrideDefault(String foo);
String annotationShouldNotOverrideDefault(T foo);
@Gateway(replyTimeout = 234)
String annotationShouldOverrideDefault(String foo);
String annotationShouldOverrideDefault(T foo);
@Gateway(replyTimeout = -1)
String annotationShouldOverrideDefaultToInfinity(String foo);
String annotationShouldOverrideDefaultToInfinity(T foo);
String explicitTimeoutShouldOverrideDefault(String foo);
String explicitTimeoutShouldOverrideDefault(T foo);
}