diff --git a/build.gradle b/build.gradle index 885b572a..bb3c7741 100644 --- a/build.gradle +++ b/build.gradle @@ -45,9 +45,9 @@ subprojects { subproject -> junitVersion = '4.8.2' log4jVersion = '1.2.15' mockitoVersion = '1.8.4' - rabbitmqVersion = '3.0.3' + rabbitmqVersion = '3.0.4' - springVersion = '3.0.7.RELEASE' + springVersion = '3.1.4.RELEASE' } eclipse { diff --git a/spring-amqp/src/main/java/org/springframework/amqp/core/AmqpAdmin.java b/spring-amqp/src/main/java/org/springframework/amqp/core/AmqpAdmin.java index cad85031..eba9ba7a 100644 --- a/spring-amqp/src/main/java/org/springframework/amqp/core/AmqpAdmin.java +++ b/spring-amqp/src/main/java/org/springframework/amqp/core/AmqpAdmin.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2013 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 @@ -13,11 +13,15 @@ package org.springframework.amqp.core; +import java.util.Properties; + + /** * Specifies a basic set of portable AMQP administrative operations for AMQP > 0.8 * * @author Mark Pollack * @author Dave Syer + * @author Gary Russell */ public interface AmqpAdmin { @@ -88,4 +92,11 @@ public interface AmqpAdmin { */ void removeBinding(Binding binding); + /** + * Returns an implementation-specific Map of properties if the queue exists. + * @param queueName the name of the queue. + * @return the properties or null if the queue doesn't exist + */ + Properties getQueueProperties(String queueName); + } diff --git a/spring-amqp/src/main/java/org/springframework/amqp/support/converter/MarshallingMessageConverter.java b/spring-amqp/src/main/java/org/springframework/amqp/support/converter/MarshallingMessageConverter.java index 64460b27..9bc12e06 100644 --- a/spring-amqp/src/main/java/org/springframework/amqp/support/converter/MarshallingMessageConverter.java +++ b/spring-amqp/src/main/java/org/springframework/amqp/support/converter/MarshallingMessageConverter.java @@ -39,8 +39,8 @@ import org.springframework.util.Assert; * @author Arjen Poutsma * @author Juergen Hoeller * @author James Carr - * @see org.springframework.amqp.rabbit.core.RabbitTemplate#convertAndSend - * @see org.springframework.amqp.rabbit.core.RabbitTemplate#receiveAndConvert + * @see org.springframework.amqp.core.AmqpTemplate#convertAndSend(Object) + * @see org.springframework.amqp.core.AmqpTemplate#receiveAndConvert() */ public class MarshallingMessageConverter extends AbstractMessageConverter implements InitializingBean { private volatile Marshaller marshaller; @@ -128,6 +128,7 @@ public class MarshallingMessageConverter extends AbstractMessageConverter implem /** * Marshals the given object to a {@link Message}. */ + @Override protected Message createMessage(Object object, MessageProperties messageProperties) throws MessageConversionException { try { if (contentType != null) { @@ -149,6 +150,7 @@ public class MarshallingMessageConverter extends AbstractMessageConverter implem /** * Unmarshals the given {@link Message} into an object. */ + @Override public Object fromMessage(Message message) throws MessageConversionException { try { ByteArrayInputStream bis = new ByteArrayInputStream(message.getBody()); diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/AdminParser.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/AdminParser.java index dc8eb50f..0ab32020 100644 --- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/AdminParser.java +++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/config/AdminParser.java @@ -29,6 +29,8 @@ class AdminParser extends AbstractSingleBeanDefinitionParser { private static final String AUTO_STARTUP_ATTRIBUTE = "auto-startup"; + private static final String IGNORE_DECLARATION_EXCEPTIONS = "ignore-declaration-exceptions"; + @Override protected String getBeanClassName(Element element) { return "org.springframework.amqp.rabbit.core.RabbitAdmin"; @@ -64,5 +66,7 @@ class AdminParser extends AbstractSingleBeanDefinitionParser { if (StringUtils.hasText(attributeValue)) { builder.addPropertyValue("autoStartup", attributeValue); } + + NamespaceUtils.setValueIfAttributeDefined(builder, element, IGNORE_DECLARATION_EXCEPTIONS); } } diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/core/RabbitAdmin.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/core/RabbitAdmin.java index 7a7b950a..7bf9611c 100644 --- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/core/RabbitAdmin.java +++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/core/RabbitAdmin.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2013 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 @@ -15,6 +15,7 @@ package org.springframework.amqp.rabbit.core; import java.io.IOException; import java.util.Collection; +import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.logging.Log; @@ -42,11 +43,18 @@ import com.rabbitmq.client.Channel; * @author Mark Fisher * @author Dave Syer * @author Ed Scriven + * @author Gary Russell */ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, InitializingBean { protected static final String DEFAULT_EXCHANGE_NAME = ""; + protected static final Object QUEUE_NAME = "QUEUE_NAME"; + + protected static final Object QUEUE_MESSAGE_COUNT = "QUEUE_MESSAGE_COUNT"; + + protected static final Object QUEUE_CONSUMER_COUNT = "QUEUE_CONSUMER_COUNT"; + /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); @@ -58,6 +66,8 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali private volatile ApplicationContext applicationContext; + private volatile boolean ignoreDeclarationExceptions; + private final Object lifecycleMonitor = new Object(); private final ConnectionFactory connectionFactory; @@ -76,6 +86,10 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali this.applicationContext = applicationContext; } + public void setIgnoreDeclarationExceptions(boolean ignoreDeclarationExceptions) { + this.ignoreDeclarationExceptions = ignoreDeclarationExceptions; + } + public RabbitTemplate getRabbitTemplate() { return this.rabbitTemplate; } @@ -200,6 +214,32 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali }); } + /** + * Returns 3 properties {@link #QUEUE_NAME}, {@link #QUEUE_MESSAGE_COUNT}, + * {@link #QUEUE_CONSUMER_COUNT}, or null if the queue doesn't exist. + */ + public Properties getQueueProperties(final String queueName) { + Assert.hasText(queueName, "'queueName' cannot be null or empty"); + return this.rabbitTemplate.execute(new ChannelCallback() { + public Properties doInRabbit(Channel channel) throws Exception { + try { + DeclareOk declareOk = channel.queueDeclarePassive(queueName); + Properties props = new Properties(); + props.put(QUEUE_NAME, declareOk.getQueue()); + props.put(QUEUE_MESSAGE_COUNT, declareOk.getMessageCount()); + props.put(QUEUE_CONSUMER_COUNT, declareOk.getConsumerCount()); + return props; + } + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Queue '" + queueName + "' does not exist"); + } + return null; + } + } + }); + } + // Lifecycle implementation public boolean isAutoStartup() { @@ -226,7 +266,7 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali connectionFactory.addConnectionListener(new ConnectionListener() { // Prevent stack overflow... - private AtomicBoolean initializing = new AtomicBoolean(false); + private final AtomicBoolean initializing = new AtomicBoolean(false); public void onCreate(Connection connection) { if (!initializing.compareAndSet(false, true)) { @@ -327,8 +367,20 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali } if (!isDeclaringDefaultExchange(exchange)) { - channel.exchangeDeclare(exchange.getName(), exchange.getType(), exchange.isDurable(), + try { + channel.exchangeDeclare(exchange.getName(), exchange.getType(), exchange.isDurable(), exchange.isAutoDelete(), exchange.getArguments()); + } + catch (IOException e) { + if (this.ignoreDeclarationExceptions) { + if (logger.isWarnEnabled()) { + logger.warn("Failed to declare exchange:" + exchange + ", continuing...", e); + } + } + else { + throw e; + } + } } } } @@ -339,8 +391,20 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali if (logger.isDebugEnabled()) { logger.debug("declaring Queue '" + queue.getName() + "'"); } - channel.queueDeclare(queue.getName(), queue.isDurable(), queue.isExclusive(), queue.isAutoDelete(), - queue.getArguments()); + try { + channel.queueDeclare(queue.getName(), queue.isDurable(), queue.isExclusive(), queue.isAutoDelete(), + queue.getArguments()); + } + catch (IOException e) { + if (this.ignoreDeclarationExceptions) { + if (logger.isWarnEnabled()) { + logger.warn("Failed to declare queue:" + queue + ", continuing...", e); + } + } + else { + throw e; + } + } } else if (logger.isDebugEnabled()) { logger.debug("Queue with name that starts with 'amq.' cannot be declared."); } @@ -355,14 +419,26 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Initiali + "]"); } - if (binding.isDestinationQueue()) { - if (!isDeclaringImplicitQueueBinding(binding)) { - channel.queueBind(binding.getDestination(), binding.getExchange(), binding.getRoutingKey(), + try { + if (binding.isDestinationQueue()) { + if (!isDeclaringImplicitQueueBinding(binding)) { + channel.queueBind(binding.getDestination(), binding.getExchange(), binding.getRoutingKey(), + binding.getArguments()); + } + } else { + channel.exchangeBind(binding.getDestination(), binding.getExchange(), binding.getRoutingKey(), binding.getArguments()); } - } else { - channel.exchangeBind(binding.getDestination(), binding.getExchange(), binding.getRoutingKey(), - binding.getArguments()); + } + catch (IOException e) { + if (this.ignoreDeclarationExceptions) { + if (logger.isWarnEnabled()) { + logger.warn("Failed to declare binding:" + binding + ", continuing...", e); + } + } + else { + throw e; + } } } } diff --git a/spring-rabbit/src/main/resources/META-INF/spring.schemas b/spring-rabbit/src/main/resources/META-INF/spring.schemas index 381ab896..10a4cb6d 100644 --- a/spring-rabbit/src/main/resources/META-INF/spring.schemas +++ b/spring-rabbit/src/main/resources/META-INF/spring.schemas @@ -1,3 +1,4 @@ +http\://www.springframework.org/schema/rabbit/spring-rabbit-1.2.xsd=org/springframework/amqp/rabbit/config/spring-rabbit-1.2.xsd http\://www.springframework.org/schema/rabbit/spring-rabbit-1.1.xsd=org/springframework/amqp/rabbit/config/spring-rabbit-1.1.xsd http\://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd=org/springframework/amqp/rabbit/config/spring-rabbit-1.0.xsd -http\://www.springframework.org/schema/rabbit/spring-rabbit.xsd=org/springframework/amqp/rabbit/config/spring-rabbit-1.1.xsd +http\://www.springframework.org/schema/rabbit/spring-rabbit.xsd=org/springframework/amqp/rabbit/config/spring-rabbit-1.2.xsd diff --git a/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.2.xsd b/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.2.xsd index 91ae9d1e..f34dae07 100644 --- a/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.2.xsd +++ b/spring-rabbit/src/main/resources/org/springframework/amqp/rabbit/config/spring-rabbit-1.2.xsd @@ -768,12 +768,27 @@ - + + + + + + + + + + + + diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/AdminParserTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/AdminParserTests.java index b98676df..080dc5b0 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/AdminParserTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/AdminParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2010-2013 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 @@ -23,13 +23,15 @@ import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; import org.springframework.util.StringUtils; /** * * @author tomas.lukosius@opencredo.com + * @author Gary Russell * */ public final class AdminParserTests { @@ -65,7 +67,7 @@ public final class AdminParserTests { private void doTest() throws Exception { // Create context - XmlBeanFactory beanFactory = loadContext(); + DefaultListableBeanFactory beanFactory = loadContext(); if (beanFactory == null) { // Context was invalid return; @@ -91,15 +93,17 @@ public final class AdminParserTests { * Load application context. Fail if tests expects invalid spring-context, but spring-context is valid. * @return */ - private XmlBeanFactory loadContext() { - XmlBeanFactory beanFactory = null; + private DefaultListableBeanFactory loadContext() { + DefaultListableBeanFactory beanFactory = null; try { // Resource file name template: --context.xml ClassPathResource resource = new ClassPathResource(getClass().getSimpleName() + "-" + contextIndex + "-context.xml", getClass()); - beanFactory = new XmlBeanFactory(resource); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(resource); if (!validContext) { - fail("Context " + resource + " suppose to fail"); + fail("Context " + resource + " failed to load"); } } catch (BeanDefinitionParsingException e) { if (validContext) { @@ -108,6 +112,7 @@ public final class AdminParserTests { } logger.warn("Failure was expected", e); + beanFactory = null; } return beanFactory; } 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 index 8e776576..a639a5b2 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 the original author or authors. + * Copyright 2010-2013 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 @@ -24,7 +24,8 @@ import org.junit.Before; import org.junit.Test; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -38,11 +39,13 @@ import com.rabbitmq.client.Address; */ public final class ConnectionFactoryParserTests { - private XmlBeanFactory beanFactory; + private DefaultListableBeanFactory beanFactory; @Before public void setUpDefaultBeanFactory() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); } @Test diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ExchangeParserTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ExchangeParserTests.java index 59fb2140..b8ca0525 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ExchangeParserTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ExchangeParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -27,7 +27,8 @@ import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.core.FanoutExchange; import org.springframework.amqp.core.HeadersExchange; import org.springframework.amqp.core.TopicExchange; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; /** * @author Dave Syer @@ -38,11 +39,13 @@ import org.springframework.core.io.ClassPathResource; */ public final class ExchangeParserTests { - private XmlBeanFactory beanFactory; + private DefaultListableBeanFactory beanFactory; @Before public void setUp() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName()+"-context.xml", getClass())); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName()+"-context.xml", getClass())); } @Test diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ListenerContainerParserTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ListenerContainerParserTests.java index 91d9c5fa..4c60be06 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ListenerContainerParserTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/ListenerContainerParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 the original author or authors. + * Copyright 2010-2013 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. @@ -35,10 +35,9 @@ import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.expression.StandardBeanExpressionResolver; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; @@ -50,12 +49,14 @@ import org.springframework.test.util.ReflectionTestUtils; */ public class ListenerContainerParserTests { - private BeanFactory beanFactory; + private DefaultListableBeanFactory beanFactory; @Before public void setUp() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); - ((ConfigurableBeanFactory)beanFactory).setBeanExpressionResolver(new StandardBeanExpressionResolver()); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); + beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver()); } @Test diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests.java new file mode 100644 index 00000000..e783ecec --- /dev/null +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests.java @@ -0,0 +1,125 @@ +/* + * Copyright 2002-2013 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.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.SingleConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.test.BrokerRunning; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.env.StandardEnvironment; + +import com.rabbitmq.client.Channel; + +/** + * @author Gary Russell + * @since 1.2 + * + */ +public class MismatchedQueueDeclarationTests { + + @Rule + public BrokerRunning brokerIsRunning = BrokerRunning.isRunning(); + + private SingleConnectionFactory connectionFactory; + + private RabbitAdmin admin; + + @Before + public void setup() { + connectionFactory = new SingleConnectionFactory(); + this.admin = new RabbitAdmin(this.connectionFactory); + deleteQueues(); + } + + @After + public void deleteQueues() { + this.admin.deleteQueue("mismatch.foo"); + this.admin.deleteQueue("mismatch.bar"); + } + + @Test + public void testAdminFailsWithMismatchedQueue() throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); + context.setConfigLocation("org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests-context.xml"); + StandardEnvironment env = new StandardEnvironment(); + env.addActiveProfile("basicAdmin"); + env.addActiveProfile("basic"); + context.setEnvironment(env); + context.refresh(); + context.getBean(CachingConnectionFactory.class).createConnection(); + context.destroy(); + Channel channel = this.connectionFactory.createConnection().createChannel(false); + channel.queueDeclarePassive("mismatch.bar"); + this.admin.deleteQueue("mismatch.bar"); + assertNotNull(this.admin.getQueueProperties("mismatch.foo")); + assertNull(this.admin.getQueueProperties("mismatch.bar")); + + env = new StandardEnvironment(); + env.addActiveProfile("basicAdmin"); + env.addActiveProfile("ttl"); + context.setEnvironment(env); + context.refresh(); + channel = this.connectionFactory.createConnection().createChannel(false); + try { + context.getBean(CachingConnectionFactory.class).createConnection(); + fail("Expected exception - basic admin fails with mismatched declarations"); + } + catch (Exception e) { + assertTrue(e.getCause().getCause().getMessage().contains("inequivalent arg 'x-message-ttl'")); + } + assertNotNull(this.admin.getQueueProperties("mismatch.foo")); + assertNull(this.admin.getQueueProperties("mismatch.bar")); + } + + @Test + public void testAdminSkipsMismatchedQueue() throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); + context.setConfigLocation("org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests-context.xml"); + StandardEnvironment env = new StandardEnvironment(); + env.addActiveProfile("advancedAdmin"); + env.addActiveProfile("basic"); + context.setEnvironment(env); + context.refresh(); + context.getBean(CachingConnectionFactory.class).createConnection(); + context.destroy(); + Channel channel = this.connectionFactory.createConnection().createChannel(false); + channel.queueDeclarePassive("mismatch.bar"); + this.admin.deleteQueue("mismatch.bar"); + assertNotNull(this.admin.getQueueProperties("mismatch.foo")); + assertNull(this.admin.getQueueProperties("mismatch.bar")); + + env = new StandardEnvironment(); + env.addActiveProfile("advancedAdmin"); + env.addActiveProfile("ttl"); + context.setEnvironment(env); + context.refresh(); + channel = this.connectionFactory.createConnection().createChannel(false); + context.getBean(CachingConnectionFactory.class).createConnection(); + assertNotNull(this.admin.getQueueProperties("mismatch.foo")); + assertNotNull(this.admin.getQueueProperties("mismatch.bar")); + } + +} diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserIntegrationTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserIntegrationTests.java index f6ac13d2..d054a265 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserIntegrationTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2013 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 @@ -25,19 +25,28 @@ import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.test.BrokerRunning; import org.springframework.amqp.rabbit.test.BrokerTestUtils; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; +/** + * @author Dave Syer + * @author Gary Russell + * @since 1.0 + * + */ public final class QueueParserIntegrationTests { @Rule public BrokerRunning brokerIsRunning = BrokerRunning.isRunning(); - private XmlBeanFactory beanFactory; + private DefaultListableBeanFactory beanFactory; @Before public void setUpDefaultBeanFactory() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); } @Test diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserTests.java index 62f52414..2098b252 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/QueueParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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 @@ -25,16 +25,26 @@ import org.springframework.amqp.core.AnonymousQueue; import org.springframework.amqp.core.Queue; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; +/** + * @author Dave Syer + * @author Gary Russell + * @since 1.0 + * + */ public class QueueParserTests { protected BeanFactory beanFactory; @Before public void setUpDefaultBeanFactory() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); + this.beanFactory = beanFactory; } @Test @@ -111,7 +121,9 @@ public class QueueParserTests { @Test(expected=BeanDefinitionStoreException.class) public void testIllegalAnonymousQueue() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "IllegalAnonymous-context.xml", getClass())); Queue queue = beanFactory.getBean("anonymous", Queue.class); assertNotNull(queue); diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandlerTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandlerTests.java index 16d035db..5d8f1fb0 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandlerTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/config/RabbitNamespaceHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2013 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. @@ -33,16 +33,26 @@ import org.springframework.amqp.core.HeadersExchange; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.TopicExchange; import org.springframework.amqp.rabbit.core.RabbitAdmin; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; +/** + * @author Tomas Lukosius + * @author Dave Syer + * @author Gary Russell + * @since 1.0 + * + */ public final class RabbitNamespaceHandlerTests { - private XmlBeanFactory beanFactory; + private DefaultListableBeanFactory beanFactory; @Before public void setUp() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName()+"-context.xml", getClass())); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName()+"-context.xml", getClass())); } @Test 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 index aee43e43..94ad8084 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2010-2013 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 @@ -27,7 +27,8 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; import org.springframework.amqp.support.converter.SerializerMessageConverter; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; /** @@ -38,11 +39,13 @@ import org.springframework.core.io.ClassPathResource; */ public final class TemplateParserTests { - private XmlBeanFactory beanFactory; + private DefaultListableBeanFactory beanFactory; @Before public void setUpDefaultBeanFactory() throws Exception { - beanFactory = new XmlBeanFactory(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); + beanFactory = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); + reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "-context.xml", getClass())); } @Test diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/core/RabbitAdminTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/core/RabbitAdminTests.java index e9cb6df0..663c9dcf 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/core/RabbitAdminTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/core/RabbitAdminTests.java @@ -1,7 +1,11 @@ package org.springframework.amqp.rabbit.core; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import java.util.Properties; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -10,6 +14,9 @@ import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.connection.SingleConnectionFactory; import org.springframework.context.support.GenericApplicationContext; +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.DefaultConsumer; + public class RabbitAdminTests { @Rule @@ -52,4 +59,33 @@ public class RabbitAdminTests { rabbitAdmin.declareQueue(); } + @Test + public void testProperties() throws Exception { + SingleConnectionFactory connectionFactory = new SingleConnectionFactory(); + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); + String queueName = "test.properties." + System.currentTimeMillis(); + try { + rabbitAdmin.declareQueue(new Queue(queueName)); + new RabbitTemplate(connectionFactory).convertAndSend(queueName, "foo"); + Properties props = rabbitAdmin.getQueueProperties(queueName); + assertNotNull(props); + assertNotNull(props.get(RabbitAdmin.QUEUE_MESSAGE_COUNT)); + assertEquals(1, props.get(RabbitAdmin.QUEUE_MESSAGE_COUNT)); + Channel channel = connectionFactory.createConnection().createChannel(false); + DefaultConsumer consumer = new DefaultConsumer(channel); + channel.basicConsume(queueName, true, consumer); + props = rabbitAdmin.getQueueProperties(queueName); + assertNotNull(props); + assertNotNull(props.get(RabbitAdmin.QUEUE_MESSAGE_COUNT)); + assertEquals(0, props.get(RabbitAdmin.QUEUE_MESSAGE_COUNT)); + assertNotNull(props.get(RabbitAdmin.QUEUE_CONSUMER_COUNT)); + assertEquals(1, props.get(RabbitAdmin.QUEUE_CONSUMER_COUNT)); + channel.close(); + } + finally { + rabbitAdmin.deleteQueue(queueName); + connectionFactory.destroy(); + } + } + } diff --git a/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests-context.xml b/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests-context.xml new file mode 100644 index 00000000..98e80bef --- /dev/null +++ b/spring-rabbit/src/test/resources/org/springframework/amqp/rabbit/config/MismatchedQueueDeclarationTests-context.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +