You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by Андрей <x0...@gmail.com> on 2023/11/29 09:58:48 UTC

JMS API with client acknowledgement issue

Hi Team,

I am currently using "artemis-jakarta-client" 2.31.2 version

I've stumbled into an issue with client acknowledge mode when using JMS
API. Here's an example:


        try (var factory = new ActiveMQConnectionFactory("<broker-url")) {
            try (var ctx = factory.createContext("<user>", "<password>",
JMSContext.CLIENT_ACKNOWLEDGE)) {
                var destination = ctx.createQueue("<destination>");
                try (var consumer = ctx.createConsumer(destination)) {
                    var message1 = consumer.receive(100000); // suppose
this call returns real message
                    var message2 = consumer.receive(100000); // suppose
this call times out, so NULL is returned
                    ctx.acknowledge(); // I'm expecting that message1 gets
acknowledged here, but it's not happening

                    /*
                    Do something here....
                     */

                }
            }
        }

The reason for ack not working is that the implementation of
"consumer.receive" method stores the latest returned value in JMSContext
for future usage in its "acknowledge" method.
This happens regardless if the value is null or not. So in case latest call
returns null, all the previous messages get lost and never acked.

This seem like a defect. Am I right?

Thanks in advance

Re: JMS API with client acknowledgement issue

Posted by Justin Bertram <jb...@apache.org>.
FYI - the fix for this issue has been merged. It will be available in
ActiveMQ Artemis 2.32.0.

Thanks again for the report!


Justin

On Thu, Nov 30, 2023 at 11:46 AM Justin Bertram <jb...@apache.org> wrote:

> I've created ARTEMIS-4520 [1] to deal with this. Thanks for reporting the
> issue!
>
>
> Justin
>
> [1] https://issues.apache.org/jira/browse/ARTEMIS-4520
>
> On Wed, Nov 29, 2023 at 4:08 AM Андрей <x0...@gmail.com> wrote:
>
>> Hi Team,
>>
>> I am currently using "artemis-jakarta-client" 2.31.2 version
>>
>> I've stumbled into an issue with client acknowledge mode when using JMS
>> API. Here's an example:
>>
>>
>>         try (var factory = new ActiveMQConnectionFactory("<broker-url")) {
>>             try (var ctx = factory.createContext("<user>", "<password>",
>> JMSContext.CLIENT_ACKNOWLEDGE)) {
>>                 var destination = ctx.createQueue("<destination>");
>>                 try (var consumer = ctx.createConsumer(destination)) {
>>                     var message1 = consumer.receive(100000); // suppose
>> this call returns real message
>>                     var message2 = consumer.receive(100000); // suppose
>> this call times out, so NULL is returned
>>                     ctx.acknowledge(); // I'm expecting that message1 gets
>> acknowledged here, but it's not happening
>>
>>                     /*
>>                     Do something here....
>>                      */
>>
>>                 }
>>             }
>>         }
>>
>> The reason for ack not working is that the implementation of
>> "consumer.receive" method stores the latest returned value in JMSContext
>> for future usage in its "acknowledge" method.
>> This happens regardless if the value is null or not. So in case latest
>> call
>> returns null, all the previous messages get lost and never acked.
>>
>> This seem like a defect. Am I right?
>>
>> Thanks in advance
>>
>

Re: JMS API with client acknowledgement issue

Posted by Justin Bertram <jb...@apache.org>.
I've created ARTEMIS-4520 [1] to deal with this. Thanks for reporting the
issue!


Justin

[1] https://issues.apache.org/jira/browse/ARTEMIS-4520

On Wed, Nov 29, 2023 at 4:08 AM Андрей <x0...@gmail.com> wrote:

> Hi Team,
>
> I am currently using "artemis-jakarta-client" 2.31.2 version
>
> I've stumbled into an issue with client acknowledge mode when using JMS
> API. Here's an example:
>
>
>         try (var factory = new ActiveMQConnectionFactory("<broker-url")) {
>             try (var ctx = factory.createContext("<user>", "<password>",
> JMSContext.CLIENT_ACKNOWLEDGE)) {
>                 var destination = ctx.createQueue("<destination>");
>                 try (var consumer = ctx.createConsumer(destination)) {
>                     var message1 = consumer.receive(100000); // suppose
> this call returns real message
>                     var message2 = consumer.receive(100000); // suppose
> this call times out, so NULL is returned
>                     ctx.acknowledge(); // I'm expecting that message1 gets
> acknowledged here, but it's not happening
>
>                     /*
>                     Do something here....
>                      */
>
>                 }
>             }
>         }
>
> The reason for ack not working is that the implementation of
> "consumer.receive" method stores the latest returned value in JMSContext
> for future usage in its "acknowledge" method.
> This happens regardless if the value is null or not. So in case latest call
> returns null, all the previous messages get lost and never acked.
>
> This seem like a defect. Am I right?
>
> Thanks in advance
>

Re: JMS API with client acknowledgement issue

Posted by Timothy Bish <ta...@gmail.com>.
On 11/30/23 12:22, Justin Bertram wrote:
> Tim, I think those are fair points. Ultimately I think the JavaDoc is
> relatively ambiguous, although I tend to favor your interpretation.
To be honest I don't think it is, just read the first sentence and then 
ignore the fluff following as that is mainly trying to explain how / why 
this method is meant to be used.  It exists mainly because you can now 
consume the messages via receive body calls which will never give you a 
message to call acknowledge on if using client acknowledge mode.
>
> What does the Qpid JMS client do in this case?
Qpid JMS has always handled this as a session level call and 
acknowledges as client ack would if message.acknowledge() were called.
>
> BTW, I looked through the Jakarta Messaging TCK source code and I don't see
> where this specific use-case is exercised.

That isn't terribly surprising given all the other cases the TCK doesn't 
check.


>
> Justin
>
> On Wed, Nov 29, 2023 at 3:58 PM Timothy Bish <ta...@gmail.com> wrote:
>
>> On 11/29/23 16:15, Justin Bertram wrote:
>>> It's not clear to me that this is a defect. The JavaDoc for
>>> JMSContext.acknowledge() [1] says (in part):
>>>
>>>> This method has identical behaviour to the acknowledge method on
>> Message.
>>> A client may individually acknowledge each message as it is consumed, or
>> it
>>> may choose to acknowledge messages as an application-defined group. In
>> both
>>> cases it makes no difference which of these two methods is used.
>>>
>>> If receive() returns a null Message Object you can't invoke acknowledge
>> on
>>> it. Therefore, whether you use JMSContext.acknowledge() or
>>> Message.acknowledge() the behavior will be identical - no message will be
>>> acknowledged.
>>>
>>> Also, it's worth noting that messages which are not acknowledged will not
>>> be lost. In most cases they will be redelivered or in some cases may be
>>> sent to a dead-letter address.
>> I believe you have skipped over the most important part of the API docs
>> for that method which is the first sentence which states:
>>
>> "Acknowledges all messages consumed by the JMSContext's session."
>>
>> That would imply it works on the session level regardless of any
>> successful (or not) calls to receive (or receiveBody which don't return
>> actual message objects) as it is meant to work against "all message
>> consumed by the JMSContext's session", not at the individual message
>> level which I'd guess is indeed why it was added to the "Simplified API"
>> as this would provide the entry point for  group acknowledge behavior
>> described in the text.
>>
>> A previously read message from the 'receive' API is in fact a consumed
>> message within the session regardless of whether the most recent call
>> returned a message.
>>
>>
>>> Justin
>>>
>>> [1]
>>>
>> https://docs.oracle.com/javaee/7/api/javax/jms/JMSContext.html#acknowledge--
>>> On Wed, Nov 29, 2023 at 4:08 AM Андрей <x0...@gmail.com> wrote:
>>>
>>>> Hi Team,
>>>>
>>>> I am currently using "artemis-jakarta-client" 2.31.2 version
>>>>
>>>> I've stumbled into an issue with client acknowledge mode when using JMS
>>>> API. Here's an example:
>>>>
>>>>
>>>>           try (var factory = new
>> ActiveMQConnectionFactory("<broker-url")) {
>>>>               try (var ctx = factory.createContext("<user>",
>> "<password>",
>>>> JMSContext.CLIENT_ACKNOWLEDGE)) {
>>>>                   var destination = ctx.createQueue("<destination>");
>>>>                   try (var consumer = ctx.createConsumer(destination)) {
>>>>                       var message1 = consumer.receive(100000); // suppose
>>>> this call returns real message
>>>>                       var message2 = consumer.receive(100000); // suppose
>>>> this call times out, so NULL is returned
>>>>                       ctx.acknowledge(); // I'm expecting that message1
>> gets
>>>> acknowledged here, but it's not happening
>>>>
>>>>                       /*
>>>>                       Do something here....
>>>>                        */
>>>>
>>>>                   }
>>>>               }
>>>>           }
>>>>
>>>> The reason for ack not working is that the implementation of
>>>> "consumer.receive" method stores the latest returned value in JMSContext
>>>> for future usage in its "acknowledge" method.
>>>> This happens regardless if the value is null or not. So in case latest
>> call
>>>> returns null, all the previous messages get lost and never acked.
>>>>
>>>> This seem like a defect. Am I right?
>>>>
>>>> Thanks in advance
>>>>
>> --
>> Tim Bish
>>
>>

-- 
Tim Bish


Re: JMS API with client acknowledgement issue

Posted by Justin Bertram <jb...@apache.org>.
Tim, I think those are fair points. Ultimately I think the JavaDoc is
relatively ambiguous, although I tend to favor your interpretation.

What does the Qpid JMS client do in this case?

BTW, I looked through the Jakarta Messaging TCK source code and I don't see
where this specific use-case is exercised.


Justin

On Wed, Nov 29, 2023 at 3:58 PM Timothy Bish <ta...@gmail.com> wrote:

> On 11/29/23 16:15, Justin Bertram wrote:
> > It's not clear to me that this is a defect. The JavaDoc for
> > JMSContext.acknowledge() [1] says (in part):
> >
> >> This method has identical behaviour to the acknowledge method on
> Message.
> > A client may individually acknowledge each message as it is consumed, or
> it
> > may choose to acknowledge messages as an application-defined group. In
> both
> > cases it makes no difference which of these two methods is used.
> >
> > If receive() returns a null Message Object you can't invoke acknowledge
> on
> > it. Therefore, whether you use JMSContext.acknowledge() or
> > Message.acknowledge() the behavior will be identical - no message will be
> > acknowledged.
> >
> > Also, it's worth noting that messages which are not acknowledged will not
> > be lost. In most cases they will be redelivered or in some cases may be
> > sent to a dead-letter address.
>
> I believe you have skipped over the most important part of the API docs
> for that method which is the first sentence which states:
>
> "Acknowledges all messages consumed by the JMSContext's session."
>
> That would imply it works on the session level regardless of any
> successful (or not) calls to receive (or receiveBody which don't return
> actual message objects) as it is meant to work against "all message
> consumed by the JMSContext's session", not at the individual message
> level which I'd guess is indeed why it was added to the "Simplified API"
> as this would provide the entry point for  group acknowledge behavior
> described in the text.
>
> A previously read message from the 'receive' API is in fact a consumed
> message within the session regardless of whether the most recent call
> returned a message.
>
>
> >
> > Justin
> >
> > [1]
> >
> https://docs.oracle.com/javaee/7/api/javax/jms/JMSContext.html#acknowledge--
> >
> > On Wed, Nov 29, 2023 at 4:08 AM Андрей <x0...@gmail.com> wrote:
> >
> >> Hi Team,
> >>
> >> I am currently using "artemis-jakarta-client" 2.31.2 version
> >>
> >> I've stumbled into an issue with client acknowledge mode when using JMS
> >> API. Here's an example:
> >>
> >>
> >>          try (var factory = new
> ActiveMQConnectionFactory("<broker-url")) {
> >>              try (var ctx = factory.createContext("<user>",
> "<password>",
> >> JMSContext.CLIENT_ACKNOWLEDGE)) {
> >>                  var destination = ctx.createQueue("<destination>");
> >>                  try (var consumer = ctx.createConsumer(destination)) {
> >>                      var message1 = consumer.receive(100000); // suppose
> >> this call returns real message
> >>                      var message2 = consumer.receive(100000); // suppose
> >> this call times out, so NULL is returned
> >>                      ctx.acknowledge(); // I'm expecting that message1
> gets
> >> acknowledged here, but it's not happening
> >>
> >>                      /*
> >>                      Do something here....
> >>                       */
> >>
> >>                  }
> >>              }
> >>          }
> >>
> >> The reason for ack not working is that the implementation of
> >> "consumer.receive" method stores the latest returned value in JMSContext
> >> for future usage in its "acknowledge" method.
> >> This happens regardless if the value is null or not. So in case latest
> call
> >> returns null, all the previous messages get lost and never acked.
> >>
> >> This seem like a defect. Am I right?
> >>
> >> Thanks in advance
> >>
>
> --
> Tim Bish
>
>

Re: JMS API with client acknowledgement issue

Posted by Timothy Bish <ta...@gmail.com>.
On 11/29/23 16:15, Justin Bertram wrote:
> It's not clear to me that this is a defect. The JavaDoc for
> JMSContext.acknowledge() [1] says (in part):
>
>> This method has identical behaviour to the acknowledge method on Message.
> A client may individually acknowledge each message as it is consumed, or it
> may choose to acknowledge messages as an application-defined group. In both
> cases it makes no difference which of these two methods is used.
>
> If receive() returns a null Message Object you can't invoke acknowledge on
> it. Therefore, whether you use JMSContext.acknowledge() or
> Message.acknowledge() the behavior will be identical - no message will be
> acknowledged.
>
> Also, it's worth noting that messages which are not acknowledged will not
> be lost. In most cases they will be redelivered or in some cases may be
> sent to a dead-letter address.

I believe you have skipped over the most important part of the API docs 
for that method which is the first sentence which states:

"Acknowledges all messages consumed by the JMSContext's session."

That would imply it works on the session level regardless of any 
successful (or not) calls to receive (or receiveBody which don't return 
actual message objects) as it is meant to work against "all message 
consumed by the JMSContext's session", not at the individual message 
level which I'd guess is indeed why it was added to the "Simplified API" 
as this would provide the entry point for  group acknowledge behavior 
described in the text.

A previously read message from the 'receive' API is in fact a consumed 
message within the session regardless of whether the most recent call 
returned a message.


>
> Justin
>
> [1]
> https://docs.oracle.com/javaee/7/api/javax/jms/JMSContext.html#acknowledge--
>
> On Wed, Nov 29, 2023 at 4:08 AM Андрей <x0...@gmail.com> wrote:
>
>> Hi Team,
>>
>> I am currently using "artemis-jakarta-client" 2.31.2 version
>>
>> I've stumbled into an issue with client acknowledge mode when using JMS
>> API. Here's an example:
>>
>>
>>          try (var factory = new ActiveMQConnectionFactory("<broker-url")) {
>>              try (var ctx = factory.createContext("<user>", "<password>",
>> JMSContext.CLIENT_ACKNOWLEDGE)) {
>>                  var destination = ctx.createQueue("<destination>");
>>                  try (var consumer = ctx.createConsumer(destination)) {
>>                      var message1 = consumer.receive(100000); // suppose
>> this call returns real message
>>                      var message2 = consumer.receive(100000); // suppose
>> this call times out, so NULL is returned
>>                      ctx.acknowledge(); // I'm expecting that message1 gets
>> acknowledged here, but it's not happening
>>
>>                      /*
>>                      Do something here....
>>                       */
>>
>>                  }
>>              }
>>          }
>>
>> The reason for ack not working is that the implementation of
>> "consumer.receive" method stores the latest returned value in JMSContext
>> for future usage in its "acknowledge" method.
>> This happens regardless if the value is null or not. So in case latest call
>> returns null, all the previous messages get lost and never acked.
>>
>> This seem like a defect. Am I right?
>>
>> Thanks in advance
>>

-- 
Tim Bish


Re: JMS API with client acknowledgement issue

Posted by Justin Bertram <jb...@apache.org>.
It's not clear to me that this is a defect. The JavaDoc for
JMSContext.acknowledge() [1] says (in part):

> This method has identical behaviour to the acknowledge method on Message.
A client may individually acknowledge each message as it is consumed, or it
may choose to acknowledge messages as an application-defined group. In both
cases it makes no difference which of these two methods is used.

If receive() returns a null Message Object you can't invoke acknowledge on
it. Therefore, whether you use JMSContext.acknowledge() or
Message.acknowledge() the behavior will be identical - no message will be
acknowledged.

Also, it's worth noting that messages which are not acknowledged will not
be lost. In most cases they will be redelivered or in some cases may be
sent to a dead-letter address.


Justin

[1]
https://docs.oracle.com/javaee/7/api/javax/jms/JMSContext.html#acknowledge--

On Wed, Nov 29, 2023 at 4:08 AM Андрей <x0...@gmail.com> wrote:

> Hi Team,
>
> I am currently using "artemis-jakarta-client" 2.31.2 version
>
> I've stumbled into an issue with client acknowledge mode when using JMS
> API. Here's an example:
>
>
>         try (var factory = new ActiveMQConnectionFactory("<broker-url")) {
>             try (var ctx = factory.createContext("<user>", "<password>",
> JMSContext.CLIENT_ACKNOWLEDGE)) {
>                 var destination = ctx.createQueue("<destination>");
>                 try (var consumer = ctx.createConsumer(destination)) {
>                     var message1 = consumer.receive(100000); // suppose
> this call returns real message
>                     var message2 = consumer.receive(100000); // suppose
> this call times out, so NULL is returned
>                     ctx.acknowledge(); // I'm expecting that message1 gets
> acknowledged here, but it's not happening
>
>                     /*
>                     Do something here....
>                      */
>
>                 }
>             }
>         }
>
> The reason for ack not working is that the implementation of
> "consumer.receive" method stores the latest returned value in JMSContext
> for future usage in its "acknowledge" method.
> This happens regardless if the value is null or not. So in case latest call
> returns null, all the previous messages get lost and never acked.
>
> This seem like a defect. Am I right?
>
> Thanks in advance
>