org.springframework.amqp.rabbit.core.RabbitAdminIntegrationTests.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.amqp.rabbit.core.RabbitAdminIntegrationTests.java

Source

/*
 * Copyright 2002-2014 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.core;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import org.springframework.amqp.AmqpIOException;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Binding.DestinationType;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.test.BrokerRunning;
import org.springframework.amqp.rabbit.test.BrokerTestUtils;
import org.springframework.context.support.GenericApplicationContext;

import com.rabbitmq.client.AMQP.Queue.DeclareOk;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author Dave Syer
 * @author Ed Scriven
 * @author Gary Russell
 * @author Gunnar Hillert
 * @author Artem Bilan
 */
public class RabbitAdminIntegrationTests {

    private final CachingConnectionFactory connectionFactory = new CachingConnectionFactory();

    @Rule
    public BrokerRunning brokerIsRunning = BrokerRunning.isRunning();

    private GenericApplicationContext context;

    private RabbitAdmin rabbitAdmin;

    public RabbitAdminIntegrationTests() {
        connectionFactory.setPort(BrokerTestUtils.getPort());
    }

    @Before
    public void init() {
        connectionFactory.setHost("localhost");
        context = new GenericApplicationContext();
        context.refresh();
        rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.deleteQueue("test.queue");
        // Force connection factory to forget that it has been used to delete the queue
        connectionFactory.destroy();
        rabbitAdmin.setApplicationContext(context);
        rabbitAdmin.setAutoStartup(true);
    }

    @After
    public void close() {
        if (context != null) {
            context.close();
        }
        if (connectionFactory != null) {
            connectionFactory.destroy();
        }
    }

    @Test
    public void testStartupWithLazyDeclaration() throws Exception {
        Queue queue = new Queue("test.queue");
        context.getBeanFactory().registerSingleton("foo", queue);
        rabbitAdmin.afterPropertiesSet();
        // A new connection is initialized so the queue is declared
        assertTrue(rabbitAdmin.deleteQueue(queue.getName()));
    }

    @Test(expected = AmqpIOException.class)
    public void testDoubleDeclarationOfExclusiveQueue() throws Exception {
        // Expect exception because the queue is locked when it is declared a second time.
        CachingConnectionFactory connectionFactory1 = new CachingConnectionFactory();
        connectionFactory1.setHost("localhost");
        connectionFactory1.setPort(BrokerTestUtils.getPort());
        CachingConnectionFactory connectionFactory2 = new CachingConnectionFactory();
        connectionFactory2.setHost("localhost");
        connectionFactory2.setPort(BrokerTestUtils.getPort());
        Queue queue = new Queue("test.queue", false, true, true);
        rabbitAdmin.deleteQueue(queue.getName());
        new RabbitAdmin(connectionFactory1).declareQueue(queue);
        try {
            new RabbitAdmin(connectionFactory2).declareQueue(queue);
        } finally {
            // Need to release the connection so the exclusive queue is deleted
            connectionFactory1.destroy();
            connectionFactory2.destroy();
        }
    }

    @Test
    public void testDoubleDeclarationOfAutodeleteQueue() throws Exception {
        // No error expected here: the queue is autodeleted when the last consumer is cancelled, but this one never has
        // any consumers.
        CachingConnectionFactory connectionFactory1 = new CachingConnectionFactory();
        connectionFactory1.setHost("localhost");
        connectionFactory1.setPort(BrokerTestUtils.getPort());
        CachingConnectionFactory connectionFactory2 = new CachingConnectionFactory();
        connectionFactory2.setHost("localhost");
        connectionFactory2.setPort(BrokerTestUtils.getPort());
        Queue queue = new Queue("test.queue", false, false, true);
        new RabbitAdmin(connectionFactory1).declareQueue(queue);
        new RabbitAdmin(connectionFactory2).declareQueue(queue);
        connectionFactory1.destroy();
        connectionFactory2.destroy();
    }

    @Test
    public void testQueueWithAutoDelete() throws Exception {

        final Queue queue = new Queue("test.queue", false, true, true);
        context.getBeanFactory().registerSingleton("foo", queue);
        rabbitAdmin.afterPropertiesSet();

        // Queue created on spring startup
        rabbitAdmin.initialize();
        assertTrue(queueExists(queue));

        // Stop and broker deletes queue (only verifiable in native API)
        connectionFactory.destroy();
        assertFalse(queueExists(queue));

        // Start and queue re-created by the connection listener
        connectionFactory.createConnection();
        assertTrue(queueExists(queue));

        // Queue manually deleted
        assertTrue(rabbitAdmin.deleteQueue(queue.getName()));
        assertFalse(queueExists(queue));

    }

    @Test
    public void testQueueWithoutAutoDelete() throws Exception {

        final Queue queue = new Queue("test.queue", false, false, false);
        context.getBeanFactory().registerSingleton("foo", queue);
        rabbitAdmin.afterPropertiesSet();

        // Queue created on Spring startup
        rabbitAdmin.initialize();
        assertTrue(queueExists(queue));

        // Stop and broker retains queue (only verifiable in native API)
        connectionFactory.destroy();
        assertTrue(queueExists(queue));

        // Start and queue still exists
        connectionFactory.createConnection();
        assertTrue(queueExists(queue));

        // Queue manually deleted
        assertTrue(rabbitAdmin.deleteQueue(queue.getName()));
        assertFalse(queueExists(queue));

        connectionFactory.destroy();
    }

    @Test
    public void testQueueWithoutName() throws Exception {

        final Queue queue = new Queue("", true, false, true);
        String generatedName = rabbitAdmin.declareQueue(queue);

        assertEquals("", queue.getName());
        Queue queueWithGeneratedName = new Queue(generatedName, true, false, true);
        assertTrue(queueExists(queueWithGeneratedName));

        // Stop and broker retains queue (only verifiable in native API)
        connectionFactory.destroy();
        assertTrue(queueExists(queueWithGeneratedName));

        // Start and queue still exists
        connectionFactory.createConnection();
        assertTrue(queueExists(queueWithGeneratedName));

        // Queue manually deleted
        assertTrue(rabbitAdmin.deleteQueue(generatedName));
        assertFalse(queueExists(queueWithGeneratedName));

        connectionFactory.destroy();
    }

    @Test
    public void testDeclareExchangeWithDefaultExchange() throws Exception {
        Exchange exchange = new DirectExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);

        rabbitAdmin.declareExchange(exchange);

        // Pass by virtue of RabbitMQ not firing a 403 reply code
    }

    @Test
    public void testSpringWithDefaultExchange() throws Exception {
        Exchange exchange = new DirectExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);
        context.getBeanFactory().registerSingleton("foo", exchange);
        rabbitAdmin.afterPropertiesSet();

        rabbitAdmin.initialize();

        // Pass by virtue of RabbitMQ not firing a 403 reply code
    }

    @Test
    public void testDeleteExchangeWithDefaultExchange() throws Exception {
        boolean result = rabbitAdmin.deleteExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);

        assertTrue(result);
    }

    @Test
    public void testDeclareBindingWithDefaultExchangeImplicitBinding() throws Exception {
        Exchange exchange = new DirectExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);
        String queueName = "test.queue";
        final Queue queue = new Queue(queueName, false, false, false);
        rabbitAdmin.declareQueue(queue);
        Binding binding = new Binding(queueName, DestinationType.QUEUE, exchange.getName(), queueName, null);

        rabbitAdmin.declareBinding(binding);

        // Pass by virtue of RabbitMQ not firing a 403 reply code for both exchange and binding declaration
        assertTrue(queueExists(queue));
    }

    @Test
    public void testSpringWithDefaultExchangeImplicitBinding() throws Exception {
        Exchange exchange = new DirectExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);
        context.getBeanFactory().registerSingleton("foo", exchange);
        String queueName = "test.queue";
        final Queue queue = new Queue(queueName, false, false, false);
        context.getBeanFactory().registerSingleton("bar", queue);
        Binding binding = new Binding(queueName, DestinationType.QUEUE, exchange.getName(), queueName, null);
        context.getBeanFactory().registerSingleton("baz", binding);
        rabbitAdmin.afterPropertiesSet();

        rabbitAdmin.initialize();

        // Pass by virtue of RabbitMQ not firing a 403 reply code for both exchange and binding declaration
        assertTrue(queueExists(queue));
    }

    @Test
    public void testRemoveBindingWithDefaultExchangeImplicitBinding() throws Exception {
        String queueName = "test.queue";
        final Queue queue = new Queue(queueName, false, false, false);
        rabbitAdmin.declareQueue(queue);
        Binding binding = new Binding(queueName, DestinationType.QUEUE, RabbitAdmin.DEFAULT_EXCHANGE_NAME,
                queueName, null);

        rabbitAdmin.removeBinding(binding);

        // Pass by virtue of RabbitMQ not firing a 403 reply code
    }

    @Test
    public void testDeclareBindingWithDefaultExchangeNonImplicitBinding() throws Exception {
        Exchange exchange = new DirectExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);
        String queueName = "test.queue";
        final Queue queue = new Queue(queueName, false, false, false);
        rabbitAdmin.declareQueue(queue);
        Binding binding = new Binding(queueName, DestinationType.QUEUE, exchange.getName(), "test.routingKey",
                null);

        try {
            rabbitAdmin.declareBinding(binding);
        } catch (AmqpIOException ex) {
            Throwable cause = ex;
            Throwable rootCause = null;
            while (cause != null) {
                rootCause = cause;
                cause = cause.getCause();
            }
            assertTrue(rootCause.getMessage().contains("reply-code=403"));
            assertTrue(rootCause.getMessage().contains("operation not permitted on the default exchange"));
        }
    }

    @Test
    public void testSpringWithDefaultExchangeNonImplicitBinding() throws Exception {
        Exchange exchange = new DirectExchange(RabbitAdmin.DEFAULT_EXCHANGE_NAME);
        context.getBeanFactory().registerSingleton("foo", exchange);
        String queueName = "test.queue";
        final Queue queue = new Queue(queueName, false, false, false);
        context.getBeanFactory().registerSingleton("bar", queue);
        Binding binding = new Binding(queueName, DestinationType.QUEUE, exchange.getName(), "test.routingKey",
                null);
        context.getBeanFactory().registerSingleton("baz", binding);
        rabbitAdmin.afterPropertiesSet();

        try {
            rabbitAdmin.declareBinding(binding);
        } catch (AmqpIOException ex) {
            Throwable cause = ex;
            Throwable rootCause = null;
            while (cause != null) {
                rootCause = cause;
                cause = cause.getCause();
            }
            assertTrue(rootCause.getMessage().contains("reply-code=403"));
            assertTrue(rootCause.getMessage().contains("operation not permitted on the default exchange"));
        }
    }

    /**
     * Verify that a queue exists using the native Rabbit API to bypass all the connection and
     * channel caching and callbacks in Spring AMQP.
     *
     * @param queue The queue to verify
     * @return True if the queue exists
     */
    private boolean queueExists(final Queue queue) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(BrokerTestUtils.getPort());
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        try {
            DeclareOk result = channel.queueDeclarePassive(queue.getName());
            return result != null;
        } catch (IOException e) {
            return e.getCause().getMessage().contains("RESOURCE_LOCKED");
        } finally {
            connection.close();
        }
    }
}