/** * 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 io.hawtjms.provider.stomp.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 static org.junit.Assert.fail; import io.hawtjms.test.support.StompTestSupport; import io.hawtjms.test.support.Wait; 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.InvalidSelectorException; import javax.jms.JMSException; import javax.jms.JMSSecurityException; 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.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Test for basic JMS MessageConsumer functionality. */ public class JmsMessageConsumerTest extends StompTestSupport { protected static final Logger LOG = LoggerFactory.getLogger(JmsMessageConsumerTest.class); @Override public boolean isPersistent() { return true; } @Test(timeout = 60000) public void testCreateMessageConsumer() throws Exception { connection = createStompConnection(); 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 = createStompConnection(); 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(200000)); 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 = createStompConnection(); 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(2000)); assertTrue("Published 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 */ @Test(timeout = 60000) public void testConsumerReceiveBeforeMessageDispatched() throws Exception { final Connection connection = createStompConnection(); 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(10); 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 = createStompConnection(); 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(1000, TimeUnit.MILLISECONDS)); TimeUnit.SECONDS.sleep(1); assertEquals(msgCount, counter.get()); } @Test(timeout = 60000) public void testSyncReceiveFailsWhenListenerSet() throws Exception { final int msgCount = 4; final Connection connection = createStompConnection(); 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(); } } }); try { consumer.receive(); fail("Should have thrown an exception."); } catch (JMSException ex) { } try { consumer.receive(1000); fail("Should have thrown an exception."); } catch (JMSException ex) { } try { consumer.receiveNoWait(); fail("Should have thrown an exception."); } catch (JMSException ex) { } } @Test(timeout = 60000) public void testSetMessageListenerAfterStartAndSend() throws Exception { final int msgCount = 4; final Connection connection = createStompConnection(); 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); sendToAmqQueue(msgCount); 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(); } } }); assertTrue(done.await(1000, TimeUnit.MILLISECONDS)); TimeUnit.SECONDS.sleep(1); assertEquals(msgCount, counter.get()); } @Test(timeout = 60000) public void testNoReceivedMessagesWhenConnectionNotStarted() throws Exception { connection = createStompConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue destination = session.createQueue(name.getMethodName()); MessageConsumer consumer = session.createConsumer(destination); sendToAmqQueue(3); assertNull(consumer.receive(2000)); } @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 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); } // After the first restart we should get all messages sent above restartPrimaryBroker(); int messagesReceived = readAllMessages(); assertEquals("Should have read: " + messagesSent, messagesSent, messagesReceived); // This time there should be no messages on this queue restartPrimaryBroker(); messagesReceived = readAllMessages(); assertEquals(0, messagesReceived); } @Test(timeout = 60000) public void testMessagesAreAckedStompProducer() throws Exception { int messagesSent = 3; connection = createStompConnection(); 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(); int messagesReceived = readAllMessages(); assertEquals(messagesSent, messagesReceived); // This time there should be no messages on this queue restartPrimaryBroker(); messagesReceived = readAllMessages(); assertEquals(0, messagesReceived); } private int readAllMessages() throws Exception { return readAllMessages(null); } private int readAllMessages(String selector) throws Exception { connection = createStompConnection(); connection.start(); 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(5000); while (msg != null) { assertNotNull(msg); assertTrue(msg instanceof TextMessage); TextMessage textMessage = (TextMessage) msg; LOG.debug(">>>> Received [{}]", textMessage.getText()); messagesReceived++; msg = consumer.receive(5000); } consumer.close(); return messagesReceived; } @Ignore @Test(timeout = 30000) public void testSelectors() throws Exception{ connection = createStompConnection(); 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); QueueViewMBean proxy = getProxyToQueue(name.getMethodName()); assertEquals(2, proxy.getQueueSize()); MessageConsumer consumer = session.createConsumer(queue, "JMSPriority > 8"); Message msg = consumer.receive(5000); assertNotNull(msg); assertTrue(msg instanceof TextMessage); assertEquals("hello + 9", ((TextMessage) msg).getText()); assertNull(consumer.receive(1000)); } @Test(timeout = 90000, expected=JMSSecurityException.class) public void testConsumerNotAuthorized() throws Exception{ connection = createStompConnection("guest", "password"); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue("USERS." + name.getMethodName()); session.createConsumer(queue); } @Test(timeout = 90000, expected=InvalidSelectorException.class) public void testInvalidSelector() throws Exception{ connection = createStompConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue(name.getMethodName()); session.createConsumer(queue, "3+5"); } }