diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/ConnectionFactoryParser.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/ConnectionFactoryParser.java
new file mode 100644
index 00000000..a5a65cd9
--- /dev/null
+++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/ConnectionFactoryParser.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010-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.amqp.rabbit.config;
+
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+/**
+ * @author Dave Syer
+ */
+class ConnectionFactoryParser extends AbstractSingleBeanDefinitionParser {
+
+ private static final String CONNECTION_FACTORY_ATTRIBUTE = "connection-factory";
+
+ private static final String CHANNEL_CACHE_SIZE_ATTRIBUTE = "channel-cache-size";
+
+ private static final String HOST_ATTRIBUTE = "host";
+
+ private static final String PORT_ATTRIBUTE = "port";
+
+ private static final String VIRTUAL_HOST_ATTRIBUTE = "virtual-host";
+
+ private static final String USER_ATTRIBUTE = "username";
+
+ private static final String PASSWORD_ATTRIBUTE = "password";
+
+ @Override
+ protected Class> getBeanClass(Element element) {
+ return CachingConnectionFactory.class;
+ }
+
+ @Override
+ protected boolean shouldGenerateId() {
+ return false;
+ }
+
+ @Override
+ protected boolean shouldGenerateIdAsFallback() {
+ return true;
+ }
+
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+
+ NamespaceUtils.addConstructorArgParentRefIfAttributeDefined(builder, element, CONNECTION_FACTORY_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, CHANNEL_CACHE_SIZE_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, HOST_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, PORT_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, USER_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, PASSWORD_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, VIRTUAL_HOST_ATTRIBUTE);
+
+ }
+
+}
diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/NamespaceUtils.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/NamespaceUtils.java
index 0d479edc..906f05f5 100644
--- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/NamespaceUtils.java
+++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/NamespaceUtils.java
@@ -49,12 +49,14 @@ public abstract class NamespaceUtils {
* @param attributeName the name of the attribute whose value will be used to populate the property
* @param propertyName the name of the property to be populated
*/
- public static void setValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element, String attributeName,
- String propertyName) {
+ public static boolean setValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ String attributeName, String propertyName) {
String attributeValue = element.getAttribute(attributeName);
if (StringUtils.hasText(attributeValue)) {
builder.addPropertyValue(propertyName, attributeValue);
+ return true;
}
+ return false;
}
/**
@@ -71,8 +73,9 @@ public abstract class NamespaceUtils {
* @param element the XML element where the attribute should be defined
* @param attributeName the name of the attribute whose value will be set on the property
*/
- public static void setValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element, String attributeName) {
- setValueIfAttributeDefined(builder, element, attributeName,
+ public static boolean setValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ String attributeName) {
+ return setValueIfAttributeDefined(builder, element, attributeName,
Conventions.attributeNameToPropertyName(attributeName));
}
@@ -95,17 +98,19 @@ public abstract class NamespaceUtils {
* @param element the XML element where the attribute should be defined
* @param attributeName the name of the attribute whose value will be used as a constructor argument
*/
- public static void addConstructorArgValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ public static boolean addConstructorArgValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
String attributeName) {
String value = element.getAttribute(attributeName);
if (StringUtils.hasText(value)) {
builder.addConstructorArgValue(new TypedStringValue(value));
+ return true;
}
+ return false;
}
/**
- * Populates the bean definition constructor argument with the boolean value of that attribute if it is defined in the given
- * element or else uses the default provided.
+ * Populates the bean definition constructor argument with the boolean value of that attribute if it is defined in
+ * the given element or else uses the default provided.
*
* @param builder the bean definition builder to be configured
* @param element the XML element where the attribute should be defined
@@ -130,12 +135,34 @@ public abstract class NamespaceUtils {
* @param element the XML element where the attribute should be defined
* @param attributeName the name of the attribute whose value will be used to set the reference
*/
- public static void addConstructorArgRefIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ public static boolean addConstructorArgRefIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
String attributeName) {
String value = element.getAttribute(attributeName);
if (StringUtils.hasText(value)) {
builder.addConstructorArgReference(value);
+ return true;
}
+ return false;
+ }
+
+ /**
+ * Populates the bean definition constructor argument with a reference to a bean with parent id equal to the
+ * attribute if it is defined in the given element.
+ *
+ * @param builder the bean definition builder to be configured
+ * @param element the XML element where the attribute should be defined
+ * @param attributeName the name of the attribute whose value will be used to set the reference
+ */
+ public static boolean addConstructorArgParentRefIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ String attributeName) {
+ String value = element.getAttribute(attributeName);
+ if (StringUtils.hasText(value)) {
+ BeanDefinitionBuilder child = BeanDefinitionBuilder.genericBeanDefinition();
+ child.setParentName(value);
+ builder.addConstructorArgValue(child.getBeanDefinition());
+ return true;
+ }
+ return false;
}
/**
@@ -147,13 +174,16 @@ public abstract class NamespaceUtils {
* @param attributeName the name of the attribute whose value will be used as a bean reference to populate the
* property
* @param propertyName the name of the property to be populated
+ * @return
*/
- public static void setReferenceIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ public static boolean setReferenceIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
String attributeName, String propertyName) {
String attributeValue = element.getAttribute(attributeName);
if (StringUtils.hasText(attributeValue)) {
builder.addPropertyReference(propertyName, attributeValue);
+ return true;
}
+ return false;
}
/**
@@ -173,9 +203,9 @@ public abstract class NamespaceUtils {
*
* @see Conventions#attributeNameToPropertyName(String)
*/
- public static void setReferenceIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
+ public static boolean setReferenceIfAttributeDefined(BeanDefinitionBuilder builder, Element element,
String attributeName) {
- setReferenceIfAttributeDefined(builder, element, attributeName,
+ return setReferenceIfAttributeDefined(builder, element, attributeName,
Conventions.attributeNameToPropertyName(attributeName));
}
diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandler.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandler.java
index 1dada394..b1060aaf 100644
--- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandler.java
+++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandler.java
@@ -35,6 +35,8 @@ public class RabbitNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("headers-exchange", new HeadersExchangeParser());
registerBeanDefinitionParser("listener-container", new ListenerContainerParser());
registerBeanDefinitionParser("admin", new AdminParser());
+ registerBeanDefinitionParser("connection-factory", new ConnectionFactoryParser());
+ registerBeanDefinitionParser("template", new TemplateParser());
}
}
diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/TemplateParser.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/TemplateParser.java
new file mode 100644
index 00000000..5baaee6e
--- /dev/null
+++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/TemplateParser.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010-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.amqp.rabbit.config;
+
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * @author Dave Syer
+ */
+class TemplateParser extends AbstractSingleBeanDefinitionParser {
+
+ private static final String CONNECTION_FACTORY_ATTRIBUTE = "connection-factory";
+
+ private static final String EXCHANGE_ATTRIBUTE = "exchange";
+
+ private static final String QUEUE_ATTRIBUTE = "queue";
+
+ private static final String ROUTING_KEY_ATTRIBUTE = "routing-key";
+
+ private static final String REPLY_TIMEOUT_ATTRIBUTE = "reply-timeout";
+
+ private static final String MESSAGE_CONVERTER_ATTRIBUTE = "message-converter";
+
+ private static final String ENCODING_ATTRIBUTE = "encoding";
+
+ private static final String CHANNEL_TRANSACTED_ATTRIBUTE = "channel-transacted";
+
+ @Override
+ protected Class> getBeanClass(Element element) {
+ return RabbitTemplate.class;
+ }
+
+ @Override
+ protected boolean shouldGenerateId() {
+ return false;
+ }
+
+ @Override
+ protected boolean shouldGenerateIdAsFallback() {
+ return true;
+ }
+
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+ String connectionFactoryRef = element.getAttribute(CONNECTION_FACTORY_ATTRIBUTE);
+
+ if (!StringUtils.hasText(connectionFactoryRef)) {
+ parserContext.getReaderContext().error("A '" + CONNECTION_FACTORY_ATTRIBUTE + "' attribute must be set.",
+ element);
+ }
+
+ if (StringUtils.hasText(connectionFactoryRef)) {
+ // Use constructor with connectionFactory parameter
+ builder.addConstructorArgReference(connectionFactoryRef);
+ }
+
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, CHANNEL_TRANSACTED_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, QUEUE_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, EXCHANGE_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, ROUTING_KEY_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, REPLY_TIMEOUT_ATTRIBUTE);
+ NamespaceUtils.setValueIfAttributeDefined(builder, element, ENCODING_ATTRIBUTE);
+ NamespaceUtils.setReferenceIfAttributeDefined(builder, element, MESSAGE_CONVERTER_ATTRIBUTE);
+
+ }
+
+}
diff --git a/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.0.xsd b/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.0.xsd
index f3236f85..593f6642 100644
--- a/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.0.xsd
+++ b/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.0.xsd
@@ -1,8 +1,7 @@
-
@@ -18,8 +17,7 @@
-
+
@@ -92,8 +90,7 @@
-
+
-
+
-
+
-
+
-
+
@@ -251,16 +244,14 @@
]]>
-
+
-
+
-
+
@@ -373,13 +363,13 @@
]]>
-
+
-
+
@@ -396,7 +386,7 @@
]]>
-
+
@@ -409,7 +399,7 @@
]]>
-
+
@@ -423,7 +413,7 @@
]]>
-
+
@@ -436,7 +426,7 @@
]]>
-
+
@@ -449,9 +439,9 @@
-
-
-
+
+
+
@@ -462,7 +452,7 @@
]]>
-
+
@@ -540,7 +530,7 @@
or defining the specified listener method. Required.
]]>
-
+
@@ -600,8 +590,7 @@
]]>
-
+
@@ -615,4 +604,161 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ConnectionFactoryParserTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ConnectionFactoryParserTests.java
new file mode 100644
index 00000000..d90711a6
--- /dev/null
+++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ConnectionFactoryParserTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-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.amqp.rabbit.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ *
+ * @author Dave Syer
+ *
+ */
+public final class ConnectionFactoryParserTests {
+
+ private XmlBeanFactory beanFactory;
+
+ @Before
+ public void setUpDefaultBeanFactory() throws Exception {
+ beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass()));
+ }
+
+ @Test
+ public void testKitchenSink() throws Exception {
+ CachingConnectionFactory connectionFactory = beanFactory.getBean("kitchenSink", CachingConnectionFactory.class);
+ assertNotNull(connectionFactory);
+ assertEquals(10, connectionFactory.getChannelCacheSize());
+ }
+
+ @Test
+ public void testNative() throws Exception {
+ CachingConnectionFactory connectionFactory = beanFactory.getBean("native", CachingConnectionFactory.class);
+ assertNotNull(connectionFactory);
+ assertEquals(10, connectionFactory.getChannelCacheSize());
+ }
+
+}
diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/TemplateParserTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/TemplateParserTests.java
new file mode 100644
index 00000000..d8de26a7
--- /dev/null
+++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/TemplateParserTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-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.amqp.rabbit.config;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.SerializerMessageConverter;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ *
+ * @author Dave Syer
+ *
+ */
+public final class TemplateParserTests {
+
+ private XmlBeanFactory beanFactory;
+
+ @Before
+ public void setUpDefaultBeanFactory() throws Exception {
+ beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass()));
+ }
+
+ @Test
+ public void testTemplate() throws Exception {
+ AmqpTemplate template = beanFactory.getBean("template", AmqpTemplate.class);
+ assertNotNull(template);
+ }
+
+ @Test
+ public void testKitchenSink() throws Exception {
+ RabbitTemplate template = beanFactory.getBean("kitchenSink", RabbitTemplate.class);
+ assertNotNull(template);
+ assertTrue(template.getMessageConverter() instanceof SerializerMessageConverter);
+ }
+
+}
diff --git a/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/ConnectionFactoryParserTests-context.xml b/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/ConnectionFactoryParserTests-context.xml
new file mode 100644
index 00000000..4ed92b34
--- /dev/null
+++ b/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/ConnectionFactoryParserTests-context.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/TemplateParserTests-context.xml b/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/TemplateParserTests-context.xml
new file mode 100644
index 00000000..275fa881
--- /dev/null
+++ b/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/TemplateParserTests-context.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/docbkx/amqp.xml b/src/docbkx/amqp.xml
index 6bef972a..123d4397 100644
--- a/src/docbkx/amqp.xml
+++ b/src/docbkx/amqp.xml
@@ -242,7 +242,8 @@ Connection connection = connectionFactory.createConnection();]]>When using XML, the configuration might look like this:
-
+
@@ -266,7 +267,12 @@ Connection connection = connectionFactory.createConnection();]]>SingleConnectionFactory
as useful for simple tests and maybe as a building block for extending the framework.
-
+ A ConnectionFactory can be created
+ quickly and conveniently using the rabbit namespace: ]]>
+ In most cases this will be preferable since the framework can choose the
+ best defaults for you, and it will always choose a
+ CachingConnectionFactory.
@@ -692,13 +698,9 @@ Object receiveAndConvert(String queueName) throws AmqpException;]]>The RabbitMQ implementation of this interface is RabbitAdmin which
when configured using Spring XML would look like this:
-
-
-
-
+ language="xml">
-]]>
+]]>
The RabbitAdmin implementation does automatic
lazy declaration of Queues,
@@ -733,10 +735,11 @@ Object receiveAndConvert(String queueName) throws AmqpException;]]>]]>
To see how to use Java to configure the AMQP infrastructure, look at
- the Stock sample application, there is the @Configuration class
- AbstractStockRabbitConfiguration which in turn has
- RabbitClientConfiguration and RabbitServerConfiguration subclasses. The
- code for AbstractStockRabbitConfiguration is show below
+ the Stock sample application, there is the @Configuration
+ class AbstractStockRabbitConfiguration which in
+ turn has RabbitClientConfiguration and RabbitServerConfiguration
+ subclasses. The code for AbstractStockRabbitConfiguration is show
+ below
-