Jms message acknowledgement - jms

I have an issue related to java messaging service ...
Problem: suppose my JMS publisher sends me 5 messages... When I receive first two messages my app processes them and acknowledges them... So that it is removed from the topic... Wen I receive 3rd message, because of some problem my app cannot process it and doesn't acknowledge... But 4th and 5th message got processed and acknowledged... But wen I checked the admin console I found out that the 3rd message is also acknowledged...
I want to know how to acknowledge each message individually. Anybody has idea???
Note: I'm using CLIENT_ACKNOWLEDGE mode.

According to JMS specification CLIENT_ACKNOWLEDGE - acknowledging a consumed message automatically acknowledges the receipt of all messages that have been delivered by its session.
Many JMS providers have implemented above specification and hence don't provide acknowledging one message. But some JMS providers (AcitveMQ ??) do implement per message acknowledgement. So you will need to check with your JMS provider if it supports per message acknowledgement feature.

Related

Get responses based on corretionID from IBM MQ for multi-thread scenario

My requirement is that:
I have an IBM MQ which is shared across 20 servers and runs the JMS client. Now there will be a specific message in the queue which is intended for a particular thread. The thread need to use a correlationID to fetch the message from all the messages in the MQ.
When I am using onMessage() it is uncertain which thread will Listen to the message. Suppose server-1 is waiting for the message but server-15 listens it. Server-1 gets eventually timed out even though there was a message intended for the thread in server-1.
Please suggest how we are going to handle this scenario without introducing major performance issue.
Use a MessageSelector on the listener container(s). If the correlationId is in the standard JMSCorrelationID header the selector would be JMSCorrelationID=foo to receive all foo messages.

Send last sent message to new consumer on a jms topic

Is it possible to configure the topic to store a copy of just the last message and send this to new connections without knowing client identifiers or other info?
Update:
From the info provided by Shashi I found this two pages where they describe a use case similar to mine (applied over stock prices) by using retroactive consumer and a subscription recovery policy. How ever I'm not getting the desired behaviour. What I currently do is:
Include in the activemq the folowing lines in the policyEntry for topic=">"
<subscriptionRecoveryPolicy>
<fixedCountSubscriptionRecoveryPolicy maximumSize="1"/>
</subscriptionRecoveryPolicy>
Add to the URL used to connect to the brocker (using activemq-cpp) consumer.retroactive=true.
Set the consumer has durable. (But I strongly think this is not want since I only need the last one, but without it I didn't get any message when starting the consumer for the second time)
Start up the broker.
Start the consumer.
Send a message to the topic using the activemq web admin console. (I receive it in the consumer, as expected)
Stop consumer.
Send another message to the topic.
Start consumer. I receive the message, also as expected.
However, if the consumer receives a message, then it goes offline (stop process) and then I restart it, it doesn't get the last message back.
The goal is to whenever the consumer starts get the last message, no mater what (obviously, except when there weren't messages sent to the topic).
Any ideas on what I'm missing?
Background:
I have a device which publishes his data to a topic when ever its data changes. A variable number of consumer may be connected to this topic, from 0 to less than 10. There is only one publisher in the topic and always publish all of his data as a single message (little data, just a couple of fields of a sensor reading). The publication rate of this information is variable, not necessarily time based, when something changes a new updated message is sent to the broker.
The problem is that when a new consumer connects to the topic it has no data of the device readings until a new message is send to the topic by the device. This could be solve by creating an additional queue so new connections can subscribe to the topic and then request the device for the current reading through the queue (the device would consume the queue message which would be a request for data, and then response in the same queue).
But Since the messages send to the topic are always information complete I was wondering if is it possible to configure the topic to store a copy of just the last message and send this to new connections without know client identifiers or other info?
Current broker in use is ActiveMQ.
What you want is to have retroactive consumers and to set the lastImageSubscriptionRecoveryPolicy subscription recovery policy on the topic. Shashi is correct in saying that the following syntax for setting a consumer to be retroactive works only with Openwire
topic = new ActiveMQTopic("TEST.Topic?consumer.retroactive=true");
In your case, what you can do is to configure all consumers to be retroactive in broker config with alwaysRetroactive="true". I tested that this works even for the AMQP protocol (library qpid-jms-client) and I suspect it will work for all protocols.
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic="FOO.>" alwaysRetroactive="true">
<subscriptionRecoveryPolicy>
<lastImageSubscriptionRecoveryPolicy />
</subscriptionRecoveryPolicy>
</policyEntry>
The configuration example is taken from https://github.com/apache/activemq/blob/master/activemq-unit-tests/src/test/resources/org/apache/activemq/test/retroactive/activemq-message-query.xml
Messaging providers (WebSphere MQ for example) have a feature called Retained Publication. With this feature the last published message on a topic is retained by the messaging provider and delivered to a new consumer who comes in after a message has been published on a given topic.
Retained Publication may be supported by Active MQ in it's native interface. This link talks about consumer.retroactive which is available for OpenWire only.
A publisher will tell the messaging provider to retain a publication by setting a property on the message before publishing. Below is how it is done using WebSphere MQ.
// set as a retained publication
msg.setIntProperty(JmsConstants.JMS_IBM_RETAIN, JmsConstants.RETAIN_PUBLICATION)

Is it possible to use CLIENT_ACKNOWLEDGE in producer side? - JMS

Is it possible to use CLIENT_ACKNOWLEDGE in producer side in JMS? Then what does it mean? I mean acknowledging is something in consumer side.
No, message acknowledgement is purely a consumer side concept. When creating a JMS Session you have the choice among several acknowledgment modes. The idea behind message acknowledgement has to do with the concept of guaranteed delivery in message oriented middleware (MOM). In short, when you send a message via a MOM implementation, that message will be persisted (by the producer) until it is sent to a consumer AND the consumer acknowledges its delivery (or until the message expires). In the event that an acknowledgement is not received by the consumer within some reasonable amount of time the message is re-sent by the producer. Each mode impacts message delivery differently.
In AUTO_ACKNOWLEDGE mode, any messages received by consumers through the session will be acknowledged automatically by the consumers underlying JMS runtime upon reception.
In CLIENT_ACKNOWLEDGE mode, each message received by consumers through the session must be explicitly acknowledged. This means that the responsibility of acknowledging a message falls on the application instead of the JMS runtime. Typically the consumer needs to invoke the acknowledge() method on the session after processing the message in the onMessage() method.
There is also a DUPS_OK_ACKNOWLEDGE setting that is similar to AUTO_ACKNOWLEDGE but instead acknowledgements are sent by the JMS implementation lazily, potentially causing duplicate reception of messages.
Typically you would use CLIENT_ACKNOWLEDGE mode when you need to have explicit control over the acknowledgement of messages.

How can sender know the message already be consumed with MQ JMS API?

I'm dealing with a standalone MQ JMS application, our app need to "aware" that client already consumed the message producer put on the queue. Because client app is not responsible by us. So we cannot let them to write something like "msg.acknowledge();" thing on their side (msg.acknowledge() is not the right approach on my condition.). I search the history answer in the stackoverflow. Find following is quite the same what I want:
https://stackoverflow.com/questions/6521117/how-to-guarantee-delivery-of-the-message-in-jms
Do the JMS spec or the various implementations support delivery confirmation of messages?
My question is, is there any other way to archive this in the MQ API or JMS API? I need to do the coding only on the msg produce side, it is can be queue or topic.
Another question is in the JMS the acknowledge mode CLIENT_ACKNOWLEDGE, is that produce irrelevant? I always believe that this mode can block the application when call send() method until the client consume the message and call the msg.acknowledge(), but seems not like that. The produce just exit the app after message be delivered, and the message just store in the queue until client call the acknowledge(). Is that possible let the producer app hang there wait until the message be acknowledged by the client?
If my concept is not right, just correct me, thanks.
The main intention of message queuing is to decouple producer and consumer. Producer does not need to wait for the message to be consumed by the consumer, it can continue it's job. Ideally if producer needs to know if the message has been processed by consumer or not, it should wait for consumer to send a response message on another queue.
Message acknowledgement has nothing to do with producer. Message acknowledgement is the way a consumer tells the messaging provider to remove the message from a queue after the message has been delivered to an application.
There is auto acknowledge where the JMS providers (like MQ JMS), after delivering message to an application, tell the messaging provider to remove the message from queue. Then there is client acknowledge where, after receiving a message, the application explicitly tells the messaging provider to remove message from a queue.
Is there is a reason why the producer has to wait for consumer to receive the message? One way, though not elegant, could be: Once the message is sent, use the message id of the sent message and try to browse for that message. If message is not found, you can assume it has been consumed

Is there a Message Bus provider that allows for Durable Subscribersand full replay?

I am trying to find a message bus provider that supports Durable Subscribers and allows me to replay, in order, based on the message timestamp, all messages for a given topic. Futhermore, I would like the message bus to reset each durable consumer's checkpoint when a message arrives late. E.g.
Client subscribes to topic 1 at 2009-12-22 12:00:00
Message 1 arrives, Timestamped 2009-12-22
Client receives Message 1
Client disconnects
Message 2 arrives, Timestamped 2009-12-21 18:00:00
Client connects
Client receives Message 2, then Message 1
I would strongly prefer an open source provider. Does anyone know of a message bus provider that supports this? I've tried to read the intro documentation for ActiveMQ, Mass Transit, etc but I have to admit that I am behind the curve on message bus terminology, so a lot of it went over my head.
AMQP (implemented by RabbitMQ, et al) lets you define durable queues and attach them to the same exchange. Each client that wants to receive messages first sets up its own durable queue, which will hold messages received from the exchange even while the client is disconnected.
The only limitation of this is that clients that have never connected, and which arrive on the scene unexpectedly, cannot belatedly setup a queue and request a dump of all previous messages. AMQP 1.0 might allow such universal persistence, but I don't know the new model that well, so I can't say for sure.
you may want to look at the spring integration project.
http://www.springsource.org/spring-integration

Resources