diff --git a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParser.java b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParser.java index f4df79f62c..863ecc34a3 100644 --- a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParser.java +++ b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParser.java @@ -18,9 +18,13 @@ package org.springframework.integration.amqp.config; import org.w3c.dom.Element; +import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.springframework.util.StringUtils; /** * Parser for the AMQP 'inbound-channel-adapter' element. @@ -34,10 +38,39 @@ public class AmqpInboundChannelAdapterParser extends AbstractAmqpInboundAdapterP super("org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter"); } + @Override + protected final String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException { + String id = element.getAttribute("id"); + if (!element.hasAttribute("channel")) { + // the created channel will get the 'id', so the adapter's bean name includes a suffix + id = id + ".adapter"; + } + else if (!StringUtils.hasText(id)) { + id = parserContext.getReaderContext().generateBeanName(definition); + } + return id; + } @Override protected void configureChannels(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "outputChannel"); + String channelName = element.getAttribute("channel"); + if (!StringUtils.hasText(channelName)) { + channelName = this.createDirectChannel(element, parserContext); + } + builder.addPropertyReference("outputChannel", channelName); + } + + private String createDirectChannel(Element element, ParserContext parserContext) { + String channelId = element.getAttribute("id"); + if (!StringUtils.hasText(channelId)) { + parserContext.getReaderContext().error("The channel-adapter's 'id' attribute is required when no 'channel' " + + "reference has been provided, because that 'id' would be used for the created channel.", element); + } + BeanDefinitionBuilder channelBuilder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.channel.DirectChannel"); + BeanDefinitionHolder holder = new BeanDefinitionHolder(channelBuilder.getBeanDefinition(), channelId); + BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry()); + return channelId; } } diff --git a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/outbound/AmqpOutboundEndpoint.java b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/outbound/AmqpOutboundEndpoint.java index 5a2ad4771e..b7ebf76aae 100644 --- a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/outbound/AmqpOutboundEndpoint.java +++ b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/outbound/AmqpOutboundEndpoint.java @@ -90,6 +90,11 @@ public class AmqpOutboundEndpoint extends AbstractReplyProducingMessageHandler { this.expectReply = expectReply; } + @Override + public String getComponentType() { + return expectReply ? "amqp:outbound-channel-adapter" : "amqp:outbound-gateway"; + } + @Override protected Object handleRequestMessage(Message requestMessage) { String routingKey = this.routingKey; diff --git a/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.1.xsd b/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.1.xsd index fb2b1fe52e..c2f08a2d8d 100644 --- a/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.1.xsd +++ b/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.1.xsd @@ -24,10 +24,13 @@ - + Message Channel to which Messages should be sent in order to have them converted and published to an AMQP Exchange. + If this attribute is not provided, the ID will be used to create a new DirectChannel, and then instead of using that + ID as the bean name of the EventDrivenConsumer instance that hosts the MessageHandler responsible for publishing the + AMQP Messages, that EventDrivenConsumer's bean name will be the ID plus the added suffix: ".adapter" @@ -86,10 +89,12 @@ - + - Message Channel to which converted Messages should be sent. + Message Channel to which converted Messages should be sent. If this attribute is not provided, the ID will + be used to create a new DirectChannel, and then instead of using that ID as the bean name of the Channel Adapter + instance, the bean name will be the ID plus the added suffix: ".adapter" diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests-context.xml b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests-context.xml new file mode 100644 index 0000000000..3f04d4be35 --- /dev/null +++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests-context.xml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests.java new file mode 100644 index 0000000000..d6ffd7749e --- /dev/null +++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.amqp.config; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Mark Fisher + * @since 2.1 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class AmqpInboundChannelAdapterParserTests { + + @Autowired + private ApplicationContext context; + + @Test + public void verifyIdAsChannel() { + Object channel = context.getBean("rabbitInbound"); + Object adapter = context.getBean("rabbitInbound.adapter"); + assertEquals(DirectChannel.class, channel.getClass()); + assertEquals(AmqpInboundChannelAdapter.class, adapter.getClass()); + } + +} diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml new file mode 100644 index 0000000000..caa016ce19 --- /dev/null +++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java new file mode 100644 index 0000000000..4f06e24360 --- /dev/null +++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.amqp.config; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.integration.amqp.outbound.AmqpOutboundEndpoint; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageHandler; +import org.springframework.integration.endpoint.EventDrivenConsumer; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Mark Fisher + * @since 2.1 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class AmqpOutboundChannelAdapterParserTests { + + @Autowired + private ApplicationContext context; + + @Test + public void verifyIdAsChannel() { + Object channel = context.getBean("rabbitOutbound"); + Object adapter = context.getBean("rabbitOutbound.adapter"); + assertEquals(DirectChannel.class, channel.getClass()); + assertEquals(EventDrivenConsumer.class, adapter.getClass()); + MessageHandler handler = TestUtils.getPropertyValue(adapter, "handler", MessageHandler.class); + assertEquals(AmqpOutboundEndpoint.class, handler.getClass()); + } + +}