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]
