AMQP-426 SMLC: Support Routing Connection Factory

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

Use the list of queue names as the lookup key.

Polishing `testAbstractRoutingConnectionFactoryWithListenerContainer()` to reflect the dynamic usage
This commit is contained in:
Gary Russell
2014-10-22 16:06:22 -04:00
committed by Artem Bilan
parent 6782c5accb
commit 6b82463f58
4 changed files with 72 additions and 0 deletions

View File

@@ -27,7 +27,9 @@ import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.AbstractRoutingConnectionFactory;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils;
import org.springframework.amqp.rabbit.connection.RabbitAccessor;
import org.springframework.amqp.rabbit.connection.RabbitResourceHolder;
@@ -352,6 +354,19 @@ public abstract class AbstractMessageListenerContainer extends RabbitAccessor
this.applicationContext = applicationContext;
}
@Override
public ConnectionFactory getConnectionFactory() {
ConnectionFactory connectionFactory = super.getConnectionFactory();
if (connectionFactory instanceof AbstractRoutingConnectionFactory) {
ConnectionFactory targetConnectionFactory = ((AbstractRoutingConnectionFactory) connectionFactory)
.getTargetConnectionFactory(this.queueNames.toString().replaceAll(" ", ""));
if (targetConnectionFactory != null) {
return targetConnectionFactory;
}
}
return connectionFactory;
}
/**
* Delegates to {@link #validateConfiguration()} and {@link #initialize()}.
*/

View File

@@ -16,6 +16,8 @@ package org.springframework.amqp.rabbit.connection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import java.util.HashMap;
import java.util.Map;
@@ -28,6 +30,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
/**
* @author Artem Bilan
* @author Josh Chappelle
@@ -144,4 +148,44 @@ public class RoutingConnectionFactoryTests {
Mockito.verify(targetConnectionFactory,
Mockito.times(2)).addConnectionListener(Mockito.any(ConnectionListener.class));
}
@Test
public void testAbstractRoutingConnectionFactoryWithListenerContainer() {
ConnectionFactory connectionFactory1 = mock(ConnectionFactory.class);
ConnectionFactory connectionFactory2 = mock(ConnectionFactory.class);
Map<Object, ConnectionFactory> factories = new HashMap<Object, ConnectionFactory>(2);
factories.put("[baz]", connectionFactory1);
factories.put("[foo,bar]", connectionFactory2);
ConnectionFactory defaultConnectionFactory = mock(ConnectionFactory.class);
SimpleRoutingConnectionFactory connectionFactory = new SimpleRoutingConnectionFactory();
connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory);
connectionFactory.setTargetConnectionFactories(factories);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("foo, bar");
container.afterPropertiesSet();
container.start();
Mockito.verify(connectionFactory1, never()).createConnection();
Mockito.verify(connectionFactory2).createConnection();
Mockito.verify(defaultConnectionFactory, never()).createConnection();
Mockito.reset(connectionFactory1, connectionFactory2, defaultConnectionFactory);
container.setQueueNames("baz");
Mockito.verify(connectionFactory1).createConnection();
Mockito.verify(connectionFactory2, never()).createConnection();
Mockito.verify(defaultConnectionFactory, never()).createConnection();
Mockito.reset(connectionFactory1, connectionFactory2, defaultConnectionFactory);
container.setQueueNames("qux");
Mockito.verify(connectionFactory1, never()).createConnection();
Mockito.verify(connectionFactory2, never()).createConnection();
Mockito.verify(defaultConnectionFactory).createConnection();
container.stop();
}
}

View File

@@ -469,6 +469,12 @@ trustStore.passPhrase=secret</programlisting>
and <code>receive-connection-factory-selector-expression</code> attributes
on the <code>&lt;rabbit:template&gt;</code> component.
</para>
<para>
Also starting with <emphasis>version 1.4</emphasis>, you can configure a routing connection factory
in a <classname>SimpleMessageListenerContainer</classname>. In that case, the list of queue names
is used as the lookup key. For example, if you configure the container with
<code>setQueueNames("foo, bar")</code>, the lookup key will be <code>"[foo,bar]"</code> (no spaces).
</para>
</section>
<section id="cf-pub-conf-ret">

View File

@@ -112,6 +112,13 @@
See <xref linkend="routing-connection-factory"/>.
</para>
</section>
<section>
<para>
A <classname>SimpleMessageListenerContainer</classname> can be configured with a routing
connection factory to enable connection selection based on the queue names.
See <xref linkend="routing-connection-factory"/>.
</para>
</section>
<section>
<title>RabbitTemplate: RecoveryCallback option</title>
<para>