Uploaded image for project: 'Qpid JMS'
  1. Qpid JMS
  2. QPIDJMS-349

JMS transactions should fail when messages are published into non-existing destinations using anonymous producer

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 0.24.0, 0.25.0, 0.26.0, 0.27.0
    • None
    • qpid-jms-client
    • None

    Description

      The current client implementation allows to commit JMS transaction successfully, when message is published into non-existing destination over anonymous relay within a transaction. Though, only part of the messages within the transaction reaches their destinations. This situation can potentially result in message loss, as the client application would consider such transaction successful. The exception "javax.jms.InvalidDestinationException: Unknown destination 'nonExistingQueue' [condition = amqp:not-found]" is reported into ExceptionListener but client allows to commit the JMS transaction successfully. If no ExceptionListener is set, the exception is logged.

      It seems, the JMS client is failing to deliver JMS transaction contract, when publishing messages using anonymous producer. Atomicity (all or nothing) is not guaranteed in this case.

      The following code snippet demonstrate the problem:

      try( Connection connection =
      connectionFactory.createConnection(username, password))
      {
          Session session = connection.createSession(true,
      Session.SESSION_TRANSACTED);
          MessageProducer messageProducer = session.createProducer(null);
          Queue nonExistingQueue = session.createQueue("nonExistingQueue");
          messageProducer.send(nonExistingQueue,
      session.createTextMessage("testMessage"));
          session.commit();
      }
      

      From AMQP point of view both broker and client behaviours are fully AMQP compliant.
      The implementations conform the requirements of specification "Using the Anonymous Terminus for Message Routing" [1] as per section "2.2.2 Routing Errors" :

      If the source of the link supports the rejected outcome, and the message has not already been settled by the sender, then the routing node MUST reject the message.

      On attach, the client specifies the following outcomes on the source:

      outcomes=[amqp:accepted:list,amqp:rejected:list,amqp:released:list,amqp:modified:list]}
      

      When Broker receives a message for non-existing destination, the anonymous
      relay implementation returns rejected outcome, as 'rejected' outcome is in the list of source supported outcomes. The Broker replies with settled disposition having rejected outcome and error 'not-found'. Here is an example of disposition

      Disposition{role=receiver,first=1,last=1,settled=true,state=TransactionalState{txnId=\x00\x00\x00\x00,outcome=Rejected{error=Error{condition=not-found,description=Unknown
      destination 'nonExistingQueue'}}}}
      

      Thus, the AMQP transaction can be committed successfully in this case, as the message is settled and has final outcome.

      I am wondering whether a better approach would be to stop supporting "rejected" outcome for anonymous producer on transacted sessions. That would cause the broker to detach the link with an error and mark the transaction as rollback only. Thus, any commit issued from the client will fail in this case.

      [1] https://www.oasis-open.org/apps/org/workgroup/amqp/download.php/61723/amqp-anonterm-v1.0-wd03.pdf

      Attachments

        Activity

          People

            Unassigned Unassigned
            orudyy Alex Rudyy
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: