/* * 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.addressing; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.ActiveMQQueueMaxConsumerLimitReached; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.core.client.ActiveMQClient; import org.apache.activemq.artemis.api.core.client.ClientConsumer; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.client.ClientProducer; import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; import org.apache.activemq.artemis.api.core.client.ServerLocator; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.api.core.RoutingType; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.server.impl.AddressInfo; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.apache.activemq.artemis.tests.util.Wait; import org.junit.Before; import org.junit.Test; public class AddressingTest extends ActiveMQTestBase { private ActiveMQServer server; private ClientSessionFactory sessionFactory; @Before public void setup() throws Exception { server = createServer(true); server.start(); server.waitForActivation(10, TimeUnit.SECONDS); ServerLocator sl = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(INVM_CONNECTOR_FACTORY)); sessionFactory = sl.createSessionFactory(); addSessionFactory(sessionFactory); } @Test public void testMulticastRouting() throws Exception { SimpleString sendAddress = new SimpleString("test.address"); List<String> testAddresses = Arrays.asList("test.address", "test.#", "test.*"); for (String consumeAddress : testAddresses) { // For each address, create 2 Queues with the same address, assert both queues receive message AddressInfo addressInfo = new AddressInfo(new SimpleString(consumeAddress)); addressInfo.addRoutingType(RoutingType.MULTICAST); server.addOrUpdateAddressInfo(addressInfo); Queue q1 = server.createQueue(new SimpleString(consumeAddress), RoutingType.MULTICAST, new SimpleString(consumeAddress + ".1"), null, true, false); Queue q2 = server.createQueue(new SimpleString(consumeAddress), RoutingType.MULTICAST, new SimpleString(consumeAddress + ".2"), null, true, false); ClientSession session = sessionFactory.createSession(); session.start(); ClientConsumer consumer1 = session.createConsumer(q1.getName()); ClientConsumer consumer2 = session.createConsumer(q2.getName()); ClientProducer producer = session.createProducer(sendAddress); ClientMessage m = session.createMessage(ClientMessage.TEXT_TYPE, true); m.getBodyBuffer().writeString("TestMessage"); producer.send(m); assertNotNull(consumer1.receive(2000)); assertNotNull(consumer2.receive(2000)); q1.deleteQueue(); q2.deleteQueue(); } } @Test public void testAnycastRouting() throws Exception { SimpleString sendAddress = new SimpleString("test.address"); List<String> testAddresses = Arrays.asList("test.address", "test.#", "test.*"); for (String consumeAddress : testAddresses) { // For each address, create 2 Queues with the same address, assert one queue receive message AddressInfo addressInfo = new AddressInfo(new SimpleString(consumeAddress)); addressInfo.addRoutingType(RoutingType.ANYCAST); server.addOrUpdateAddressInfo(addressInfo); Queue q1 = server.createQueue(new SimpleString(consumeAddress), RoutingType.ANYCAST, new SimpleString(consumeAddress + ".1"), null, true, false, Queue.MAX_CONSUMERS_UNLIMITED, false, true); Queue q2 = server.createQueue(new SimpleString(consumeAddress), RoutingType.ANYCAST, new SimpleString(consumeAddress + ".2"), null, true, false, Queue.MAX_CONSUMERS_UNLIMITED, false, true); ClientSession session = sessionFactory.createSession(); session.start(); ClientConsumer consumer1 = session.createConsumer(q1.getName()); ClientConsumer consumer2 = session.createConsumer(q2.getName()); ClientProducer producer = session.createProducer(sendAddress); ClientMessage m = session.createMessage(ClientMessage.TEXT_TYPE, true); m.getBodyBuffer().writeString("TestMessage"); producer.send(m); int count = 0; count = (consumer1.receive(1000) == null) ? count : count + 1; count = (consumer2.receive(1000) == null) ? count : count + 1; assertEquals(1, count); q1.deleteQueue(); q2.deleteQueue(); } } @Test public void testAnycastRoutingRoundRobin() throws Exception { SimpleString address = new SimpleString("test.address"); AddressInfo addressInfo = new AddressInfo(address); addressInfo.addRoutingType(RoutingType.ANYCAST); server.addOrUpdateAddressInfo(addressInfo); Queue q1 = server.createQueue(address, RoutingType.ANYCAST, address.concat(".1"), null, true, false, Queue.MAX_CONSUMERS_UNLIMITED, false, true); Queue q2 = server.createQueue(address, RoutingType.ANYCAST, address.concat(".2"), null, true, false, Queue.MAX_CONSUMERS_UNLIMITED, false, true); Queue q3 = server.createQueue(address, RoutingType.ANYCAST, address.concat(".3"), null, true, false, Queue.MAX_CONSUMERS_UNLIMITED, false, true); ClientSession session = sessionFactory.createSession(); session.start(); ClientProducer producer = session.createProducer(address); ClientConsumer consumer1 = session.createConsumer(q1.getName()); ClientConsumer consumer2 = session.createConsumer(q2.getName()); ClientConsumer consumer3 = session.createConsumer(q3.getName()); List<ClientConsumer> consumers = new ArrayList<>(Arrays.asList(new ClientConsumer[]{consumer1, consumer2, consumer3})); List<String> messages = new ArrayList<>(); messages.add("Message1"); messages.add("Message2"); messages.add("Message3"); ClientMessage clientMessage; for (String message : messages) { clientMessage = session.createMessage(true); clientMessage.getBodyBuffer().writeString(message); producer.send(clientMessage); } String m; for (ClientConsumer consumer : consumers) { clientMessage = consumer.receive(1000); m = clientMessage.getBodyBuffer().readString(); messages.remove(m); } assertTrue(messages.isEmpty()); // Check we don't receive more messages int count = 0; for (ClientConsumer consumer : consumers) { count = (consumer.receive(1000) == null) ? count : count + 1; } assertEquals(0, count); } @Test public void testMulticastRoutingBackwardsCompat() throws Exception { SimpleString sendAddress = new SimpleString("test.address"); List<String> testAddresses = Arrays.asList("test.address", "test.#", "test.*"); for (String consumeAddress : testAddresses) { // For each address, create 2 Queues with the same address, assert both queues receive message Queue q1 = server.createQueue(new SimpleString(consumeAddress), RoutingType.MULTICAST, new SimpleString(consumeAddress + ".1"), null, true, false); Queue q2 = server.createQueue(new SimpleString(consumeAddress), RoutingType.MULTICAST, new SimpleString(consumeAddress + ".2"), null, true, false); ClientSession session = sessionFactory.createSession(); session.start(); ClientConsumer consumer1 = session.createConsumer(q1.getName()); ClientConsumer consumer2 = session.createConsumer(q2.getName()); ClientProducer producer = session.createProducer(sendAddress); ClientMessage m = session.createMessage(ClientMessage.TEXT_TYPE, true); m.getBodyBuffer().writeString("TestMessage"); producer.send(m); assertNotNull(consumer1.receive(2000)); assertNotNull(consumer2.receive(2000)); q1.deleteQueue(); q2.deleteQueue(); } } @Test public void testPurgeOnNoConsumersTrue() throws Exception { SimpleString address = new SimpleString("test.address"); SimpleString queueName = SimpleString.toSimpleString(UUID.randomUUID().toString()); server.createQueue(address, RoutingType.ANYCAST, queueName, null, null, true, false, false, false, false, 1, true, true); Queue queue = server.locateQueue(queueName); assertNotNull(queue); ClientSession session = sessionFactory.createSession(); ClientProducer producer = session.createProducer(address); // there are no consumers so no messages should be routed to the queue producer.send(session.createMessage(true)); assertEquals(0, queue.getMessageCount()); ClientConsumer consumer = session.createConsumer(queueName); // there is a consumer now so the message should be routed producer.send(session.createMessage(true)); Wait.waitFor(() -> queue.getMessageCount() == 1); assertEquals(1, queue.getMessageCount()); consumer.close(); // the last consumer was closed so the queue should exist but be purged assertNotNull(server.locateQueue(queueName)); assertEquals(0, queue.getMessageCount()); // there are no consumers so no messages should be routed to the queue producer.send(session.createMessage(true)); assertEquals(0, queue.getMessageCount()); } @Test public void testPurgeOnNoConsumersFalse() throws Exception { SimpleString address = new SimpleString("test.address"); SimpleString queueName = SimpleString.toSimpleString(UUID.randomUUID().toString()); server.createQueue(address, RoutingType.ANYCAST, queueName, null, null, true, false, false, false, false, 1, false, true); assertNotNull(server.locateQueue(queueName)); ClientSession session = sessionFactory.createSession(); ClientProducer producer = session.createProducer(address); producer.send(session.createMessage(true)); session.createConsumer(queueName).close(); assertNotNull(server.locateQueue(queueName)); assertEquals(1, server.locateQueue(queueName).getMessageCount()); } @Test public void testLimitOnMaxConsumers() throws Exception { SimpleString address = new SimpleString("test.address"); SimpleString queueName = SimpleString.toSimpleString(UUID.randomUUID().toString()); // For each address, create 2 Queues with the same address, assert both queues receive message boolean purgeOnNoConsumers = false; Queue q1 = server.createQueue(address, RoutingType.MULTICAST, queueName, null, true, false, 0, purgeOnNoConsumers, true); Exception expectedException = null; String expectedMessage = "Maximum Consumer Limit Reached on Queue"; try { ClientSession session = sessionFactory.createSession(); session.start(); session.createConsumer(q1.getName()); } catch (ActiveMQQueueMaxConsumerLimitReached e) { expectedException = e; } assertNotNull(expectedException); assertTrue(expectedException.getMessage().contains(expectedMessage)); assertTrue(expectedException.getMessage().contains(address)); assertTrue(expectedException.getMessage().contains(queueName)); } @Test public void testUnlimitedMaxConsumers() throws Exception { int noConsumers = 50; SimpleString address = new SimpleString("test.address"); SimpleString queueName = SimpleString.toSimpleString(UUID.randomUUID().toString()); // For each address, create 2 Queues with the same address, assert both queues receive message boolean purgeOnNoConsumers = false; Queue q1 = server.createQueue(address, RoutingType.MULTICAST, queueName, null, true, false, Queue.MAX_CONSUMERS_UNLIMITED, purgeOnNoConsumers, true); ClientSession session = sessionFactory.createSession(); session.start(); for (int i = 0; i < noConsumers; i++) { session.createConsumer(q1.getName()); } } @Test public void testEmptyRoutingTypes() throws Exception { server.addOrUpdateAddressInfo(new AddressInfo(SimpleString.toSimpleString("xy"))); server.stop(); server.start(); server.addOrUpdateAddressInfo(new AddressInfo(SimpleString.toSimpleString("xy"))); server.stop(); } }