/*
* Copyright 2002-2017 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.listener;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.SingleConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.junit.BrokerRunning;
import org.springframework.amqp.rabbit.junit.LongRunningIntegrationTest;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.utils.test.TestUtils;
import org.springframework.test.util.ReflectionTestUtils;
/**
* @author Gary Russell
*
* @since 1.2.1
*
*/
public class SimpleMessageListenerContainerLongTests {
private final Log logger = LogFactory.getLog(SimpleMessageListenerContainerLongTests.class);
@Rule
public LongRunningIntegrationTest longTest = new LongRunningIntegrationTest();
@Rule
public BrokerRunning brokerRunning = BrokerRunning.isRunningWithEmptyQueues("foo");
@After
public void tearDown() {
this.brokerRunning.removeTestQueues();
}
@Test
public void testChangeConsumerCount() throws Exception {
testChangeConsumerCountGuts(false);
}
@Test
public void testChangeConsumerCountTransacted() throws Exception {
testChangeConsumerCountGuts(true);
}
private void testChangeConsumerCountGuts(boolean transacted) throws Exception {
final SingleConnectionFactory singleConnectionFactory = new SingleConnectionFactory("localhost");
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(singleConnectionFactory);
try {
container.setMessageListener(new MessageListenerAdapter(this));
container.setQueueNames("foo");
container.setAutoStartup(false);
container.setConcurrentConsumers(2);
container.setChannelTransacted(transacted);
container.afterPropertiesSet();
assertEquals(2, ReflectionTestUtils.getField(container, "concurrentConsumers"));
container.start();
waitForNConsumers(container, 2);
container.setConcurrentConsumers(1);
waitForNConsumers(container, 1);
container.setMaxConcurrentConsumers(3);
RabbitTemplate template = new RabbitTemplate(singleConnectionFactory);
for (int i = 0; i < 20; i++) {
template.convertAndSend("foo", "foo");
}
waitForNConsumers(container, 2); // increased consumers due to work
waitForNConsumers(container, 1, 20000); // should stop the extra consumer after 10 seconds idle
container.setConcurrentConsumers(3);
waitForNConsumers(container, 3);
container.stop();
waitForNConsumers(container, 0);
singleConnectionFactory.destroy();
}
finally {
container.stop();
}
}
@Test
public void testAddQueuesAndStartInCycle() throws Exception {
final SingleConnectionFactory connectionFactory = new SingleConnectionFactory("localhost");
final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setMessageListener((MessageListener) message -> { });
container.setConcurrentConsumers(2);
container.afterPropertiesSet();
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
for (int i = 0; i < 20; i++) {
Queue queue = new Queue("testAddQueuesAndStartInCycle" + i);
admin.declareQueue(queue);
container.addQueueNames(queue.getName());
if (!container.isRunning()) {
container.start();
}
}
int n = 0;
while (n++ < 100 && container.getActiveConsumerCount() != 2) {
Thread.sleep(100);
}
assertEquals(2, container.getActiveConsumerCount());
container.stop();
for (int i = 0; i < 20; i++) {
admin.deleteQueue("testAddQueuesAndStartInCycle" + i);
}
connectionFactory.destroy();
}
public void handleMessage(String foo) {
logger.info(foo);
}
private void waitForNConsumers(SimpleMessageListenerContainer container, int n) throws InterruptedException {
this.waitForNConsumers(container, n, 10000);
}
private void waitForNConsumers(SimpleMessageListenerContainer container, int n, int howLong) throws InterruptedException {
int i = 0;
while (true) {
Set<?> consumers = (Set<?>) TestUtils.getPropertyValue(container, "consumers");
if (n == 0 && consumers == null) {
break;
}
if (consumers != null && consumers.size() == n) {
break;
}
Thread.sleep(100);
if (i++ > howLong / 100) {
fail("Never reached " + n + " consumers");
}
}
}
}