If there's a "start" operation on the connection, a client on that connection 
shouldn't start prefetching before that, IMO. Prefetch starts the expiration 
clock on the server for locks and depending on how the app does its setup and 
whether starting depends on user action, the client might silently drain a 
queue here, including eating up several redeliveries. 

-----Original Message-----
From: Robbie Gemmell [mailto:[email protected]] 
Sent: Tuesday, September 19, 2017 3:59 PM
To: [email protected]
Subject: Re: JMS message consumer behavior

On 19 September 2017 at 13:10, Clemens Vasters <[email protected]> 
wrote:
> This may be my ignorance of JMS details, but why does a Qpid JMS consumer go 
> off and happily prefetch messages when its associated Session/Connection 
> hasn't even been start()'ed yet?
>

Mainly its just 'because it does', i.e. it doesn't have any specific smarts in 
there to delay it. There are actually some advantages to doing that, and some 
downsides.

As Rob said, JMS doesnt speak to this at all, prefetching isn't something it 
addresses, so its just an implementation detail as far as thats concerned.

> I just got misled by the trace output into believing that my app code's 
> receive/callback usage was wrong.

Assuming you wanted to received messages with the Consumer you created, it was 
actually wrong in that you had any such usage without calling start(), but I 
can see what you are saying, the logging is speaking to details of its internal 
operation but if you thought it was really describing handing messages to the 
application it could mislead.

>
> Here:
>
> Connection connection = cf.createConnection(csb.getSasKeyName(), 
> csb.getSasKey()); // Create Session, no transaction, client ack 
> Session session = connection.createSession(false, 
> Session.CLIENT_ACKNOWLEDGE); // Create consumer MessageConsumer 
> consumer = session.createConsumer(queue); 
> consumer.setMessageListener(message -> {
>     try {
>         // receives message is passed to callback
>         logger.info(String.format("Received message %d with sq#: %s",
>                 totalReceived.incrementAndGet(), message.getJMSMessageID()));
>         message.acknowledge();
>     } catch (Exception e) {
>         logger.error(e);
>     }
> });
> //connection.start();
> If I just let the app spin after this, it'll start logging prefetch 
> events
>
> ...
> 2017-09-19 14:04:42,515 [windows.net:-1]] - TRACE AmqpProvider                
>    - New Proton Event: DELIVERY
> 2017-09-19 14:04:42,515 [windows.net:-1]] - TRACE AmqpConsumer                
>    - AmqpConsumer { ID:fce87003-90ac-4fb9-8e83-fdb4cd975a6a:2:1:1 } has 
> incoming Message(s).
> 2017-09-19 14:04:42,517 [windows.net:-1]] - DEBUG AmqpConsumer                
>    - Dispatching received message: JmsInboundMessageDispatch { sequence = 1, 
> messageId = ID:21a39efc-8501-45e8-8c67-d3483ca03874:1:1:1-5, consumerId = 
> ID:fce87003-90ac-4fb9-8e83-fdb4cd975a6a:2:1:1 }
> ...
>
> But my callback is never invoked.
>
> Once I call start() on the connection (which I now do right after creating 
> the connection in my code), the callback does get invoked.
>
> That is quite confusing.

To be fair, that would happen regardless as it is behaviour JMS does dictate, 
you just wouldnt have seen any logging in the alternative case, and with more 
familiarity of the protocol spec would perhaps have figured it out a little 
easier. Most folks won't understand the spec enough to get that, or maybe turn 
up the logging at all, and will just be left with the silly JMS behaviour and 
resort to google/stackoverflow for the age old 'you need to start the 
connection' answer. JMSContext from JMS 2.0 auto-starts things by default to 
avoid such issues.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected] For additional 
commands, e-mail: [email protected]

Reply via email to