diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java index ea1b0abcdb..0e0f0808f4 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java @@ -1090,7 +1090,7 @@ public interface ActiveMQServerControl { @Operation(desc = "Destroy a queue", impact = MBeanOperationInfo.ACTION) void destroyQueue(@Parameter(name = "name", desc = "Name of the queue to destroy") String name, @Parameter(name = "removeConsumers", desc = "Remove consumers of this queue") boolean removeConsumers, - @Parameter(name = "autoDeleteAddress", desc = "Automatically delete the address if this was the last queue") boolean autoDeleteAddress) throws Exception; + @Parameter(name = "forceAutoDeleteAddress", desc = "Automatically delete the address if this was the last queue") boolean autoDeleteAddress) throws Exception; /** * Enables message counters for this server. diff --git a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java index 951b9addcb..534b77d010 100644 --- a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java +++ b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/impl/JMSServerManagerImpl.java @@ -817,7 +817,7 @@ public class JMSServerManagerImpl extends CleaningActivateCallback implements JM // We can't remove the remote binding. As this would be the bridge associated with the topic on this case if (binding.getType() != BindingType.REMOTE_QUEUE) { - server.destroyQueue(SimpleString.toSimpleString(queueName), null, !removeConsumers, removeConsumers, true); + server.destroyQueue(SimpleString.toSimpleString(queueName), null, !removeConsumers, removeConsumers, false); } } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java index eb59d5343f..af17daf5f3 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java @@ -1563,9 +1563,9 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active } @Override - public void destroyQueue(final String name, final boolean removeConsumers, final boolean autoDeleteAddress) throws Exception { + public void destroyQueue(final String name, final boolean removeConsumers, final boolean forceAutoDeleteAddress) throws Exception { if (AuditLogger.isBaseLoggingEnabled()) { - AuditLogger.destroyQueue(this.server, null, null, name, removeConsumers, autoDeleteAddress); + AuditLogger.destroyQueue(this.server, null, null, name, removeConsumers, forceAutoDeleteAddress); } checkStarted(); @@ -1573,7 +1573,7 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active try { SimpleString queueName = new SimpleString(name); try { - server.destroyQueue(queueName, null, !removeConsumers, removeConsumers, autoDeleteAddress); + server.destroyQueue(queueName, null, !removeConsumers, removeConsumers, forceAutoDeleteAddress); } catch (Exception e) { if (AuditLogger.isResourceLoggingEnabled()) { AuditLogger.destroyQueueFailure(name); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java index 60681f58d1..7f551d475b 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java @@ -672,13 +672,13 @@ public interface ActiveMQServer extends ServiceComponent { SecurityAuth session, boolean checkConsumerCount, boolean removeConsumers, - boolean autoDeleteAddress) throws Exception; + boolean forceAutoDeleteAddress) throws Exception; void destroyQueue(SimpleString queueName, SecurityAuth session, boolean checkConsumerCount, boolean removeConsumers, - boolean autoDeleteAddress, + boolean forceAutoDeleteAddress, boolean checkMessageCount) throws Exception; String destroyConnectionWithSessionMetadata(String metaKey, String metaValue) throws Exception; diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index b30b77fe8e..89fcbeb855 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -2329,9 +2329,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { throw ActiveMQMessageBundle.BUNDLE.noSuchQueue(queueName); } - String address = binding.getAddress().toString(); - - destroyQueue(queueName, session, checkConsumerCount, removeConsumers, addressSettingsRepository.getMatch(address).isAutoDeleteAddresses()); + destroyQueue(queueName, session, checkConsumerCount, removeConsumers, false); } @Override @@ -2339,8 +2337,8 @@ public class ActiveMQServerImpl implements ActiveMQServer { final SecurityAuth session, final boolean checkConsumerCount, final boolean removeConsumers, - final boolean autoDeleteAddress) throws Exception { - destroyQueue(queueName, session, checkConsumerCount, removeConsumers, autoDeleteAddress, false); + final boolean forceAutoDeleteAddress) throws Exception { + destroyQueue(queueName, session, checkConsumerCount, removeConsumers, forceAutoDeleteAddress, false); } @Override @@ -2348,7 +2346,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { final SecurityAuth session, final boolean checkConsumerCount, final boolean removeConsumers, - final boolean autoDeleteAddress, + final boolean forceAutoDeleteAddress, final boolean checkMessageCount) throws Exception { if (postOffice == null) { return; @@ -2384,7 +2382,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { } if (hasBrokerQueuePlugins()) { - callBrokerQueuePlugins(plugin -> plugin.beforeDestroyQueue(queue, session, checkConsumerCount, removeConsumers, autoDeleteAddress)); + callBrokerQueuePlugins(plugin -> plugin.beforeDestroyQueue(queue, session, checkConsumerCount, removeConsumers, forceAutoDeleteAddress)); } if (mirrorControllerService != null) { @@ -2394,13 +2392,13 @@ public class ActiveMQServerImpl implements ActiveMQServer { queue.deleteQueue(removeConsumers); if (hasBrokerQueuePlugins()) { - callBrokerQueuePlugins(plugin -> plugin.afterDestroyQueue(queue, address, session, checkConsumerCount, removeConsumers, autoDeleteAddress)); + callBrokerQueuePlugins(plugin -> plugin.afterDestroyQueue(queue, address, session, checkConsumerCount, removeConsumers, forceAutoDeleteAddress)); } - if (queue.isTemporary()) { + if (forceAutoDeleteAddress) { AddressInfo addressInfo = getAddressInfo(address); - if (autoDeleteAddress && postOffice != null && addressInfo != null && addressInfo.isAutoCreated() && !isAddressBound(address.toString()) && addressSettingsRepository.getMatch(address.toString()).getAutoDeleteAddressesDelay() == 0) { + if (postOffice != null && addressInfo != null && addressInfo.isAutoCreated() && !isAddressBound(address.toString()) && addressSettingsRepository.getMatch(address.toString()).getAutoDeleteAddressesDelay() == 0) { try { removeAddressInfo(address, session); } catch (ActiveMQDeleteAddressException e) { diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueManagerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueManagerImpl.java index d64f576cf1..9fa34f8783 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueManagerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueManagerImpl.java @@ -72,7 +72,7 @@ public class QueueManagerImpl extends ReferenceCounterUtil implements QueueManag ActiveMQServerLogger.LOGGER.autoRemoveQueue("" + queue.getName(), queue.getID(), "" + queue.getAddress()); try { - server.destroyQueue(queueName, null, true, false, settings.isAutoDeleteAddresses(), true); + server.destroyQueue(queueName, null, true, false, false, true); } catch (Exception e) { ActiveMQServerLogger.LOGGER.errorRemovingAutoCreatedDestination(e, queueName, "queue"); } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java index 6e7805ab81..9ac5129d86 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java @@ -1129,7 +1129,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { logger.debug("deleting temporary queue " + bindingName); } try { - server.destroyQueue(bindingName, null, false); + server.destroyQueue(bindingName, null, false, false, true); if (observer != null) { observer.tempQueueDeleted(bindingName); } @@ -1177,7 +1177,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { throw new ActiveMQNonExistentQueueException(); } - server.destroyQueue(unPrefixedQueueName, this, true); + server.destroyQueue(unPrefixedQueueName, this, true, false, true); TempQueueCleanerUpper cleaner = this.tempQueueCleannerUppers.remove(unPrefixedQueueName); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/TopicDurableTests.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/TopicDurableTests.java index 4c549ce9db..f707cce26e 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/TopicDurableTests.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/TopicDurableTests.java @@ -39,6 +39,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.utils.Wait; import org.apache.qpid.jms.JmsConnectionFactory; import org.junit.Test; @@ -47,6 +48,11 @@ import static org.hamcrest.CoreMatchers.is; public class TopicDurableTests extends JMSClientTestSupport { + @Override + protected void addConfiguration(ActiveMQServer server) { + server.getConfiguration().setAddressQueueScanPeriod(100); + } + @Test public void testMessageDurableSubscription() throws Exception { JmsConnectionFactory connectionFactory = new JmsConnectionFactory(getBrokerQpidJMSConnectionURI() + "?jms.clientID=jmsTopicClient"); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java index 030abfe212..91296cc895 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java @@ -17,6 +17,7 @@ package org.apache.activemq.artemis.tests.integration.jms.client; import javax.jms.Connection; +import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; @@ -35,7 +36,9 @@ import org.apache.activemq.artemis.core.settings.impl.AddressSettings; import org.apache.activemq.artemis.jms.client.ActiveMQConnection; import org.apache.activemq.artemis.jms.client.ActiveMQDestination; import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager; +import org.apache.activemq.artemis.tests.util.CFUtil; import org.apache.activemq.artemis.tests.util.JMSTestBase; +import org.apache.activemq.artemis.tests.util.Wait; import org.junit.Before; import org.junit.Test; @@ -278,6 +281,8 @@ public class TemporaryDestinationTest extends JMSTestBase { for (ServerSession serverSession : server.getSessions()) { assertFalse(((ServerSessionImpl)serverSession).cloneTargetAddresses().containsKey(SimpleString.toSimpleString(temporaryQueue.getQueueName()))); } + Wait.assertTrue(() -> server.locateQueue(temporaryQueue.getQueueName()) == null, 1000, 100); + Wait.assertTrue(() -> server.getAddressInfo(SimpleString.toSimpleString(temporaryQueue.getQueueName())) == null, 1000, 100); } finally { if (conn != null) { conn.close(); @@ -285,6 +290,39 @@ public class TemporaryDestinationTest extends JMSTestBase { } } + @Test + public void testTemporaryQueueConnectionClosedRemovedAMQP() throws Exception { + testTemporaryQueueConnectionClosedRemoved("AMQP"); + } + + @Test + public void testTemporaryQueueConnectionClosedRemovedCORE() throws Exception { + testTemporaryQueueConnectionClosedRemoved("CORE"); + } + + @Test + public void testTemporaryQueueConnectionClosedRemovedOpenWire() throws Exception { + testTemporaryQueueConnectionClosedRemoved("OPENWIRE"); + } + + private void testTemporaryQueueConnectionClosedRemoved(String protocol) throws Exception { + ConnectionFactory factory = CFUtil.createConnectionFactory("amqp", "tcp://localhost:61616"); + final TemporaryQueue temporaryQueue; + try (Connection conn = factory.createConnection()) { + Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + temporaryQueue = s.createTemporaryQueue(); + MessageProducer producer = s.createProducer(temporaryQueue); + producer.send(s.createMessage()); + // These next two assertions are here to validate the test itself + // The queue and address should be found on the server while they still exist on the connection + Wait.assertFalse(() -> server.locateQueue(temporaryQueue.getQueueName()) == null, 1000, 100); + Wait.assertFalse(() -> server.getAddressInfo(SimpleString.toSimpleString(temporaryQueue.getQueueName())) == null, 1000, 100); + } + + Wait.assertTrue(() -> server.locateQueue(temporaryQueue.getQueueName()) == null, 1000, 100); + Wait.assertTrue(() -> server.getAddressInfo(SimpleString.toSimpleString(temporaryQueue.getQueueName())) == null, 1000, 100); + } + @Test public void testForTempQueueTargetInfosSizeLimit() throws Exception { try { diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java index 127b2ef3c1..7c3fecce52 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java @@ -81,6 +81,7 @@ import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.server.ServerConsumer; import org.apache.activemq.artemis.core.server.ServerSession; import org.apache.activemq.artemis.core.server.impl.AddressInfo; +import org.apache.activemq.artemis.core.settings.impl.AddressSettings; import org.apache.activemq.artemis.core.settings.impl.DeletionPolicy; import org.apache.activemq.artemis.core.settings.impl.SlowConsumerPolicy; import org.apache.activemq.artemis.core.transaction.impl.XidImpl; @@ -506,6 +507,35 @@ public class ActiveMQServerControlTest extends ManagementTestBase { checkNoResource(ObjectNameBuilder.DEFAULT.getAddressObjectName(address)); } + @Test + public void testCreateAndDestroyQueueWithAutoDeleteAddress() throws Exception { + server.getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoDeleteAddresses(false)); + SimpleString address = RandomUtil.randomSimpleString(); + SimpleString name = RandomUtil.randomSimpleString(); + + ActiveMQServerControl serverControl = createManagementControl(); + + checkNoResource(ObjectNameBuilder.DEFAULT.getQueueObjectName(address, name, RoutingType.ANYCAST)); + if (legacyCreateQueue) { + serverControl.createQueue(address.toString(), "ANYCAST", name.toString(), null, true, -1, false, true); + } else { + serverControl.createQueue(new QueueConfiguration(name).setAddress(address).setRoutingType(RoutingType.ANYCAST).setAutoCreateAddress(true).toJSON()); + } + + checkResource(ObjectNameBuilder.DEFAULT.getQueueObjectName(address, name, RoutingType.ANYCAST)); + QueueControl queueControl = ManagementControlHelper.createQueueControl(address, name, RoutingType.ANYCAST, mbeanServer); + Assert.assertEquals(address.toString(), queueControl.getAddress()); + Assert.assertEquals(name.toString(), queueControl.getName()); + Assert.assertNull(queueControl.getFilter()); + Assert.assertEquals(true, queueControl.isDurable()); + Assert.assertEquals(false, queueControl.isTemporary()); + + serverControl.destroyQueue(name.toString(), false, true); + + checkNoResource(ObjectNameBuilder.DEFAULT.getQueueObjectName(address, name, RoutingType.ANYCAST)); + checkNoResource(ObjectNameBuilder.DEFAULT.getAddressObjectName(address)); + } + @Test public void testRemoveQueueFilter() throws Exception {