AMQP-812: Deprecate RabbitManagementTemplate (#779)

* AMQP-812: Deprecate RabbitManagementTemplate

JIRA: https://jira.spring.io/browse/AMQP-812

* Fix `RabbitRestApiTests`
This commit is contained in:
Artem Bilan
2018-07-23 15:57:33 -04:00
committed by Gary Russell
parent 8fa1eee8f5
commit ae8550d569
9 changed files with 80 additions and 104 deletions

View File

@@ -254,7 +254,7 @@ project('spring-rabbit') {
compile project(":spring-amqp")
compile "com.rabbitmq:amqp-client:$rabbitmqVersion"
compile "com.rabbitmq:http-client:$rabbitmqHttpClientVersion"
compile ("com.rabbitmq:http-client:$rabbitmqHttpClientVersion", optional)
compile ("org.springframework:spring-aop:$springVersion", optional)
compile "org.springframework:spring-context:$springVersion"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2016 the original author or authors.
* Copyright 2015-2018 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.
@@ -24,7 +24,9 @@ import java.util.List;
* @author Gary Russell
* @since 1.5
*
* @deprecated since 2.1 in favor of direct usage of target REST API client.
*/
@Deprecated
public interface AmqpManagementOperations {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2017 the original author or authors.
* Copyright 2015-2018 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.
@@ -21,7 +21,6 @@ import java.util.stream.Collectors;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AbstractExchange;
import org.springframework.amqp.core.AmqpManagementOperations;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Binding.DestinationType;
import org.springframework.amqp.core.DirectExchange;
@@ -48,8 +47,10 @@ import com.rabbitmq.http.client.domain.QueueInfo;
*
* @since 1.5
*
* @deprecated since 2.1 in favor of direct {@link Client} usage.
*/
public class RabbitManagementTemplate implements AmqpManagementOperations {
@Deprecated
public class RabbitManagementTemplate implements org.springframework.amqp.core.AmqpManagementOperations {
private static final String DEFAULT_VHOST = "/";

View File

@@ -77,7 +77,6 @@ import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionNameStrategy;
import org.springframework.amqp.rabbit.connection.SimplePropertyValueConnectionNameStrategy;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitManagementTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.junit.BrokerRunning;
import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler;
@@ -140,6 +139,8 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ErrorHandler;
import com.rabbitmq.client.Channel;
import com.rabbitmq.http.client.Client;
import com.rabbitmq.http.client.domain.QueueInfo;
/**
*
@@ -718,8 +719,8 @@ public class EnableRabbitIntegrationTests {
this.rabbitTemplate.convertAndSend("amqp656", "foo");
assertEquals("foo", this.rabbitTemplate.receiveAndConvert("amqp656dlq", 10000));
try {
RabbitManagementTemplate rmt = new RabbitManagementTemplate();
org.springframework.amqp.core.Queue amqp656 = rmt.getQueue("amqp656");
Client rabbitRestClient = new Client("http://localhost:15672/api/", "guest", "guest");
QueueInfo amqp656 = rabbitRestClient.getQueue("/", "amqp656");
if (amqp656 != null) {
assertEquals("", amqp656.getArguments().get("test-empty"));
assertEquals("undefined", amqp656.getArguments().get("test-null"));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 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.
@@ -17,7 +17,6 @@
package org.springframework.amqp.rabbit.core;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -41,6 +40,7 @@ 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.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
@@ -56,6 +56,8 @@ import com.rabbitmq.client.AMQP.Queue.DeclareOk;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.http.client.Client;
import com.rabbitmq.http.client.domain.ExchangeInfo;
/**
* @author Dave Syer
@@ -260,8 +262,8 @@ public class RabbitAdminIntegrationTests {
exchange.setInternal(true);
rabbitAdmin.declareExchange(exchange);
Exchange exchange2 = getExchange(exchangeName);
assertThat(exchange2, instanceOf(DirectExchange.class));
ExchangeInfo exchange2 = getExchange(exchangeName);
assertEquals(ExchangeTypes.DIRECT, exchange2.getType());
assertTrue(exchange2.isInternal());
boolean result = rabbitAdmin.deleteExchange(exchangeName);
@@ -416,22 +418,22 @@ public class RabbitAdminIntegrationTests {
assertEquals(Integer.valueOf(1000), received.getMessageProperties().getReceivedDelay());
assertThat(System.currentTimeMillis() - t1, greaterThan(950L));
Exchange exchange2 = getExchange(exchangeName);
ExchangeInfo exchange2 = getExchange(exchangeName);
assertNotNull(exchange2);
assertThat(exchange2, instanceOf(DirectExchange.class));
assertTrue(exchange2.isDelayed());
assertEquals(ExchangeTypes.DIRECT, exchange2.getArguments().get("x-delayed-type"));
assertEquals("x-delayed-message", exchange2.getType());
this.rabbitAdmin.deleteQueue(queue.getName());
this.rabbitAdmin.deleteExchange(exchangeName);
}
private Exchange getExchange(String exchangeName) throws InterruptedException {
RabbitManagementTemplate rmt = new RabbitManagementTemplate();
private ExchangeInfo getExchange(String exchangeName) throws Exception {
Client rabbitRestClient = new Client("http://localhost:15672/api/", "guest", "guest");
int n = 0;
Exchange exchange = rmt.getExchange(exchangeName);
ExchangeInfo exchange = rabbitRestClient.getExchange("/", exchangeName);
while (n++ < 100 && exchange == null) {
Thread.sleep(100);
exchange = rmt.getExchange(exchangeName);
exchange = rabbitRestClient.getExchange("/", exchangeName);
}
return exchange;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2017 the original author or authors.
* Copyright 2015-2018 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.
@@ -25,6 +25,8 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -45,6 +47,9 @@ import org.springframework.amqp.rabbit.junit.BrokerRunning;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.http.client.Client;
import com.rabbitmq.http.client.domain.BindingInfo;
import com.rabbitmq.http.client.domain.ExchangeInfo;
import com.rabbitmq.http.client.domain.QueueInfo;
/**
@@ -54,15 +59,20 @@ import com.rabbitmq.http.client.domain.QueueInfo;
* @since 1.5
*
*/
public class RabbitManagementTemplateTests {
public class RabbitRestApiTests {
private final CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
private final RabbitManagementTemplate template = new RabbitManagementTemplate();
private final Client rabbitRestClient;
@ClassRule
public static BrokerRunning brokerAndManagementRunning = BrokerRunning.isBrokerAndManagementRunning();
public RabbitRestApiTests() throws MalformedURLException, URISyntaxException {
this.rabbitRestClient = new Client("http://localhost:15672/api/", "guest", "guest");
}
@After
public void tearDown() {
connectionFactory.destroy();
@@ -70,37 +80,37 @@ public class RabbitManagementTemplateTests {
@Test
public void testExchanges() {
List<Exchange> list = this.template.getExchanges();
List<ExchangeInfo> list = this.rabbitRestClient.getExchanges();
assertTrue(list.size() > 0);
}
@Test
public void testExchangesVhost() {
List<Exchange> list = this.template.getExchanges("/");
List<ExchangeInfo> list = this.rabbitRestClient.getExchanges("/");
assertTrue(list.size() > 0);
}
@Test
public void testBindings() {
List<Binding> list = this.template.getBindings();
List<BindingInfo> list = this.rabbitRestClient.getBindings();
assertTrue(list.size() > 0);
}
@Test
public void testBindingsVhost() {
List<Binding> list = this.template.getBindings("/");
List<BindingInfo> list = this.rabbitRestClient.getBindings("/");
assertTrue(list.size() > 0);
}
@Test
public void testQueues() {
List<Queue> list = this.template.getQueues();
List<QueueInfo> list = this.rabbitRestClient.getQueues();
assertTrue(list.size() > 0);
}
@Test
public void testQueuesVhost() {
List<Queue> list = this.template.getQueues("/");
List<QueueInfo> list = this.rabbitRestClient.getQueues("/");
assertTrue(list.size() > 0);
}
@@ -125,12 +135,12 @@ public class RabbitManagementTemplateTests {
.with("bar");
admin.declareBinding(binding2);
List<Binding> bindings = this.template.getBindingsForExchange("/", exchange1.getName());
List<BindingInfo> bindings = this.rabbitRestClient.getBindingsBySource("/", exchange1.getName());
assertEquals(2, bindings.size());
assertEquals(exchange1.getName(), bindings.get(0).getExchange());
assertEquals(exchange1.getName(), bindings.get(0).getSource());
assertThat("foo", anyOf(equalTo(bindings.get(0).getRoutingKey()), equalTo(bindings.get(1).getRoutingKey())));
Binding qout = null;
Binding eout = null;
BindingInfo qout = null;
BindingInfo eout = null;
if (bindings.get(0).getRoutingKey().equals("foo")) {
qout = bindings.get(0);
eout = bindings.get(1);
@@ -139,12 +149,12 @@ public class RabbitManagementTemplateTests {
eout = bindings.get(0);
qout = bindings.get(1);
}
assertEquals(Binding.DestinationType.QUEUE, qout.getDestinationType());
assertEquals("queue", qout.getDestinationType());
assertEquals(queue.getName(), qout.getDestination());
assertNotNull(qout.getArguments());
assertEquals("", qout.getArguments().get("alternate-exchange"));
assertEquals(Binding.DestinationType.EXCHANGE, eout.getDestinationType());
assertEquals("exchange", eout.getDestinationType());
assertEquals(exchange2.getName(), eout.getDestination());
admin.deleteExchange(exchange1.getName());
@@ -157,7 +167,7 @@ public class RabbitManagementTemplateTests {
Map<String, Object> args = Collections.<String, Object>singletonMap("alternate-exchange", "");
Exchange exchange = new DirectExchange(UUID.randomUUID().toString(), true, true, args);
admin.declareExchange(exchange);
Exchange exchangeOut = this.template.getExchange("/", exchange.getName());
ExchangeInfo exchangeOut = this.rabbitRestClient.getExchange("/", exchange.getName());
assertTrue(exchangeOut.isDurable());
assertTrue(exchangeOut.isAutoDelete());
assertEquals(exchange.getName(), exchangeOut.getName());
@@ -180,13 +190,13 @@ public class RabbitManagementTemplateTests {
admin.declareQueue(queue2);
Channel channel = this.connectionFactory.createConnection().createChannel(false);
String consumer = channel.basicConsume(queue1.getName(), false, "", false, true, null, new DefaultConsumer(channel));
QueueInfo qi = this.template.getClient().getQueue("/", queue1.getName());
QueueInfo qi = this.rabbitRestClient.getQueue("/", queue1.getName());
int n = 0;
while (n++ < 100 && (qi.getExclusiveConsumerTag() == null || qi.getExclusiveConsumerTag().equals(""))) {
Thread.sleep(100);
qi = this.template.getClient().getQueue("/", queue1.getName());
qi = this.rabbitRestClient.getQueue("/", queue1.getName());
}
Queue queueOut = this.template.getQueue("/", queue1.getName());
QueueInfo queueOut = this.rabbitRestClient.getQueue("/", queue1.getName());
assertFalse(queueOut.isDurable());
assertFalse(queueOut.isExclusive());
assertTrue(queueOut.isAutoDelete());
@@ -196,7 +206,7 @@ public class RabbitManagementTemplateTests {
channel.basicCancel(consumer);
channel.close();
queueOut = this.template.getQueue("/", queue2.getName());
queueOut = this.rabbitRestClient.getQueue("/", queue2.getName());
assertTrue(queueOut.isDurable());
assertFalse(queueOut.isExclusive());
assertFalse(queueOut.isAutoDelete());
@@ -211,12 +221,17 @@ public class RabbitManagementTemplateTests {
public void testDeleteExchange() {
String exchangeName = "testExchange";
Exchange testExchange = new DirectExchange(exchangeName);
this.template.addExchange(testExchange);
Exchange exchangeToAssert = this.template.getExchange(exchangeName);
ExchangeInfo info = new ExchangeInfo();
info.setArguments(testExchange.getArguments());
info.setAutoDelete(testExchange.isAutoDelete());
info.setDurable(testExchange.isDurable());
info.setType(testExchange.getType());
this.rabbitRestClient.declareExchange("/", testExchange.getName(), info);
ExchangeInfo exchangeToAssert = this.rabbitRestClient.getExchange("/", exchangeName);
assertEquals(testExchange.getName(), exchangeToAssert.getName());
assertEquals(testExchange.getType(), exchangeToAssert.getType());
this.template.deleteExchange(testExchange);
assertNull(this.template.getExchange(exchangeName));
this.rabbitRestClient.deleteExchange("/", testExchange.getName());
assertNull(this.rabbitRestClient.getExchange("/", exchangeName));
}
}

View File

@@ -4160,66 +4160,18 @@ To check if a message was delayed, use the `getReceivedDelay()` method on the `M
It is a separate property to avoid unintended propagation to an output message generated from an input message.
[[management-template]]
[[management-rest-api]]
==== RabbitMQ REST API
When the management plugin is enabled, the RabbitMQ server exposes a REST API to monitor and configure the broker.
A https://github.com/rabbitmq/hop[Java Binding for the API] is now provided.
In general, you can use that API directly, but a convenience wrapper is provided to use the familiar Spring AMQP `Queue`, `Exchange`, and `Binding` domain objects with the API.
Much more information is available for these objects when using the `com.rabbitmq.http.client.Client` API directly
(`QueueInfo`, `ExchangeInfo`, and `BindingInfo` respectively).
The following operations are available on the `RabbitManagementTemplate`:
The `com.rabbitmq.http.client.Client` is a standard, immediate and, therefore, blocking API.
It is based on the https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#spring-web[Spring Web] module and its `RestTemplate` implementation.
On the other hand, the `com.rabbitmq.http.client.ReactorNettyClient` is a reactive, non-blocking implementation based on the http://projectreactor.io/docs/netty/release/reference/docs/index.html[Reactor Netty] project.
[source, java]
----
public interface AmqpManagementOperations {
The hop dependency (`com.rabbitmq:http-client`) is now also `optional`.
void addExchange(Exchange exchange);
void addExchange(String vhost, Exchange exchange);
void purgeQueue(Queue queue);
void purgeQueue(String vhost, Queue queue);
void deleteQueue(Queue queue);
void deleteQueue(String vhost, Queue queue);
Queue getQueue(String name);
Queue getQueue(String vhost, String name);
List<Queue> getQueues();
List<Queue> getQueues(String vhost);
void addQueue(Queue queue);
void addQueue(String vhost, Queue queue);
void deleteExchange(Exchange exchange);
void deleteExchange(String vhost, Exchange exchange);
Exchange getExchange(String name);
Exchange getExchange(String vhost, String name);
List<Exchange> getExchanges();
List<Exchange> getExchanges(String vhost);
List<Binding> getBindings();
List<Binding> getBindings(String vhost);
List<Binding> getBindingsForExchange(String vhost, String exchange);
}
----
Refer to the javadocs for more information.
Refer to their javadocs for more information.
[[exception-handling]]
==== Exception Handling

View File

@@ -570,9 +570,8 @@ See <<reply-listener>> for more information.
===== The RabbitManagementTemplate
The `RabbitManagementTemplate` has been introduced to monitor and configure the RabbitMQ Broker using the REST API
provided by its https://www.rabbitmq.com/management.html[Management Plugin].
See <<management-template>> for more information.
The `RabbitManagementTemplate` has been introduced to monitor and configure the RabbitMQ Broker using the REST API provided by its https://www.rabbitmq.com/management.html[Management Plugin].
See <<management-rest-api>> for more information.
===== Listener Container Bean Names (XML)

View File

@@ -19,13 +19,11 @@ RabbitMQ `ConnectionFactory` instances created by the `RabbitConnectionFactoryBe
Certain classes have moved to different packages; most are internal classes and won't affect user applications.
Two exceptions are `ChannelAwareMessageListener` and `RabbitListenerErrorHandler`; these interfaces are now in `org.springframework.amqp.rabbit.listener.api`.
===== Publisher Confirms Changes
Channels enabled for publisher confirms are not returned to the cache while there are outstanding confirms.
See <<template-confirms>> for more information.
===== Listener Container Factory Improvements
The listener container factories can now be used to create any listener container, not just those for use with `@RabbitListener` s or the `@RabbitListenerEndpointRegistry`.
@@ -35,7 +33,7 @@ See <<using-container-factories>> for more information.
===== Broker Event Listener
A `BrokerEventListener` is introduced to publish selected broker events as `ApplictionEvent` s.
A `BrokerEventListener` is introduced to publish selected broker events as `ApplicationEvent` s.
See <<broker-events>> for more information.
===== RabbitAdmin Changes
@@ -50,5 +48,11 @@ The `RabbitTemplate` now can be configured with the `noLocalReplyConsumer` optio
See <<request-reply>> for more information.
===== Message Converts
A new `Jackson2XmlMessageConverter` is introduced to support converting messages from/to XML format.
See <<Jackson2XmlMessageConverter>> for more information.
See <<Jackson2XmlMessageConverter>> for more information.
===== Management REST API
The `RabbitManagementTemplate` is now deprecated in favor of the direct `com.rabbitmq.http.client.Client` (or `com.rabbitmq.http.client.ReactorNettyClient`) usage.
See <<management-rest-api>> for more information.