diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/dsl/AmqpTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/dsl/AmqpTests.java index 4b2545349b..d983456520 100644 --- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/dsl/AmqpTests.java +++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/dsl/AmqpTests.java @@ -40,6 +40,7 @@ import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer; import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.Lifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.amqp.channel.AbstractAmqpChannel; @@ -91,13 +92,19 @@ public class AmqpTests { @Qualifier("amqpInboundGatewayContainer") private SimpleMessageListenerContainer amqpInboundGatewayContainer; + @Autowired + private Lifecycle asyncOutboundGateway; + @AfterClass public static void tearDown() { brokerRunning.removeTestQueues(); } @Test - public void testAmqpInboundGatewayFlow() throws Exception { + public void testAmqpInboundGatewayFlow() { + assertNotNull(this.amqpInboundGatewayContainer); + assertSame(this.amqpTemplate, TestUtils.getPropertyValue(this.amqpInboundGateway, "amqpTemplate")); + Object result = this.amqpTemplate.convertSendAndReceive(this.amqpQueue.getName(), "world"); assertEquals("HELLO WORLD", result); @@ -109,9 +116,6 @@ public class AmqpTests { ((RabbitTemplate) this.amqpTemplate).setReceiveTimeout(10000); result = this.amqpTemplate.receiveAndConvert("defaultReplyTo"); assertEquals("HELLO WORLD", result); - assertSame(this.amqpTemplate, TestUtils.getPropertyValue(this.amqpInboundGateway, "amqpTemplate")); - - assertNotNull(this.amqpInboundGatewayContainer); } @Autowired @@ -141,6 +145,8 @@ public class AmqpTests { assertNotNull(receive); assertEquals("HELLO THROUGH THE AMQP", receive.getPayload()); + + ((Lifecycle) this.amqpOutboundInput).stop(); } @Test @@ -167,6 +173,8 @@ public class AmqpTests { Message receive = replyChannel.receive(10000); assertNotNull(receive); assertEquals("HELLO ASYNC GATEWAY", receive.getPayload()); + + this.asyncOutboundGateway.stop(); } @Autowired @@ -264,7 +272,8 @@ public class AmqpTests { @Bean public IntegrationFlow amqpInboundFlow(ConnectionFactory rabbitConnectionFactory) { - return IntegrationFlows.from(Amqp.inboundAdapter(rabbitConnectionFactory, fooQueue())) + return IntegrationFlows.from(Amqp.inboundAdapter(rabbitConnectionFactory, fooQueue()) + .id("amqpInboundFlowAdapter")) .transform(String.class, String::toUpperCase) .channel(Amqp.pollableChannel(rabbitConnectionFactory) .queueName("amqpReplyChannel") @@ -286,7 +295,8 @@ public class AmqpTests { public IntegrationFlow amqpAsyncOutboundFlow(AsyncRabbitTemplate asyncRabbitTemplate) { return f -> f .handle(Amqp.asyncOutboundGateway(asyncRabbitTemplate) - .routingKeyFunction(m -> queue().getName())); + .routingKeyFunction(m -> queue().getName()), + e -> e.id("asyncOutboundGateway")); } @Bean diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/dsl/IntegrationFlowBeanPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/dsl/IntegrationFlowBeanPostProcessor.java index f9566bb035..a141737ef2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/dsl/IntegrationFlowBeanPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/dsl/IntegrationFlowBeanPostProcessor.java @@ -17,26 +17,23 @@ package org.springframework.integration.config.dsl; import java.util.Collection; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Set; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationNotAllowedException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionCustomizer; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ApplicationEventMulticaster; -import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.core.io.DescriptiveResource; import org.springframework.integration.channel.AbstractMessageChannel; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.FixedSubscriberChannel; @@ -67,17 +64,14 @@ import org.springframework.util.StringUtils; * * @author Artem Bilan * @author Gary Russell + * * @since 5.0 */ -public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware, - SmartInitializingSingleton { - - private final Set> applicationListeners = new HashSet>(); +public class IntegrationFlowBeanPostProcessor + implements BeanPostProcessor, BeanFactoryAware, SmartInitializingSingleton { private ConfigurableListableBeanFactory beanFactory; - private AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor; - @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory, @@ -86,8 +80,6 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean ); this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; - this.autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor(); - this.autowiredAnnotationBeanPostProcessor.setBeanFactory(this.beanFactory); } @Override @@ -111,13 +103,6 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean @Override public void afterSingletonsInstantiated() { - if (this.beanFactory.containsBean(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { - ApplicationEventMulticaster multicaster = - (ApplicationEventMulticaster) this.beanFactory.getBean( - AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME); - this.applicationListeners.forEach(multicaster::addApplicationListener); - } - for (String beanName : this.beanFactory.getBeanNamesForType(IntegrationFlow.class)) { if (this.beanFactory.containsBeanDefinition(beanName)) { String scope = this.beanFactory.getBeanDefinition(beanName).getScope(); @@ -135,8 +120,6 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean String flowNamePrefix = flowBeanName + "."; int subFlowNameIndex = 0; int channelNameIndex = 0; - boolean registerSingleton = flow.isRegisterComponents(); - Map integrationComponents = flow.getIntegrationComponents(); Map targetIntegrationComponents = new LinkedHashMap<>(integrationComponents.size()); @@ -161,13 +144,13 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean String handlerBeanName = generateBeanName(messageHandler); String[] handlerAlias = new String[] { id + IntegrationConfigUtils.HANDLER_ALIAS_SUFFIX }; - registerComponent(messageHandler, handlerBeanName, flowBeanName, registerSingleton); + registerComponent(messageHandler, handlerBeanName, flowBeanName); for (String alias : handlerAlias) { this.beanFactory.registerAlias(handlerBeanName, alias); } } - registerComponent(endpoint, id, flowBeanName, registerSingleton); + registerComponent(endpoint, id, flowBeanName); targetIntegrationComponents.put(endpoint, id); } else { @@ -182,14 +165,14 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + channelNameIndex++; } } - registerComponent(component, channelBeanName, flowBeanName, registerSingleton); + registerComponent(component, channelBeanName, flowBeanName); targetIntegrationComponents.put(component, channelBeanName); } else if (component instanceof MessageChannelReference) { String channelBeanName = ((MessageChannelReference) component).getName(); if (!this.beanFactory.containsBean(channelBeanName)) { DirectChannel directChannel = new DirectChannel(); - registerComponent(directChannel, channelBeanName, flowBeanName, registerSingleton); + registerComponent(directChannel, channelBeanName, flowBeanName); targetIntegrationComponents.put(directChannel, channelBeanName); } } @@ -200,7 +183,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean channelBeanName = flowNamePrefix + "channel" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + channelNameIndex++; } - registerComponent(component, channelBeanName, flowBeanName, registerSingleton); + registerComponent(component, channelBeanName, flowBeanName); targetIntegrationComponents.put(component, channelBeanName); } else if (component instanceof SourcePollingChannelAdapterSpec) { @@ -221,7 +204,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean if (!StringUtils.hasText(id)) { id = generateBeanName(pollingChannelAdapterFactoryBean, entry.getValue()); } - registerComponent(pollingChannelAdapterFactoryBean, id, flowBeanName, registerSingleton); + registerComponent(pollingChannelAdapterFactoryBean, id, flowBeanName); targetIntegrationComponents.put(pollingChannelAdapterFactoryBean, id); MessageSource messageSource = spec.get().getT2(); @@ -233,7 +216,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean && ((NamedComponent) messageSource).getComponentName() != null) { messageSourceId = ((NamedComponent) messageSource).getComponentName(); } - registerComponent(messageSource, messageSourceId, flowBeanName, registerSingleton); + registerComponent(messageSource, messageSourceId, flowBeanName); } } else if (component instanceof StandardIntegrationFlow) { @@ -242,19 +225,31 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean ? entry.getValue() : flowNamePrefix + "subFlow" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + subFlowNameIndex++; - registerComponent(component, subFlowBeanName, flowBeanName, registerSingleton); + registerComponent(component, subFlowBeanName, flowBeanName); targetIntegrationComponents.put(component, subFlowBeanName); } else if (component instanceof AnnotationGatewayProxyFactoryBean) { - String gatewayId = entry.getValue() != null - ? entry.getValue() - : flowNamePrefix + "gateway"; - registerComponent(component, gatewayId, flowBeanName, registerSingleton); + AnnotationGatewayProxyFactoryBean gateway = (AnnotationGatewayProxyFactoryBean) component; + String gatewayId = entry.getValue(); + + if (gatewayId == null) { + gatewayId = gateway.getComponentName(); + } + if (gatewayId == null) { + gatewayId = flowNamePrefix + "gateway"; + } + + registerComponent(gateway, gatewayId, flowBeanName, + beanDefinition -> { + ((AbstractBeanDefinition) beanDefinition) + .setSource(new DescriptiveResource(gateway.getObjectType().getName())); + }); + targetIntegrationComponents.put(component, gatewayId); } else { String generatedBeanName = generateBeanName(component, entry.getValue()); - registerComponent(component, generatedBeanName, flowBeanName, registerSingleton); + registerComponent(component, generatedBeanName, flowBeanName); targetIntegrationComponents.put(component, generatedBeanName); } } @@ -276,7 +271,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean } private void processIntegrationComponentSpec(IntegrationComponentSpec bean) { - registerComponent(bean.get(), generateBeanName(bean.get(), bean.getId()), null, false); + registerComponent(bean.get(), generateBeanName(bean.get(), bean.getId())); if (bean instanceof ComponentsRegistration) { Map componentsToRegister = ((ComponentsRegistration) bean).getComponentsToRegister(); if (!CollectionUtils.isEmpty(componentsToRegister)) { @@ -296,26 +291,25 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean } private void registerComponent(Object component, String beanName) { - registerComponent(component, beanName, null, true); + registerComponent(component, beanName, null); } - private void registerComponent(Object component, String beanName, String parentName, boolean registerSingleton) { - if (component instanceof ApplicationListener) { - this.applicationListeners.add((ApplicationListener) component); - } - this.autowiredAnnotationBeanPostProcessor.processInjection(component); - this.beanFactory.initializeBean(component, beanName); - if (registerSingleton) { - this.beanFactory.registerSingleton(beanName, component); - if (parentName != null) { - this.beanFactory.registerDependentBean(parentName, beanName); - } + @SuppressWarnings("unchecked") + private void registerComponent(Object component, String beanName, String parentName, + BeanDefinitionCustomizer... customizers) { + + BeanDefinition beanDefinition = + BeanDefinitionBuilder.genericBeanDefinition((Class) component.getClass(), () -> component) + .applyCustomizers(customizers) + .getRawBeanDefinition(); + + ((BeanDefinitionRegistry) this.beanFactory).registerBeanDefinition(beanName, beanDefinition); + + if (parentName != null) { + this.beanFactory.registerDependentBean(parentName, beanName); } - if (component instanceof DisposableBean) { - ((DefaultSingletonBeanRegistry) this.beanFactory) - .registerDisposableBean(beanName, (DisposableBean) component); - } + this.beanFactory.getBean(beanName); } private String generateBeanName(Object instance) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java b/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java index 1e5bc41f6f..683bfc0c94 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java @@ -302,28 +302,38 @@ public final class IntegrationFlows { * Populate the {@link MessageChannel} to the new {@link IntegrationFlowBuilder} * chain, which becomes as a {@code requestChannel} for the Messaging Gateway(s) built * on the provided service interface. - *

A gateway proxy bean for provided service interface is registered under a name of - * the {@link IntegrationFlow} bean plus {@code .gateway} suffix. + *

A gateway proxy bean for provided service interface is registered under a name + * from the + * {@link org.springframework.integration.annotation.MessagingGateway#name()} if present + * or from the {@link IntegrationFlow} bean name plus {@code .gateway} suffix. * @param serviceInterface the service interface class with an optional * {@link org.springframework.integration.annotation.MessagingGateway} annotation. * @return new {@link IntegrationFlowBuilder}. */ public static IntegrationFlowBuilder from(Class serviceInterface) { + return from(serviceInterface, null); + } + + /** + * Populate the {@link MessageChannel} to the new {@link IntegrationFlowBuilder} + * chain, which becomes as a {@code requestChannel} for the Messaging Gateway(s) built + * on the provided service interface. + *

A gateway proxy bean for provided service interface is registered under a name of + * the provided {@code beanName} if not null, or from the + * {@link org.springframework.integration.annotation.MessagingGateway#name()} if present + * or as a fallback to the {@link IntegrationFlow} bean name plus {@code .gateway} suffix. + * @param serviceInterface the service interface class with an optional + * {@link org.springframework.integration.annotation.MessagingGateway} annotation. + * @param beanName the bean name to be used for registering bean for the gateway proxy + * @return new {@link IntegrationFlowBuilder}. + */ + public static IntegrationFlowBuilder from(Class serviceInterface, String beanName) { final DirectChannel gatewayRequestChannel = new DirectChannel(); - GatewayProxyFactoryBean gatewayProxyFactoryBean = - new AnnotationGatewayProxyFactoryBean(serviceInterface) { + GatewayProxyFactoryBean gatewayProxyFactoryBean = new AnnotationGatewayProxyFactoryBean(serviceInterface); - @Override - protected void onInit() { - super.onInit(); - getGateways() - .values() - .forEach(gateway -> - gateway.setRequestChannel(gatewayRequestChannel)); - } - - }; + gatewayProxyFactoryBean.setDefaultRequestChannel(gatewayRequestChannel); + gatewayProxyFactoryBean.setBeanName(beanName); return from(gatewayRequestChannel) .addComponent(gatewayProxyFactoryBean); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/dsl/StandardIntegrationFlow.java b/spring-integration-core/src/main/java/org/springframework/integration/dsl/StandardIntegrationFlow.java index 57dc69783d..d657de9740 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/dsl/StandardIntegrationFlow.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/dsl/StandardIntegrationFlow.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-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. @@ -69,23 +69,12 @@ public class StandardIntegrationFlow implements IntegrationFlow, SmartLifecycle private final List lifecycles = new LinkedList<>(); - private final boolean registerComponents = true; // NOSONAR - private boolean running; StandardIntegrationFlow(Map integrationComponents) { this.integrationComponents = new LinkedHashMap<>(integrationComponents); } - //TODO Figure out some custom DestinationResolver when we don't register singletons - remove NOSONAR above when done - /*public void setRegisterComponents(boolean registerComponents) { - this.registerComponents = registerComponents; - }*/ - - public boolean isRegisterComponents() { - return this.registerComponents; - } - public void setIntegrationComponents(Map integrationComponents) { this.integrationComponents.clear(); this.integrationComponents.putAll(integrationComponents); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/dsl/context/IntegrationFlowContext.java b/spring-integration-core/src/main/java/org/springframework/integration/dsl/context/IntegrationFlowContext.java index c77fdc0319..57cc104a6b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/dsl/context/IntegrationFlowContext.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/dsl/context/IntegrationFlowContext.java @@ -16,6 +16,7 @@ package org.springframework.integration.dsl.context; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -24,10 +25,10 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.support.context.NamedComponent; @@ -68,8 +69,6 @@ public final class IntegrationFlowContext implements BeanFactoryAware { private ConfigurableListableBeanFactory beanFactory; - private AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor; - private IntegrationFlowContext() { } @@ -80,8 +79,6 @@ public final class IntegrationFlowContext implements BeanFactoryAware { "'ConfigurableListableBeanFactory'. " + "Consider using 'GenericApplicationContext' implementation."); this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; - this.autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor(); - this.autowiredAnnotationBeanPostProcessor.setBeanFactory(this.beanFactory); } /** @@ -113,22 +110,23 @@ public final class IntegrationFlowContext implements BeanFactoryAware { this.registry.put(flowId, builder.integrationFlowRegistration); } + @SuppressWarnings("unchecked") private Object registerBean(Object bean, String beanName, String parentName) { if (beanName == null) { beanName = generateBeanName(bean, parentName); } - this.autowiredAnnotationBeanPostProcessor.processInjection(bean); - bean = this.beanFactory.initializeBean(bean, beanName); - this.beanFactory.registerSingleton(beanName, bean); + BeanDefinition beanDefinition = + BeanDefinitionBuilder.genericBeanDefinition((Class) bean.getClass(), () -> bean) + .getRawBeanDefinition(); + + ((BeanDefinitionRegistry) this.beanFactory).registerBeanDefinition(beanName, beanDefinition); + if (parentName != null) { this.beanFactory.registerDependentBean(parentName, beanName); } - if (bean instanceof DisposableBean) { - ((DefaultSingletonBeanRegistry) this.beanFactory) - .registerDisposableBean(beanName, (DisposableBean) bean); - } - return bean; + + return this.beanFactory.getBean(beanName); } /** @@ -150,7 +148,11 @@ public final class IntegrationFlowContext implements BeanFactoryAware { if (this.registry.containsKey(flowId)) { IntegrationFlowRegistration flowRegistration = this.registry.remove(flowId); flowRegistration.stop(); - ((DefaultSingletonBeanRegistry) this.beanFactory).destroySingleton(flowId); + + Arrays.stream(this.beanFactory.getDependentBeans(flowId)) + .forEach(((BeanDefinitionRegistry) this.beanFactory)::removeBeanDefinition); + + ((BeanDefinitionRegistry) this.beanFactory).removeBeanDefinition(flowId); } else { throw new IllegalStateException("Only manually registered IntegrationFlows can be removed. " @@ -207,7 +209,7 @@ public final class IntegrationFlowContext implements BeanFactoryAware { private boolean autoStartup = true; - IntegrationFlowRegistrationBuilder(IntegrationFlow integrationFlow) { + private IntegrationFlowRegistrationBuilder(IntegrationFlow integrationFlow) { this.integrationFlowRegistration = new IntegrationFlowRegistration(integrationFlow); this.integrationFlowRegistration.setBeanFactory(IntegrationFlowContext.this.beanFactory); this.integrationFlowRegistration.setIntegrationFlowContext(IntegrationFlowContext.this); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java index 859e5fd3f5..bf9f56dbd7 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java @@ -47,13 +47,20 @@ public class AnnotationGatewayProxyFactoryBean extends GatewayProxyFactoryBean { public AnnotationGatewayProxyFactoryBean(Class serviceInterface) { super(serviceInterface); - AnnotationAttributes gatewayAttributes = AnnotatedElementUtils.getMergedAnnotationAttributes(serviceInterface, - MessagingGateway.class.getName(), false, true); + AnnotationAttributes gatewayAttributes = + AnnotatedElementUtils.getMergedAnnotationAttributes(serviceInterface, + MessagingGateway.class.getName(), false, true); if (gatewayAttributes == null) { gatewayAttributes = AnnotationUtils.getAnnotationAttributes( AnnotationUtils.synthesizeAnnotation(MessagingGateway.class), false, true); } + this.gatewayAttributes = gatewayAttributes; + + String id = gatewayAttributes.getString("name"); + if (!StringUtils.hasText(id)) { + setBeanName(id); + } } @Override diff --git a/spring-integration-core/src/test/java/org/springframework/integration/dsl/flows/IntegrationFlowTests.java b/spring-integration-core/src/test/java/org/springframework/integration/dsl/flows/IntegrationFlowTests.java index 0744596e9a..f66d211568 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/dsl/flows/IntegrationFlowTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/dsl/flows/IntegrationFlowTests.java @@ -444,6 +444,7 @@ public class IntegrationFlowTests { } @Autowired + @Qualifier("errorRecovererFunction") private Function errorRecovererFlowGateway; @Test @@ -789,7 +790,7 @@ public class IntegrationFlowTests { @Bean public IntegrationFlow errorRecovererFlow() { - return IntegrationFlows.from(Function.class) + return IntegrationFlows.from(Function.class, "errorRecovererFunction") .handle((GenericHandler) (p, h) -> { throw new RuntimeException("intentional"); }, e -> e.advice(retryAdvice()))