You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@activemq.apache.org by "Justin Bertram (Jira)" <ji...@apache.org> on 2021/08/18 17:13:00 UTC

[jira] [Comment Edited] (ARTEMIS-3424) Unnecessary exception "ActiveMQQueueExistsException: Binding already exists LocalQueueBinding" when creating queue consumers

    [ https://issues.apache.org/jira/browse/ARTEMIS-3424?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17401261#comment-17401261 ] 

Justin Bertram edited comment on ARTEMIS-3424 at 8/18/21, 5:12 PM:
-------------------------------------------------------------------

The {{DEBUG}} logging here is the result of a known race condition between core JMS clients which are auto-creating destinations. In your code when both consumers are started concurrently each checks for the existence of the destination and both are informed that the destination doesn't exist. Therefore each consumer attempts to create the destination. One succeeds and one fails. However, the consumer which fails simply ignores the exception as it is a {{ActiveMQQueueExistsException}} since that means the queue it is trying to create already exists which is functionally equivalent to successfully creating the queue.

The broker logs the exception just like any other exception because it doesn't necessarily know the client will ignore the exception. This is different from ARTEMIS-1707 because in that situation the exception could be ignored _on the broker_ which isn't true here. 

It's also worth noting that debug logging, generally speaking, is expected to be used by folks who have a fairly decent grasp of how the broker works internally (e.g. developers working to diagnose an issue). Exceptions logged at debug can be safely ignored and are presented for informational purposes only. Actual problems are logged at {{WARN}} or {{ERROR}}.

Ultimately if you don't want to see this exception logged at {{DEBUG}} you should define your destinations in your configuration to avoid auto-creation by the core JMS clients. Otherwise you can safely ignore the exceptions.


was (Author: jbertram):
The {{DEBUG}} logging here is the result of a known race condition between core JMS clients which are auto-creating destinations. In your code when both consumers are started concurrently each checks for the existence of the destination and both are informed that the destination doesn't exist. Therefore each consumer attempts to create the destination. One succeeds and one fails. However, the consumer which fails simply ignores the exception as it is a {{ActiveMQQueueExistsException}} since that means the queue it is trying to create already exists which is functionally equivalent to successfully creating the queue.

The broker logs the exception just like any other exception because it doesn't necessarily know the client will ignore the exception. This is different from ARTEMIS-1707 because in that situation the exception could be ignored _on the broker_ which isn't true here. 

It's also worth noting that debug logging, generally speaking, is expected to be used by folks who have a fairly decent grasp of how the broker works internally (e.g. developers working to diagnose an issue). Exceptions logged at debug can be safely ignored and are presented for informational purposes only. Actual problems are logged at {{WARN}} or {{ERROR}}.

> Unnecessary exception "ActiveMQQueueExistsException: Binding already exists LocalQueueBinding" when creating queue consumers
> ----------------------------------------------------------------------------------------------------------------------------
>
>                 Key: ARTEMIS-3424
>                 URL: https://issues.apache.org/jira/browse/ARTEMIS-3424
>             Project: ActiveMQ Artemis
>          Issue Type: Improvement
>            Reporter: Endre Stølsvik
>            Priority: Minor
>
> While working with embedded Artemis (employing the in-vm acceptor), I found these worrisome debug exceptions that consistently came up: {{ActiveMQQueueExistsException: AMQ229018: Binding already exists LocalQueueBinding [address=Test.queue...]}}
> After having scratched my head for a good while, it occurred to me to check on a default install of an Artemis broker on command line, after having adjusted the logging. And lo and behold, they also appear there.
>  
> {code:java}
> 2021-08-18 17:39:22,936 DEBUG [org.apache.activemq.artemis.core.protocol.core.ServerSessionPacketHandler] Sending exception to client: ActiveMQQueueExistsException[errorType=QUEUE_EXISTS message=AMQ229018: Binding already exists LocalQueueBinding [address=Test.queue, queue=QueueImpl[name=Test.queue, postOffice=PostOfficeImpl [server=ActiveMQServerImpl::serverUUID=abc2a8cb-f37b-11eb-bfbc-60f2623f9c33], temp=false]@7ad901eb, filter=null, name=Test.queue, clusterName=Test.queueabc2a8cb-f37b-11eb-bfbc-60f2623f9c33]]
> 	at org.apache.activemq.artemis.core.postoffice.impl.SimpleAddressManager.addBinding(SimpleAddressManager.java:91) [artemis-server-2.17.0.jar:2.17.0]
> 	at org.apache.activemq.artemis.core.postoffice.impl.WildcardAddressManager.addBinding(WildcardAddressManager.java:95) [artemis-server-2.17.0.jar:2.17.0]
> 	at org.apache.activemq.artemis.core.postoffice.impl.PostOfficeImpl.addBinding(PostOfficeImpl.java:873) [artemis-server-2.17.0.jar:2.17.0]
> ...
> {code}
> To me, this seems like just noise of the type that makes you wonder, even though they are emitted on debug.
> It seems like a similar situation have been tackled earlier, in ARTEMIS-1707, but that was ActiveMQAddressExistsException, while this is ActiveMQQueueExistsException.
> Here's a class that exhibits the situation. Note that it evidently works just fine, both of the consumers receiving exactly half of the messages:
>  
> {code:java}
> import java.util.concurrent.CountDownLatch;
> import java.util.concurrent.TimeUnit;
> import javax.jms.Connection;
> import javax.jms.Message;
> import javax.jms.MessageConsumer;
> import javax.jms.MessageProducer;
> import javax.jms.Queue;
> import javax.jms.Session;
> import javax.jms.TextMessage;
> import org.apache.activemq.artemis.api.core.QueueConfiguration;
> import org.apache.activemq.artemis.api.core.RoutingType;
> import org.apache.activemq.artemis.api.core.SimpleString;
> import org.apache.activemq.artemis.core.config.Configuration;
> import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
> import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
> import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
> import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
> import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
> public class Test_MatsTestBroker {
>     // @Test
>     public void test() throws Exception {
>         String brokerUrl = "vm://test";
> //        String brokerUrl = "tcp://localhost:61616";
>         EmbeddedActiveMQ broker = brokerUrl.startsWith("vm")
>                 ? createArtemisBroker(brokerUrl)
>                 : null;
>         ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
>         Connection connection = connectionFactory.createConnection();
>         int numberOfMessages = 50;
>         CountDownLatch countDownLatch = new CountDownLatch(numberOfMessages);
>         Thread thread1 = new Thread(() -> consumer(connection, countDownLatch), "EndreXY 1");
>         Thread thread2 = new Thread(() -> consumer(connection, countDownLatch), "EndreXY 2");
>         thread1.start();
>         thread2.start();
>         connection.start();
>         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
>         Queue queue = session.createQueue("Test.queue");
>         MessageProducer producer = session.createProducer(queue);
>         for (int i = 0; i < 50; i++) {
>             TextMessage textMessage = session.createTextMessage("Message " + i);
>             producer.send(textMessage);
>         }
>         boolean await = countDownLatch.await(10, TimeUnit.SECONDS);
>         // Assert.assertTrue("Counted down correctly, received all messages", await);
>         connection.close();
>         if (broker != null) {
>             broker.stop();
>         }
>     }
>     private void consumer(Connection con, CountDownLatch countDownLatch) {
>         try {
>             Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
>             Queue queue = session.createQueue("Test.queue");
>             MessageConsumer consumer = session.createConsumer(queue);
>             while (true) {
>                 Message msg = consumer.receive(10_000);
>                 countDownLatch.countDown();
>                 if (msg instanceof TextMessage) {
>                     TextMessage txtMsg = (TextMessage) msg;
>                     System.out.println("Received message!" + txtMsg.getText());
>                 }
>                 if (msg == null) {
>                     break;
>                 }
>             }
>         }
>         catch (Exception e) {
>             System.out.println("Got exception when receiving.");
>         }
>     }
>     public static void main(String... args) throws Exception {
>         System.setProperty(MatsTestBroker.SYSPROP_MATS_TEST_BROKER,
>                 MatsTestBroker.SYSPROP_MATS_TEST_BROKER_VALUE_ARTEMIS);
>         new Test_MatsTestBroker().test();
>         System.out.println("Done!");
>     }
>     public static EmbeddedActiveMQ createArtemisBroker(String brokerUrl) {
>         Configuration config = new ConfigurationImpl();
>         try {
>             config.setSecurityEnabled(false);
>             config.setPersistenceEnabled(false);
>             config.addAcceptorConfiguration("in-vm", brokerUrl);
>             // :: Configuring for separate DLQs, with pattern (which is default) "DLQ." as prefix.
>             config.addAddressesSetting("#",
>                     new AddressSettings()
>                             .setDeadLetterAddress(SimpleString.toSimpleString("DLQ"))
>                             .setMaxDeliveryAttempts(3)
>                             .setAutoCreateQueues(true) // default true
>                             .setAutoCreateAddresses(true) // default true
>                             .setAutoCreateDeadLetterResources(true) // CHANGED! default false
>                             .setDeadLetterQueuePrefix(SimpleString.toSimpleString("DLQ.")) // default "DLQ."
>                             .setDeadLetterQueueSuffix(SimpleString.toSimpleString("")) // default ""
>                             .setExpiryAddress(SimpleString.toSimpleString("ExpiryQueue")));
>             // :: This is just trying to emulate the default config from default broker.xml - inspired by Spring
>             // Boot which also got problems with default config in embedded mode being a tad lacking.
>             // https://github.com/spring-projects/spring-boot/pull/12680/commits/a252bb52b5106f3fec0d3b2b157507023aa04b2b
>             config.addAddressConfiguration(
>                     new CoreAddressConfiguration()
>                             .setName("DLQ")
>                             .addRoutingType(RoutingType.ANYCAST)
>                             .addQueueConfiguration(new QueueConfiguration("DLQ")
>                                     .setRoutingType(RoutingType.ANYCAST)));
>             config.addAddressConfiguration(
>                     new CoreAddressConfiguration()
>                             .setName("ExpiryQueue")
>                             .addRoutingType(RoutingType.ANYCAST)
>                             .addQueueConfiguration(new QueueConfiguration("ExpiryQueue")
>                                     .setRoutingType(RoutingType.ANYCAST)));
>         }
>         catch (Exception e) {
>             throw new AssertionError("Can't config the Artemis Configuration.", e);
>         }
>         EmbeddedActiveMQ server = new EmbeddedActiveMQ();
>         server.setConfiguration(config);
>         try {
>             server.start();
>         }
>         catch (Exception e) {
>             throw new AssertionError("Can't start the Artemis Broker.", e);
>         }
>         return server;
>     }
> }
> {code}
>  
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)