/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.qpid.jms.consumer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; import org.apache.activemq.broker.jmx.QueueViewMBean; import org.apache.activemq.broker.jmx.TopicViewMBean; import org.apache.qpid.jms.JmsMessageAvailableListener; import org.apache.qpid.jms.JmsMessageConsumer; import org.apache.qpid.jms.support.AmqpTestSupport; import org.apache.qpid.jms.support.Wait; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Test for basic JMS MessageConsumer functionality. */ public class JmsMessageConsumerTest extends AmqpTestSupport { protected static final Logger LOG = LoggerFactory.getLogger(JmsMessageConsumerTest.class); @Override public boolean isPersistent() { return true; } @Test(timeout = 60000) public void testCreateMessageConsumer() throws Exception { connection = createAmqpConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); assertNotNull(session); Queue queue = session.createQueue(name.getMethodName()); session.createConsumer(queue); QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(0, proxy.getQueueSize()); } @Test(timeout = 60000) public void testSyncConsumeFromQueue() throws Exception { connection = createAmqpConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); assertNotNull(session); Queue queue = session.createQueue(name.getMethodName()); MessageConsumer consumer = session.createConsumer(queue); sendToAmqQueue(1); final QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(1, proxy.getQueueSize()); assertNotNull("Failed to receive any message.", consumer.receive(3000)); assertTrue("Queued message not consumed.", Wait.waitFor(new Wait.Condition() { @Override public boolean isSatisified() throws Exception { return proxy.getQueueSize() == 0; } })); } @Test(timeout = 60000) public void testSyncConsumeFromTopic() throws Exception { connection = createAmqpConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); assertNotNull(session); Topic topic = session.createTopic(name.getMethodName()); MessageConsumer consumer = session.createConsumer(topic); sendToAmqTopic(1); final TopicViewMBean proxy = getProxyToTopic(name.getMethodName()); assertEquals(1, proxy.getEnqueueCount()); assertNotNull("Failed to receive any message.", consumer.receive(3000)); assertTrue("Published message not consumed.", Wait.waitFor(new Wait.Condition() { @Override public boolean isSatisified() throws Exception { return proxy.getQueueSize() == 0; } })); } @Test(timeout = 60000) public void testMessageAvailableConsumer() throws Exception { connection = createAmqpConnection(); connection.start(); final int MSG_COUNT = 10; final AtomicInteger available = new AtomicInteger(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); assertNotNull(session); Queue queue = session.createQueue(name.getMethodName()); MessageConsumer consumer = session.createConsumer(queue); ((JmsMessageConsumer) consumer).setAvailableListener(new JmsMessageAvailableListener() { @Override public void onMessageAvailable(MessageConsumer consumer) { available.incrementAndGet(); } }); sendToAmqQueue(MSG_COUNT); final QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(MSG_COUNT, proxy.getQueueSize()); assertTrue("Listener not notified of correct number of messages.", Wait.waitFor(new Wait.Condition() { @Override public boolean isSatisified() throws Exception { return available.get() == MSG_COUNT; } })); // All should be immediately ready for consume. for (int i = 0; i < MSG_COUNT; ++i) { assertNotNull(consumer.receiveNoWait()); } assertTrue("Queued message not consumed.", Wait.waitFor(new Wait.Condition() { @Override public boolean isSatisified() throws Exception { return proxy.getQueueSize() == 0; } })); } /** * Test to check if consumer thread wakes up inside a receive(timeout) after * a message is dispatched to the consumer. We do a long poll here to ensure * that a blocked receive with timeout does eventually get a Message. We don't * want to test the short poll and retry case here since that's not what we are * testing. * * @throws Exception on error found during test run. */ @Test(timeout = 60000) public void testConsumerReceiveBeforeMessageDispatched() throws Exception { final Connection connection = createAmqpConnection(); this.connection = connection; connection.start(); final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); final Queue queue = session.createQueue(name.getMethodName()); Thread t = new Thread() { @Override public void run() { try { TimeUnit.SECONDS.sleep(5); MessageProducer producer = session.createProducer(queue); producer.send(session.createTextMessage("Hello")); } catch (Exception e) { LOG.warn("Caught during message send: {}", e.getMessage()); } } }; t.start(); MessageConsumer consumer = session.createConsumer(queue); Message msg = consumer.receive(60000); assertNotNull(msg); } @Test(timeout = 60000) public void testAsynchronousMessageConsumption() throws Exception { final int msgCount = 4; final Connection connection = createAmqpConnection(); final AtomicInteger counter = new AtomicInteger(0); final CountDownLatch done = new CountDownLatch(1); this.connection = connection; connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue destination = session.createQueue(name.getMethodName()); MessageConsumer consumer = session.createConsumer(destination); consumer.setMessageListener(new MessageListener() { @Override public void onMessage(Message m) { LOG.debug("Async consumer got Message: {}", m); counter.incrementAndGet(); if (counter.get() == msgCount) { done.countDown(); } } }); sendToAmqQueue(msgCount); assertTrue(done.await(5000, TimeUnit.MILLISECONDS)); assertEquals(msgCount, counter.get()); } @Test(timeout = 60000) public void testMessagesAreAckedAMQProducer() throws Exception { int messagesSent = 3; assertTrue(brokerService.isPersistent()); connection = createActiveMQConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(name.getMethodName()); MessageProducer p = session.createProducer(queue); TextMessage message = null; for (int i=0; i < messagesSent; i++) { message = session.createTextMessage(); String messageText = "Hello " + i + " sent at " + new java.util.Date().toString(); message.setText(messageText); LOG.debug(">>>> Sent [{}]", messageText); p.send(message); } connection.close(); // After the first restart we should get all messages sent above restartPrimaryBroker(); QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(messagesSent, proxy.getQueueSize()); int messagesReceived = readAllMessages(); assertEquals(messagesSent, messagesReceived); // This time there should be no messages on this queue restartPrimaryBroker(); proxy = getProxyToQueue(name.getMethodName()); assertEquals(0, proxy.getQueueSize()); } @Test(timeout = 60000) public void testMessagesAreAckedAMQPProducer() throws Exception { int messagesSent = 3; connection = createAmqpConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(name.getMethodName()); MessageProducer producer = session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.PERSISTENT); TextMessage message = null; for (int i=0; i < messagesSent; i++) { message = session.createTextMessage(); String messageText = "Hello " + i + " sent at " + new java.util.Date().toString(); message.setText(messageText); LOG.debug(">>>> Sent [{}]", messageText); producer.send(message); } connection.close(); // After the first restart we should get all messages sent above restartPrimaryBroker(); QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(messagesSent, proxy.getQueueSize()); int messagesReceived = readAllMessages(); assertEquals(messagesSent, messagesReceived); // This time there should be no messages on this queue restartPrimaryBroker(); proxy = getProxyToQueue(name.getMethodName()); assertEquals(0, proxy.getQueueSize()); } private int readAllMessages() throws Exception { return readAllMessages(null); } private int readAllMessages(String selector) throws Exception { Connection connection = createAmqpConnection(); connection.start(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(name.getMethodName()); int messagesReceived = 0; MessageConsumer consumer; if (selector == null) { consumer = session.createConsumer(queue); } else { consumer = session.createConsumer(queue, selector); } Message msg = consumer.receive(2000); while (msg != null) { assertNotNull(msg); assertTrue(msg instanceof TextMessage); TextMessage textMessage = (TextMessage) msg; LOG.debug(">>>> Received [{}]", textMessage.getText()); messagesReceived++; msg = consumer.receive(2000); } consumer.close(); return messagesReceived; } finally { connection.close(); } } @Test(timeout=30000) public void testSelectors() throws Exception{ connection = createAmqpConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(name.getMethodName()); MessageProducer p = session.createProducer(queue); TextMessage message = session.createTextMessage(); message.setText("hello"); p.send(message, DeliveryMode.PERSISTENT, 5, 0); message = session.createTextMessage(); message.setText("hello + 9"); p.send(message, DeliveryMode.PERSISTENT, 9, 0); p.close(); QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(2, proxy.getQueueSize()); MessageConsumer consumer = session.createConsumer(queue, "JMSPriority > 8"); Message msg = consumer.receive(5000); assertNotNull("No message was recieved", msg); assertTrue(msg instanceof TextMessage); assertEquals("hello + 9", ((TextMessage) msg).getText()); assertNull(consumer.receive(1000)); } @Test(timeout=45000) public void testSelectorsWithJMSType() throws Exception { connection = createAmqpConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(name.getMethodName()); MessageProducer producer = session.createProducer(queue); TextMessage message = session.createTextMessage(); message.setText("text"); producer.send(message, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); TextMessage message2 = session.createTextMessage(); String type = "myJMSType"; message2.setJMSType(type); message2.setText("text + type"); producer.send(message2, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); producer.close(); final QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertTrue("Queue did not get all expected messages", Wait.waitFor(new Wait.Condition() { @Override public boolean isSatisified() throws Exception { return proxy.getQueueSize() == 2; } })); MessageConsumer consumer = session.createConsumer(queue, "JMSType = '" + type + "'"); Message msg = consumer.receive(5000); assertNotNull("No message was recieved", msg); assertTrue(msg instanceof TextMessage); assertEquals("Unexpected JMSType value", type, msg.getJMSType()); assertEquals("Unexpected message content", "text + type", ((TextMessage) msg).getText()); } }