Tibco EMS Queuebrowser pending message count slowness - java

I have a requirement to fetch the pending messages from tibco ems queue. Below is my program using spring jms template. However, I published 5000 messages to queue and tried fetching the count of same with out consuming, and realized it took nearly 20 minutes to browse and get the count. Please advise on any performance improvement here or any other better way to get the pending message count
jmsTemplate.execute(new SessionCallback<QueueBrowser>() {
public QueueBrowser doInJms(Session session) throws JMSException {
javax.jms.Queue queue = session.createQueue(queueName);
QueueBrowser browser = session.createBrowser(queue);
Enumeration messages = browser.getEnumeration();
int num = 0;
while(messages.hasMoreElements()) {
messages.nextElement();
num +=1;
LOG.info("num={}",num);
}
return null;
}
}, true);

From EMS 8.3 samples:
javax.jms.QueueBrowser browser = session.createBrowser(queue);
Enumeration msgs = browser.getEnumeration();
int browseCount=0;
while (msgs.hasMoreElements())
{
message = (javax.jms.Message)msgs.nextElement();
System.err.println("Browsed message: number="+message.getIntProperty("msg_num"));
browseCount++;
}

Related

Remove message from a queue in ActiveMq

I have an application with several activeMq queues. I would like to list the messages in them and remove any of them from any of the queues based on the id of the message.
Here is my code so far.
public void killMessage(String id) {
try {
ActiveMQConnection activeMqConnection = (ActiveMQConnection) connectionFactory.createConnection();
activeMqConnection.start();
DestinationSource destinationSource = activeMqConnection.getDestinationSource();
Set<ActiveMQQueue> queues = destinationSource.getQueues();
QueueSession queueSession = activeMqConnection.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
for(ActiveMQQueue queue : queues) {
QueueBrowser browser = queueSession.createBrowser(queue);
Enumeration<?> messagesInQueue = browser.getEnumeration();
while (messagesInQueue.hasMoreElements()) {
Message message = (Message) messagesInQueue.nextElement();
System.out.println("Current id: " + message.getJMSMessageID());
if(message.getJMSMessageID().equals(id)){
System.out.println("-----message id found-------");
}
}
}
activeMqConnection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
I iterate through all the queues, then I iterate through all messages in each queue. I even find the message I want to delete, but I cannot find a way to remove it from the queue.
Edit:
I also created a consumer. I am not sure how the consumer should make the messages disappear from the queue. My attempt at it, which have no effect at all, messages remain in the queue, and I get no error message and no exception is thrown which could indicate the consumer did not match a message:
if(message.getJMSMessageID().equals(id)){
System.out.println("-----message id found-------");
MessageConsumer consumer = queueSession.createConsumer(queue, "JMSMessageID='" + id + "'");
consumer.receive();
consumer.close();
}
If you want to use the JMS API to do this then you'll have to create a consumer and use a selector to consume the message with the ID that you want. A queue browser cannot consume messages; it can only browse them.
In the code you pasted you're creating a transacted session which means when you consume the message you'll need to commit the session otherwise the message will never be acknowledged. That said, you're probably better off creating a non-transacted session with AUTO_ACKNOWLEDGE instead.
Also, you probably want to call receive(int) (i.e. with a timeout) so that if the selector can't find the message for some reason your application doesn't just sit there forever waiting on the method to return.

JMS - Message redlivery on fail

I've got this scenario:
a JMS message elaboration via an MDB might fail (throws a RuntimeException in this case)
the message should be redelivered, though after a delay (ideal, but not strictly necessary: after an increasing delay depending on the number of fails)
after x failures, the message should be disregarded and never sent again
Right now, the behaviour I have is that the failed message is redelivered instantly for 10 times, and I haven't been able to customize this.
Is there a way I can achieve this via #JMSdefinition (or other annotations as well) or setting the correct properties in the message? If so, how to do?
You can schedule the message with _AMQ_SCHED_DELIVERY property:
Queue q = (Queue) ServiceLocator.getInstance().getDestination("QUEUE");
QueueConnectionFactory factory = (QueueConnectionFactory) ServiceLocator.getInstance().getConnectionFactory(
"java:/ConnectionFactory");
QueueConnection connection = factory.createQueueConnection();
QueueSession session = null;
QueueSender sender = null;
session = connection.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
sender = session.createSender(q);
ObjectMessage msg = session.createObjectMessage();
if (redelivedCount > 0) {
msg.setIntProperty("redelivedCount", redelivedCount);
// schedule to run in 10 secs
msg.setLongProperty("_AMQ_SCHED_DELIVERY", System.currentTimeMillis() + 10000);
}
msg.setStringProperty("action", action);
msg.setObject(params);
sender.send(msg);

JMS selector strange behaviour

In JMS consider the following pseudo-code:
Sender:
QueueSender qs = session.createSender(queue);
int i = 0;
while(i < 10)
{
TextMessage msg = session.createTextMessage();
msg.setText(""+i);
msg.setIntProperty("value", i);
qs.send(msg);
i++;
}
Receiver:
String sel = "value >2";
QueueReceiver qr = session.createReceiver(q,sel);
while(true)
{
TextMessage tm = (TextMessage) qr.receive();
System.out.println(tm.getText);
}
I would have expected the consumer not to consume/print anything becauses the messages he is interested at are blocked by the messages 0,1,2 that are not being pulled by any consumer.
What I see instead is the consumer printing out all the messages selected by its selector...
Is that the correct behaviour of JMS ?
Is that documented somewhere ?
thanks.
I would have expected the consumer not to consume/print anything
becauses the messages he is interested at are blocked by the messages
0,1,2 that are not being pulled by any consumer
This assumption is incorrect. When you use a selector in JMS, the messages that do not satisfy the selector expression will not be delivered to the QueueReceiver. The QueueReciever will continue to read all those messages that satisfy the selector expression.
I believe that your output contains the numbers from 3 - 10. . This is the expected behavior. See the documentation for the createReceiver method.

QueueBrowser does not return all messages

I list down queues and messages from each queue. The following is my code. But, QueueBrowser does not retrieve messages correctly.
Let's say, I have a queue named TestQueue which has 1000 message.
first time i run my program it shows only 200 messages.
second - 400
third - 600
forth - 800
fifth - 1000
Can you tell me how to fix this problem?
ConnectionFactory out = new ActiveMQConnectionFactory("tcp://localhost:61616?jms.prefetchPolicy.all=10000");
ActiveMQConnection connection = (ActiveMQConnection) out.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Set<ActiveMQQueue> amqs = connection.getDestinationSource().getQueues();
Iterator<ActiveMQQueue> queues = amqs.iterator();
while ( queues.hasNext() )
{
ActiveMQQueue queue_t = aqueues.next();
String q_name = queue_t.getPhysicalName();
List<ActiveMQMessage> msgList = ((ActiveMQSession) session).getUnconsumedMessages();
System.out.println( "\nQueue = " + q_name);
QueueBrowser queueBrowser = session.createBrowser(queue_t);
Enumeration e = queueBrowser.getEnumeration();
int numMsgs = 0;
while(e.hasMoreElements())
{
Message message = (Message) e.nextElement();
numMsgs++;
}
System.out.println("No of messages = " + numMsgs);
queueBrowser.close();
}
session.close();
connection.close();
From the javax.jms.QueueBrowser API:
Messages may be arriving and expiring while the scan is done. The JMS API does not require the content of an enumeration to be a static snapshot of queue content. Whether these changes are visible or not depends on the JMS provider.
Have you tried specifying the prefetch policy?
Just connect using JMX to Broker (use jconsole for example). On specific queue set MaxPageSize properties more than 200 then you can list more messages.

Apache ActiveMQ fall back mechanism

I am using Apache Active MQ with Spring..... the problem I am facing is that I am creating producer on one machine let say Machine1 and I am creating one consumer on second machine let say Machine2...
I am creating producer on Machine1 by calling a simple servlet call.... and then create a consumer on Machine2....
Problem I am facing is that suppose in anyway if my producer is not able to send any data packet in specified time duration then I want to delete my consumer and Queue from Machine2...
Is there anyway I can set my Consumer and Queue to get auto delete and perform some business logic if I do not get any packet from producer in a specified time duration....
connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,ActiveMQConnection.DEFAULT_PASSWORD,ConnectorURL);
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueID+"");
connection = connectionFactory.createConnection();
connection.start();
consumer = session.createConsumer(destination);
basically this code create consumer for my application....then I assign this consumer to my application listener that listen if producer send any message to consumer....
ScenarioExecutionQueueListenerImpl executionQueueListener = new ScenarioExecutionQueueListenerImpl(scenario,result, host);
beanFactory.autowireBean(executionQueueListener);
connection.setExceptionListener(executionQueueListener);
Message message = consumer.receive();
consumer.setMessageListener(executionQueueListener);
executionQueueListener.setConsumer(consumer);
executionQueueListener.onMessage(message);
I would not setup a messagelistener for that case, but just use the consumer.receive() method. The MessageListener is more for time independent/asynchronous consuming.
public void run(){
Message m = consumer.receive(timeout_value_in_millisec);
if( m != null ){
// got a message, handle it.
processMessage(msg);
}else{
// no message received in specified time,
}
// close session, connection etc.
}
public void processMessage(Message msg){
}

Categories