Unable to receive message sent to acivemq by C# in Java - java

What I want to do is to send messages via Apache Activemq between C# app and Java app.
C#:
using (IConnection connection = factory.CreateConnection())
using (ISession session = connection.CreateSession())
{
IDestination destination = SessionUtil.GetDestination(session, "queue://ISI");
// Create a consumer and producer
using (IMessageProducer producer = session.CreateProducer(destination))
{
// Start the connection so that messages will be processed.
connection.Start();
ITextMessage request = session.CreateTextMessage(JsonConvert.SerializeObject(obj));
/*request.NMSCorrelationID = "abc";
request.Properties["NMSXGroupID"] = "cheese";
request.Properties["myHeader"] = "Cheddar";*/
producer.Send(request);
return request;
}
}
Java:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(isiProperties.getMqUrl());
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("ISI");
MessageConsumer consumer = session.createConsumer(destination);
Message message = consumer.receive();
if(message instanceof TextMessage) {
try {
String text = ((TextMessage) message).getText();
ObjectMapper mapper = new ObjectMapper();
StatusChangeMessage obj = mapper.readValue(text, StatusChangeMessage.class);
if (obj instanceof StatusChangeMessage) {
StatusChangeMessage received = (StatusChangeMessage) obj;
Order order = orderRepository.findOne(received.getOrderId());
order.setStatus(received.getStatus());
orderRepository.saveAndFlush(order);
}
} catch(JMSException e) {
} catch(IOException e) {
}
}
The C# app correctly sends messages (it is visible in activemq admin interface) but there are no active subscribers (Java app should do that). Do you see anything wrong here?
Basically, breakpoint on if(message instanceof TextMessage) { does not get executed.

I have finally found a solutioin. It was two-steps problem. Firstly, Windows firewall influenced activemq. Secondly, client library probably didn't fully match to the server. Problem finally gone after downgrading server to 5.8.0.

Related

Why does my JMS client not consume messages from the Topic?

I have ActiveMQ running on the localhost using the default port, 61616. I put some messages in a Topic called topic.STUDENTS. I have a client program that I am trying to use to read the messages in the Topic. Here is the main part of the program that does not work as expected. I was expecting to get some of the message back but instead I just receive null.
public void receiveMessages() throws URISyntaxException, JMSException, Exception {
try {
//Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
//Create a session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//Create the destination (Topic or Queue)
Destination destination = session.createTopic("topic.STUDENTS");
//Create a MessageConsumer from the Session to the Topic or Queue
MessageConsumer consumer = session.createConsumer(destination);
//Wait for a message
Message message = consumer.receive(1000);
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
System.out.println("Received: " + text);
} else {
System.out.println("Received: " + message);
}
consumer.close();
session.close();
connection.close();
} catch(Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
This code basically apes the code from ActiveMQ 'Hello World' example: http://activemq.apache.org/hello-world.html
Does anyone know why I do not receive any messages from the Topic? Here is one message that is in the Topic that I can see through the ./activemq browse topic.STUDENTS command:
JMS_BODY_FIELD:JMSText = Invention-my-dear-friends-is-93%-perspiration-6%-electricity
JMS_HEADER_FIELD:JMSExpiration = 0
JMS_HEADER_FIELD:JMSMessageID = ID:user-thinkpad-335i-59919-1457977678059-1:1:1:1:3
JMS_HEADER_FIELD:JMSPriority = 4
JMS_HEADER_FIELD:JMSDestination = topic.STUDENTS
JMS_HEADER_FIELD:JMSTimestamp = 1457977678409
JMS_HEADER_FIELD:JMSRedelivered = false
JMS_HEADER_FIELD:JMSDeliveryMode = persistent
Topics do not retain messages by default, so if you start the consumer after you've produced the messages then any message that was sent before the consumer arrived is gone. If you want to consume messages that were produced while your consumer was offline then you need to use a Queue or register a durable Topic subscriber on the Topic prior to producing the messages.

Java Producer, Stompy Python Consumer, ActiveMQ

I have a java ActiveMQ producer which produces Integer messages into an ObjectMessage instance.
On the python side, I use stomp python for listening on the queue. However, I receive empty message body although all the headers are received right.
Moreover, if I change the message type to TextMessage on the java side, I get correct message on python-consumer side.
I have also tried with PyactiveMQ but with the same effect
Any suggestions will be appreciated!!!
EDIT: Here is a boilerplate java producer code and python subscriber code which i wrote to test stomp on python
public class App
{
Connection conn;
Session session;
MessageProducer producer;
public void registerPublisher(String queueName, String url) throws JMSException {
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("system", "manager" ,url);
conn = cf.createConnection();
conn.start();
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queueName);
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
}
public void send(int c) {
for (int i=0; i<c; ++i) {
try {
TextMessage tm = session.createTextMessage(new Integer(i).toString());
// ObjectMessage tm = session.createObjectMessage();
producer.send(tm);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
public static void main(String []arg) {
App app = new App();
try {
app.registerPublisher(arg[0], arg[1]);
System.out.println(app.session);
} catch (JMSException e) {
e.printStackTrace();
}
app.send(1000);
}
}
And Python Stomp listener
import time
import sys
import logging
import stomp
from stomp import ConnectionListener
queuename = sys.argv[1]
logging.basicConfig( level=logging.DEBUG)
class MyListener(ConnectionListener):
def on_error(self, headers, message):
print 'received an error %s' % message
def onMessage(self, headers, message):
print headers
print str(message)
print type(message)
print 'received a message ...%s...' % message
conn = stomp.Connection([('localhost', 61613)])
conn.set_listener('', MyListener())
conn.start()
conn.connect()
conn.subscribe(destination='/queue/'+queuename, ack='auto')
while 1:
time.sleep(2)
In order to send an receive ObjectMessage types over Stomp you need to use the message transformation feature of ActiveMQ to have the object payload delivered in a form a STOMP client can understand. ActiveMQ provides XML and JSON transformation support out of the box however you can add your own transformer to get whatever format you want on the content.
PROBLEM: Sending ObjectMessage from a java producer to ActiveMQ Broker. Stomp Python consumer client was getting empty message body
SOLUTION: Use transformation header while subscribing to the activemq broker in the python client,
for example:
connection.subscribe(destination='/queue/'+queuename, ack='auto', transformation="jms-json")
So that the broker knows in what form the message is to be sent to the stomp client

ACTIVEMQ- publisher subscriber hello world example

There are two programs: subscriber and publisher...
Subscriber is able to put the message onto the topic and the message is sent successfully.
When I check the activemq server on my browser it shows 1 msg enqueued . But when I run the consumer code, it is not receiving the message
Here is the producer code:
import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class producer {
private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
// JMS messages are sent and received using a Session. We will
// create here a non-transactional session object. If you want
// to use transactions you should set the first parameter to 'true'
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("testt");
MessageProducer producer = session.createProducer(topic);
// We will send a small text message saying 'Hello'
TextMessage message = session.createTextMessage();
message.setText("HELLO JMS WORLD");
// Here we are sending the message!
producer.send(message);
System.out.println("Sent message '" + message.getText() + "'");
connection.close();
}
}
After I run this code the output at the console is:
26 Jan, 2012 2:30:04 PM org.apache.activemq.transport.failover.FailoverTransport doReconnect
INFO: Successfully connected to tcp://localhost:61616
Sent message 'HELLO JMS WORLD'
And here is the consumer code:
import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class consumer {
// URL of the JMS server
private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
// Name of the topic from which we will receive messages from = " testt"
public static void main(String[] args) throws JMSException {
// Getting JMS connection from the server
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("testt");
MessageConsumer consumer = session.createConsumer(topic);
MessageListener listner = new MessageListener() {
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("Received message"
+ textMessage.getText() + "'");
}
} catch (JMSException e) {
System.out.println("Caught:" + e);
e.printStackTrace();
}
}
};
consumer.setMessageListener(listner);
connection.close();
}
}
After I run this code it doesnt show anything.
Can someone help to me to overcome this problem?
Your issue is that your consumer is running and then shutting down immediately.
Try adding this into your consumer:
consumer.setMessageListener(listner);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
connection.close();
This will wait until you hit a key before stopping.
Other things to consider:
Use a finally block for the close
Java naming conventions encourage using uppercase for the first letter of a class
The main problem (besides the app closing down to quickly) is that you are sending to a Topic. Topics don't retain messages so if you run your application that produces and then run the consumer, the consumer won't receive anything because it was not subscribed to the topic at the time the message was sent. If you fix the shutdown issue and then run the consumer in one terminal and then run the producer you should then see the message received by your consumer. If you want message retention then you need to use a Queue which will hold onto the message until someone consumes it.
Your producer class is correct. It runs smoothly.
But, your consumer is incorrect & you have to modify it.
First, add setClientID("any_string_value") after creating connection object;
eg: Connection connection = connectionFactory.createConnection();
// need to setClientID value, any string value you wish
connection.setClientID("12345");
secondly, use createDurableSubscriber() method instead of createConsumer() for transmitting message via topic.
MessageConsumer consumer = session.createDurableSubscriber(topic,"SUB1234");
Here is the modified comsumer class:
package mq.test;
import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class consumer {
// URL of the JMS server
private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
// Name of the topic from which we will receive messages from = " testt"
public static void main(String[] args) throws JMSException {
// Getting JMS connection from the server
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
// need to setClientID value, any string value you wish
connection.setClientID("12345");
try{
connection.start();
}catch(Exception e){
System.err.println("NOT CONNECTED!!!");
}
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("test_data");
//need to use createDurableSubscriber() method instead of createConsumer() for topic
// MessageConsumer consumer = session.createConsumer(topic);
MessageConsumer consumer = session.createDurableSubscriber(topic,
"SUB1234");
MessageListener listner = new MessageListener() {
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("Received message"
+ textMessage.getText() + "'");
}
} catch (JMSException e) {
System.out.println("Caught:" + e);
e.printStackTrace();
}
}
};
consumer.setMessageListener(listner);
//connection.close();
}
}
Now, your code will run successfully.
just some:
work with a queue not a topic. messages in topics will be discarded when no consumer is available, they are NOT persistend.
add connection.start() after setting the message listener. you should start a connection when all consumers/producers are properly set up.
wait some time before before closing the connection again.
the topic will probably be your most important source of failure.

Slow HornetQ Producer when Queue is persistent

I have tried with Persistent Queue in horntQ. I have made two separate examples (Producer, Consumer). My consumer is working well but the Producer is taking too much time to finish sending message. I have run both separately as well as together. What could be the problem?
my code is:
public class HornetProducer implements Runnable{
Context ic = null;
ConnectionFactory cf = null;
Connection connection = null;
Queue queue = null;
Session session = null;
MessageProducer publisher = null;
TextMessage message = null;
int messageSent=0;
public synchronized static Context getInitialContext()throws javax.naming.NamingException {
Properties p = new Properties( );
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES," org.jboss.naming:org.jnp.interfaces");
p.put(Context.PROVIDER_URL, "jnp://localhosts:1099");
return new javax.naming.InitialContext(p);
}
public HornetProducer()throws Exception{
ic = getInitialContext();
cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
queue = (Queue)ic.lookup("queue/testQueue2");
connection = cf.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
publisher = session.createProducer(queue);
connection.start();
}
public void publish(){
try{
message = session.createTextMessage("Hello!");
System.out.println("StartDate: "+new Date());
for(int i=0;i<10000;i++){
messageSent++;
publisher.send(message);
}
System.out.println("EndDate: "+new Date());
}catch(Exception e){
System.out.println("Exception in Consume: "+ e.getMessage());
}
}
public void run(){
publish();
}
public static void main(String[] args) throws Exception{
new HornetProducer().publish();
}
}
You are sending these messages persistently, and non transactionally. What means, each message sent has to be completed individually.
That means for each message you send, you have to make a network round trip to the server, and wait it finish persistency before you can send another message.
If you had multiple producers on this situation, hornetq would batch both producers and you would save a lot of time. (i.e. the server will batch many write requests).
If you want to speed up the sending of a single producer, you should use transactions probably.
for example:
I - Change your session to transactioned:
session = connection.createSession(true, Session.SESSION_TRANSACTIONED);
II - commit every N messages:
for(int i=0;i<10000;i++){
messageSent++;
publisher.send(message);
if (messageSent % 1000 == 0) session.commit();
}
session.commit();
You could also disable sync on Persistent messages. (Sending them asynchronously).

Signal a rollback from a JMS MessageListener

I've been working with JMS and ActiveMQ. Everything is working wonders. I am not using spring, nor can I.
The interface javax.jms.MessageListener has only one method, onMessage. From within a implementation, there is a chance an exception will be thrown. If in fact an exception gets thrown, then I say the message wasn't properly processed and needs to be re-tried. So, I need ActiveMQ to wait for a little while and then, retry. i.e. I need the thrown exception to rollback the JMS transaction.
How can I accomplish such a behaviour?
Maybe there is some configuration in ActiveMQ I wasn't able to find.
Or... maybe could do away with registering MessageListeners to consumers and consume the messages myself, in a a loop like:
while (true) {
// ... some administrative stuff like ...
session = connection.createSesstion(true, SESSION_TRANSACTED)
try {
Message m = receiver.receive(queue, 1000L);
theMessageListener.onMessage(m);
session.commit();
} catch (Exception e) {
session.rollback();
Thread.sleep(someTimeDefinedSomewhereElse);
}
// ... some more administrative stuff
}
in a couple of threads, instead of registering the listener.
Or... I could somehow decorate/AOP/byte-manipulate the MessageListeners to do this themselves.
What route would you take and why?
note: I don't have full control over the MessageListeners code.
EDIT
A test for proof of concept:
#Test
#Ignore("Interactive test, just a proof of concept")
public void transaccionConListener() throws Exception {
final AtomicInteger atomicInteger = new AtomicInteger(0);
BrokerService brokerService = new BrokerService();
String bindAddress = "vm://localhost";
brokerService.addConnector(bindAddress);
brokerService.setPersistenceAdapter(new MemoryPersistenceAdapter());
brokerService.setUseJmx(false);
brokerService.start();
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(bindAddress);
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setInitialRedeliveryDelay(500);
redeliveryPolicy.setBackOffMultiplier(2);
redeliveryPolicy.setUseExponentialBackOff(true);
redeliveryPolicy.setMaximumRedeliveries(2);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
activeMQConnectionFactory.setUseRetroactiveConsumer(true);
activeMQConnectionFactory.setClientIDPrefix("ID");
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(activeMQConnectionFactory);
pooledConnectionFactory.start();
Connection connection = pooledConnectionFactory.createConnection();
Session session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
Queue helloQueue = session.createQueue("Hello");
MessageConsumer consumer = session.createConsumer(helloQueue);
consumer.setMessageListener(new MessageListener() {
#Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
switch (atomicInteger.getAndIncrement()) {
case 0:
System.out.println("OK, first message received " + textMessage.getText());
message.acknowledge();
break;
case 1:
System.out.println("NOPE, second must be retried " + textMessage.getText());
throw new RuntimeException("I failed, aaaaah");
case 2:
System.out.println("OK, second message received " + textMessage.getText());
message.acknowledge();
}
} catch (JMSException e) {
e.printStackTrace(System.out);
}
}
});
connection.start();
{
// A client sends two messages...
Connection connection1 = pooledConnectionFactory.createConnection();
Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection1.start();
MessageProducer producer = session1.createProducer(helloQueue);
producer.send(session1.createTextMessage("Hello World 1"));
producer.send(session1.createTextMessage("Hello World 2"));
producer.close();
session1.close();
connection1.stop();
connection1.close();
}
JOptionPane.showInputDialog("I will wait, you watch the log...");
consumer.close();
session.close();
connection.stop();
connection.close();
pooledConnectionFactory.stop();
brokerService.stop();
assertEquals(3, atomicInteger.get());
}
If you want to use SESSION_TRANSACTED as your acknowledgement mode, then you need to setup a RedeliveryPolicy on your Connection/ConnectionFactory. This page on ActiveMQ's website also contains some good info for what you might need to do.
Since you aren't using Spring, you can setup a RedeliveryPolicy with something similar to the following code (taken from one of the above links):
RedeliveryPolicy policy = connection.getRedeliveryPolicy();
policy.setInitialRedeliveryDelay(500);
policy.setBackOffMultiplier(2);
policy.setUseExponentialBackOff(true);
policy.setMaximumRedeliveries(2);
Edit
Taking your code snippet added to the answer, the following shows how this works with transactions. Try this code with the Session.rollback() method commented out and you'll see that using SESION_TRANSACTED and Session.commit/rollback works as expected:
#Test
public void test() throws Exception {
final AtomicInteger atomicInteger = new AtomicInteger(0);
BrokerService brokerService = new BrokerService();
String bindAddress = "vm://localhost";
brokerService.addConnector(bindAddress);
brokerService.setPersistenceAdapter(new MemoryPersistenceAdapter());
brokerService.setUseJmx(false);
brokerService.start();
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(bindAddress);
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setInitialRedeliveryDelay(500);
redeliveryPolicy.setBackOffMultiplier(2);
redeliveryPolicy.setUseExponentialBackOff(true);
redeliveryPolicy.setMaximumRedeliveries(2);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
activeMQConnectionFactory.setUseRetroactiveConsumer(true);
activeMQConnectionFactory.setClientIDPrefix("ID");
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(activeMQConnectionFactory);
pooledConnectionFactory.start();
Connection connection = pooledConnectionFactory.createConnection();
final Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Queue helloQueue = session.createQueue("Hello");
MessageConsumer consumer = session.createConsumer(helloQueue);
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
switch (atomicInteger.getAndIncrement()) {
case 0:
System.out.println("OK, first message received " + textMessage.getText());
session.commit();
break;
case 1:
System.out.println("NOPE, second must be retried " + textMessage.getText());
session.rollback();
throw new RuntimeException("I failed, aaaaah");
case 2:
System.out.println("OK, second message received " + textMessage.getText());
session.commit();
}
} catch (JMSException e) {
e.printStackTrace(System.out);
}
}
});
connection.start();
{
// A client sends two messages...
Connection connection1 = pooledConnectionFactory.createConnection();
Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection1.start();
MessageProducer producer = session1.createProducer(helloQueue);
producer.send(session1.createTextMessage("Hello World 1"));
producer.send(session1.createTextMessage("Hello World 2"));
producer.close();
session1.close();
connection1.stop();
connection1.close();
}
JOptionPane.showInputDialog("I will wait, you watch the log...");
consumer.close();
session.close();
connection.stop();
connection.close();
pooledConnectionFactory.stop();
assertEquals(3, atomicInteger.get());
}
}
You need to set the acknowledgment mode to Session.CLIENT_ACKNOWLEDGE, the client acknowledges a consumed message by calling the message's acknowledge method.
QueueSession session = connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
Then, after processing the message to need to call the Message.acknowledge() method in order to remove that message.
Message message = ...;
// Processing message
message.acknowledge();
A little late, but here goes -
I would not use a MessageListener but rather a global pools to manage listening and processing.
ListeningPool -> listener -> submit processing task -> ProcessingPool -> execute and acknowledge or close without acknowledgment.
Maintain 2 thread pools, one for listeners and one for processors.
Have a listening Runnable implementation that listens to a queue in a while true loop, and consumer.receive(timeout) method. In the finally block, close connection, session and consumer if there was no message received. If a message is received, submit a task to processing pool with all the conn, session, message and consumer arguments.
Have a processing implementation that takes in the message, connection, session and consumer. Do your processing and acknowledge if all ok. If not, close without acknowledgement. This would trigger a redelivery according to your server's redelivery policy.
Initialize your listening pool with all the Listener Tasks, listening for messages, each for one queue. Initialize your processing pool with parameters acceptable to your application runtime.
public class CustomMessageListener implements Runnable {
private ConnectionFactory connectionFactory;
private MessageProcessor processor;
private long backOff;
private boolean stopped = false;
private Executor processPool;
public CustomMessageListener(ConnectionFactory connectionFactory,
long backOff, MessageProcessor processor, Executor processPool) {
this.connectionFactory = connectionFactory;
this.backOff = backOff;
this.processor = processor;
this.processPool = processPool;
}
#Override
public void run() {
while (!stopped) {
listen();
}
}
public void stop() {
this.stopped = true;
}
public void listen() {
Connection c = null;
Session s = null;
MessageConsumer consumer = null;
boolean received = false;
try {
c = connectionFactory.createConnection();
s = c.createSession(false, Session.CLIENT_ACKNOWLEDGE);
consumer = s.createConsumer(...);
Message message = consumer.receive(backOff); // waits maximum backOff ms for a message
if (message != null) {
received = true;
// submit a task to processing pool...
executor.submit(processor.process(message, s, consumer, c));
}
} catch (JMSException ex) {
// log your exception
} finally {
if (!received) {
// close conn, session, consumer
}
}
}
}
public class MessageProcessor {
public Runnable process(Message msg, Session s, MessageConsumer consumer, Connection conn) {
return () - > {
try {
//do your processing
msg.acknowledge(); // done
} catch (JMSException ex) {
// log your exception
} finally {
// close your resources
}
};
}
}
You can call stop() to stop listening for more messages, for a graceful shutdown. Include a queueName in the constructor to listen for a particular queue.
If your session is transacted,then "acknowledgeMode" is ignored anyways..So, just leave your session transacted and use session.rollback and session.commit to commit or rollback your transaction.

Categories