/* * 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.activemq.artemis.tests.integration.amqp; import java.util.ArrayList; import java.util.Enumeration; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.QueueBrowser; import javax.jms.Session; import javax.jms.TextMessage; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.tests.util.Wait; import org.apache.qpid.jms.JmsConnection; import org.apache.qpid.jms.policy.JmsDefaultPrefetchPolicy; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JMSMessageConsumerTest extends JMSClientTestSupport { protected static final Logger LOG = LoggerFactory.getLogger(JMSMessageConsumerTest.class); @Test(timeout = 60000) public void testSelector() throws Exception { Connection connection = createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); MessageProducer producer = session.createProducer(queue); TextMessage message = session.createTextMessage(); message.setText("msg:0"); producer.send(message); message = session.createTextMessage(); message.setText("msg:1"); message.setStringProperty("color", "RED"); producer.send(message); connection.start(); MessageConsumer messageConsumer = session.createConsumer(queue, "color = 'RED'"); TextMessage m = (TextMessage) messageConsumer.receive(5000); assertNotNull(m); assertEquals("msg:1", m.getText()); assertEquals(m.getStringProperty("color"), "RED"); } finally { connection.close(); } } @SuppressWarnings("rawtypes") @Test(timeout = 30000) public void testSelectorsWithJMSType() throws Exception { Connection connection = createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); MessageProducer p = session.createProducer(queue); TextMessage message = session.createTextMessage(); message.setText("text"); p.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"); p.send(message2, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); QueueBrowser browser = session.createBrowser(queue); Enumeration enumeration = browser.getEnumeration(); int count = 0; while (enumeration.hasMoreElements()) { Message m = (Message) enumeration.nextElement(); assertTrue(m instanceof TextMessage); count++; } assertEquals(2, count); MessageConsumer consumer = session.createConsumer(queue, "JMSType = '" + type + "'"); Message msg = consumer.receive(2000); assertNotNull(msg); assertTrue(msg instanceof TextMessage); assertEquals("Unexpected JMSType value", type, msg.getJMSType()); assertEquals("Unexpected message content", "text + type", ((TextMessage) msg).getText()); } finally { connection.close(); } } @SuppressWarnings("rawtypes") @Test(timeout = 30000) public void testSelectorsWithJMSPriority() throws Exception { Connection connection = createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); 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); QueueBrowser browser = session.createBrowser(queue); Enumeration enumeration = browser.getEnumeration(); int count = 0; while (enumeration.hasMoreElements()) { Message m = (Message) enumeration.nextElement(); assertTrue(m instanceof TextMessage); count++; } assertEquals(2, count); MessageConsumer consumer = session.createConsumer(queue, "JMSPriority > 8"); Message msg = consumer.receive(2000); assertNotNull(msg); assertTrue(msg instanceof TextMessage); assertEquals("hello + 9", ((TextMessage) msg).getText()); } finally { connection.close(); } } @Test(timeout = 60000) public void testJMSSelectorFiltersJMSMessageID() throws Exception { Connection connection = createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); MessageProducer producer = session.createProducer(queue); // Send one to receive TextMessage message = session.createTextMessage(); producer.send(message); // Send another to filter producer.send(session.createTextMessage()); connection.start(); // First one should make it through MessageConsumer messageConsumer = session.createConsumer(queue, "JMSMessageID = '" + message.getJMSMessageID() + "'"); TextMessage m = (TextMessage) messageConsumer.receive(5000); assertNotNull(m); assertEquals(message.getJMSMessageID(), m.getJMSMessageID()); // The second one should not be received. assertNull(messageConsumer.receive(1000)); } finally { connection.close(); } } @Test(timeout = 60000) public void testZeroPrefetchWithTwoConsumers() throws Exception { JmsConnection connection = (JmsConnection) createConnection(); ((JmsDefaultPrefetchPolicy) connection.getPrefetchPolicy()).setAll(0); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); MessageProducer producer = session.createProducer(queue); producer.send(session.createTextMessage("Msg1")); producer.send(session.createTextMessage("Msg2")); // now lets receive it MessageConsumer consumer1 = session.createConsumer(queue); MessageConsumer consumer2 = session.createConsumer(queue); TextMessage answer = (TextMessage) consumer1.receive(5000); assertNotNull(answer); assertEquals("Should have received a message!", answer.getText(), "Msg1"); answer = (TextMessage) consumer2.receive(5000); assertNotNull(answer); assertEquals("Should have received a message!", answer.getText(), "Msg2"); answer = (TextMessage) consumer2.receiveNoWait(); assertNull("Should have not received a message!", answer); } @Test(timeout = 30000) public void testProduceAndConsumeLargeNumbersOfTopicMessagesClientAck() throws Exception { doTestProduceAndConsumeLargeNumbersOfMessages(true, Session.CLIENT_ACKNOWLEDGE); } @Test(timeout = 30000) public void testProduceAndConsumeLargeNumbersOfQueueMessagesClientAck() throws Exception { doTestProduceAndConsumeLargeNumbersOfMessages(false, Session.CLIENT_ACKNOWLEDGE); } @Test(timeout = 30000) public void testProduceAndConsumeLargeNumbersOfTopicMessagesAutoAck() throws Exception { doTestProduceAndConsumeLargeNumbersOfMessages(true, Session.AUTO_ACKNOWLEDGE); } @Test(timeout = 30000) public void testProduceAndConsumeLargeNumbersOfQueueMessagesAutoAck() throws Exception { doTestProduceAndConsumeLargeNumbersOfMessages(false, Session.AUTO_ACKNOWLEDGE); } public void doTestProduceAndConsumeLargeNumbersOfMessages(boolean topic, int ackMode) throws Exception { final int MSG_COUNT = 1000; final CountDownLatch done = new CountDownLatch(MSG_COUNT); JmsConnection connection = (JmsConnection) createConnection(); connection.setForceAsyncSend(true); connection.start(); Session session = connection.createSession(false, ackMode); final Destination destination; if (topic) { destination = session.createTopic(getTopicName()); } else { destination = session.createQueue(getQueueName()); } MessageConsumer consumer = session.createConsumer(destination); consumer.setMessageListener(new MessageListener() { @Override public void onMessage(Message message) { try { message.acknowledge(); done.countDown(); } catch (JMSException ex) { LOG.info("Caught exception.", ex); } } }); MessageProducer producer = session.createProducer(destination); TextMessage textMessage = session.createTextMessage(); textMessage.setText("messageText"); for (int i = 0; i < MSG_COUNT; i++) { producer.send(textMessage); } assertTrue("Did not receive all messages: " + MSG_COUNT, done.await(15, TimeUnit.SECONDS)); } @Test(timeout = 60000) public void testPrefetchedMessagesAreNotConsumedOnConsumerClose() throws Exception { final int NUM_MESSAGES = 10; Connection connection = createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); MessageProducer producer = session.createProducer(queue); byte[] bytes = new byte[2048]; new Random().nextBytes(bytes); for (int i = 0; i < NUM_MESSAGES; i++) { TextMessage message = session.createTextMessage(); message.setText("msg:" + i); producer.send(message); } connection.close(); Queue queueView = getProxyToQueue(getQueueName()); assertTrue("Not all messages were enqueud", Wait.waitFor(() -> queueView.getMessageCount() == NUM_MESSAGES)); // Create a consumer and prefetch the messages connection = createConnection(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(queue); Thread.sleep(100); consumer.close(); connection.close(); assertTrue("Not all messages were enqueud", Wait.waitFor(() -> queueView.getMessageCount() == NUM_MESSAGES)); } finally { connection.close(); } } @Test(timeout = 60000) public void testMessagesReceivedInParallel() throws Throwable { final int numMessages = 50000; long time = System.currentTimeMillis(); final ArrayList<Throwable> exceptions = new ArrayList<>(); Thread t = new Thread(new Runnable() { @Override public void run() { Connection connectionConsumer = null; try { connectionConsumer = createConnection(); connectionConsumer.start(); Session sessionConsumer = connectionConsumer.createSession(false, Session.AUTO_ACKNOWLEDGE); final javax.jms.Queue queue = sessionConsumer.createQueue(getQueueName()); final MessageConsumer consumer = sessionConsumer.createConsumer(queue); long n = 0; int count = numMessages; while (count > 0) { try { if (++n % 1000 == 0) { System.out.println("received " + n + " messages"); } Message m = consumer.receive(5000); Assert.assertNotNull("Could not receive message count=" + count + " on consumer", m); count--; } catch (JMSException e) { e.printStackTrace(); break; } } } catch (Throwable e) { exceptions.add(e); e.printStackTrace(); } finally { try { connectionConsumer.close(); } catch (Throwable ignored) { // NO OP } } } }); Connection connection = createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); t.start(); MessageProducer p = session.createProducer(queue); p.setDeliveryMode(DeliveryMode.NON_PERSISTENT); for (int i = 0; i < numMessages; i++) { BytesMessage message = session.createBytesMessage(); message.writeUTF("Hello world!!!!" + i); message.setIntProperty("count", i); p.send(message); } // Wait for the consumer thread to completely read the Queue t.join(); if (!exceptions.isEmpty()) { throw exceptions.get(0); } Queue queueView = getProxyToQueue(getQueueName()); connection.close(); assertTrue("Not all messages consumed", Wait.waitFor(() -> queueView.getMessageCount() == 0)); long taken = (System.currentTimeMillis() - time); System.out.println("Microbenchamrk ran in " + taken + " milliseconds, sending/receiving " + numMessages); double messagesPerSecond = ((double) numMessages / (double) taken) * 1000; System.out.println(((int) messagesPerSecond) + " messages per second"); } @Test(timeout = 60000) public void testClientAckMessages() throws Exception { final int numMessages = 10; Connection connection = createConnection(); try { long time = System.currentTimeMillis(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(getQueueName()); MessageProducer producer = session.createProducer(queue); byte[] bytes = new byte[2048]; new Random().nextBytes(bytes); for (int i = 0; i < numMessages; i++) { TextMessage message = session.createTextMessage(); message.setText("msg:" + i); producer.send(message); } connection.close(); Queue queueView = getProxyToQueue(getQueueName()); assertTrue("Not all messages enqueued", Wait.waitFor(() -> queueView.getMessageCount() == numMessages)); // Now create a new connection and receive and acknowledge connection = createConnection(); session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(queue); for (int i = 0; i < numMessages; i++) { Message msg = consumer.receive(5000); if (msg == null) { System.out.println("ProtonTest.testManyMessages"); } Assert.assertNotNull("" + i, msg); Assert.assertTrue("" + msg, msg instanceof TextMessage); String text = ((TextMessage) msg).getText(); // System.out.println("text = " + text); Assert.assertEquals(text, "msg:" + i); msg.acknowledge(); } consumer.close(); connection.close(); // Wait for Acks to be processed and message removed from queue. Thread.sleep(500); assertTrue("Not all messages consumed", Wait.waitFor(() -> queueView.getMessageCount() == 0)); long taken = (System.currentTimeMillis() - time) / 1000; System.out.println("taken = " + taken); } finally { connection.close(); } } @Test(timeout = 240000) public void testTimedOutWaitingForWriteLogOnConsumer() throws Throwable { String name = "exampleQueue1"; final int numMessages = 40; Connection connection = createConnection(); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); javax.jms.Queue queue = session.createQueue(name); MessageProducer producer = session.createProducer(queue); for (int i = 0; i < numMessages; i++) { TextMessage message = session.createTextMessage(); message.setText("Message temporary"); producer.send(message); } producer.close(); session.close(); for (int i = 0; i < numMessages; i++) { session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); queue = session.createQueue(name); MessageConsumer c = session.createConsumer(queue); c.receive(1000); producer.close(); session.close(); } session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); queue = session.createQueue(name); MessageConsumer c = session.createConsumer(queue); for (int i = 0; i < numMessages; i++) { c.receive(1000); } producer.close(); session.close(); } finally { connection.close(); } } }