Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
0.24.0, 0.25.0, 0.26.0, 0.27.0
-
None
-
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