id is now a fallback for a generated channel name

This commit is contained in:
Mark Fisher
2011-08-22 14:40:52 -04:00
parent 2d151932fc
commit cbde3470d6
7 changed files with 191 additions and 5 deletions

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -24,10 +24,13 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" use="required" type="xsd:string">
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
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"
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
@@ -86,10 +89,12 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inboundType">
<xsd:attribute name="channel" use="required" type="xsd:string">
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
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"
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp-2.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<amqp:inbound-channel-adapter id="rabbitInbound" queue-names="inboundchanneladapter.test.1"/>
<bean id="connectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.springframework.amqp.rabbit.connection.ConnectionFactory"/>
</bean>
</beans>

View File

@@ -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());
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp-2.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<amqp:outbound-channel-adapter id="rabbitOutbound" exchange-name="outboundchanneladapter.test.1"/>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/>
<bean id="connectionFactory" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.springframework.amqp.rabbit.connection.ConnectionFactory"/>
</bean>
</beans>

View File

@@ -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());
}
}