How to tell if a JMS Session is async

39 Views Asked by At

I need to write some code that only calls acknowledge if the session is synchronous because otherwise acknowledge throws a JMSCC0033 for not being able to call it against an async session (same as JMS Acknowledge Asynchronous Message) . However I cannot find a method or means to check the session itself. There is an internal implementation of isAsync, but nothing I can see externally. Would checking if there is a listener be enough? Am I totally missing something in the documentation?

This is library code, where the mode can be set via config, however I am fairly sure that it is ClientAcknowledge based on the user reports. This is a library that wants to clear all messages while closing, however runs into this exception periodically. From my decompiling the code I have come to the conclusion that it seems that there is no exposed way to check...which seems like a flaw since it can blow things up and has an internal mechanism to check it that seems easily exposable. Right now I am thinking I will have to just catch and swallow the exception...

1

There are 1 best solutions below

2
Justin Bertram On

You can use a session to create a Producer to send messages asynchronously or you can use a session to create a Consumer and register a MessageListener to receive messages asynchronously. However, there is no overall concept in JMS of a "sync" or "async" session.

To be clear, it's perfectly acceptable to invoke acknowledge() on the Message received by the onMessage() method of a MessageListener. Here's some sample code that works perfectly well with ActiveMQ Artemis:

ConnectionFactory cf = ...
Connection c = cf.createConnection();
Session s = c.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Destination q = s.createQueue("myQueue");
MessageConsumer mc = s.createConsumer(q);
CountDownLatch latch = new CountDownLatch(1);
c.start();
mc.setMessageListener(message -> {
   try {
      message.acknowledge();
      System.out.println("Message acknowledged!");
      latch.countDown();
   } catch (JMSException e) {
      throw new RuntimeException(e);
   }
});
MessageProducer mp = s.createProducer(q);
mp.send(s.createMessage());
latch.await(2, TimeUnit.SECONDS);

It will print:

Message acknowledged!

It's also worth keeping in mind that a JMS Session is not thread-safe so if you're accessing the same session from multiple threads concurrently then you're going to have problems.