| = Last-Value Queues |
| :idprefix: |
| :idseparator: - |
| |
| Last-Value queues are special queues which discard any messages when a newer message with the same value for a well-defined Last-Value property is put in the queue. |
| In other words, a Last-Value queue only retains the last value. |
| |
| A typical example for Last-Value queue is for stock prices, where you are only interested by the latest value for a particular stock. |
| |
| Messages sent to an Last-Value queue without the specified property will be delivered as normal and will never be "replaced". |
| |
| == Configuration |
| |
| [discrete] |
| ==== Last Value Key Configuration |
| |
| Last-Value queues can be statically configured in broker.xml via the `last-value-key` |
| |
| [,xml] |
| ---- |
| <address name="foo.bar"> |
| <multicast> |
| <queue name="orders1" last-value-key="reuters_code" /> |
| </multicast> |
| </address> |
| ---- |
| |
| Specified on creating a queue by using the CORE api specifying the parameter `lastValue` to `true`. |
| |
| Or on auto-create when using the JMS Client by using address parameters when creating the destination used by the consumer. |
| |
| [,java] |
| ---- |
| Queue queue = session.createQueue("my.destination.name?last-value-key=reuters_code"); |
| Topic topic = session.createTopic("my.destination.name?last-value-key=reuters_code"); |
| ---- |
| |
| Address wildcards can be used to configure Last-Value queues for a set of addresses (see xref:wildcard-syntax.adoc#wildcard-syntax[here]). |
| |
| [,xml] |
| ---- |
| <address-setting match="lastValueQueue"> |
| <default-last-value-key>reuters_code</default-last-value-key> |
| </address-setting> |
| ---- |
| |
| By default, `default-last-value-key` is `null`. |
| |
| [discrete] |
| ==== Legacy Last Value Configuration |
| |
| Last-Value queues can also just be configured via the `last-value` boolean property, doing so it will default the last-value-key to `_AMQ_LVQ_NAME`. |
| |
| [,xml] |
| ---- |
| <address name="foo.bar"> |
| <multicast> |
| <queue name="orders1" last-value="true" /> |
| </multicast> |
| </address> |
| ---- |
| |
| Specified on creating a queue by using the CORE api specifying the parameter `lastValue` to `true`. |
| |
| Or on auto-create when using the JMS Client by using address parameters when creating the destination used by the consumer. |
| |
| [,java] |
| ---- |
| Queue queue = session.createQueue("my.destination.name?last-value=true"); |
| Topic topic = session.createTopic("my.destination.name?last-value=true"); |
| ---- |
| |
| Also the default for all queues under and address can be defaulted using the `address-setting` configuration: |
| |
| [,xml] |
| ---- |
| <address-setting match="lastValueQueue"> |
| <default-last-value-queue>true</default-last-value-queue> |
| </address-setting> |
| ---- |
| |
| By default, `default-last-value-queue` is false. |
| |
| Note that `address-setting` `last-value-queue` config is deprecated, please use `default-last-value-queue` instead. |
| |
| == Last-Value Property |
| |
| The property name used to identify the last value is configurable at the queue level mentioned above. |
| |
| If using the legacy setting to configure an LVQ then the default property `"_AMQ_LVQ_NAME"` is used (or the constant `Message.HDR_LAST_VALUE_NAME` from the Core API). |
| |
| For example, using the sample configuration |
| |
| [,xml] |
| ---- |
| <address name="foo.bar"> |
| <multicast> |
| <queue name="orders1" last-value-key="reuters_code" /> |
| </multicast> |
| </address> |
| ---- |
| |
| if two messages with the same value for the Last-Value property are sent to a Last-Value queue, only the latest message will be kept in the queue: |
| |
| [,java] |
| ---- |
| // send 1st message with Last-Value property `reuters_code` set to `VOD` |
| TextMessage message = session.createTextMessage("1st message with Last-Value property set"); |
| message.setStringProperty("reuters_code", "VOD"); |
| producer.send(message); |
| |
| // send 2nd message with Last-Value property `reuters_code` set to `VOD` |
| message = session.createTextMessage("2nd message with Last-Value property set"); |
| message.setStringProperty("reuters_code", "VOD"); |
| producer.send(message); |
| |
| ... |
| |
| // only the 2nd message will be received: it is the latest with |
| // the Last-Value property set |
| TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); |
| System.out.format("Received message: %s\n", messageReceived.getText()); |
| ---- |
| |
| == Forcing all consumers to be non-destructive |
| |
| It's common to combine last-value queues with xref:non-destructive-queues.adoc#non-destructive-queues[non-destructive] semantics. |
| |
| == Clustering |
| |
| The fundamental ideas behind last-value queues and clustering are at odds with each other. |
| |
| Clustering was designed as a way to increase message throughput through horizontal scaling. |
| The messages in a clustered queue can be spread across _all_ nodes in the cluster. |
| This allows clients to be distributed across the cluster to leverage the computing resources all the nodes rather than being bottlenecked on a single node. |
| |
| However, if you wanted to use a last-value queue in a cluster then in order to enforce last-value semantics all messages would be required to go to a queue on a _single_ node. |
| This would effectively _nullify_ the benefits of clustering. |
| Also, the arrival of messages on and and redistribution of those messages from nodes other than the node where the last-value semantics would be enforced would almost certainly impact which message is considered "last." |
| |
| For these reasons last-value queues are not supported in a traditional cluster. |
| However, it would be possible to use a xref:connection-routers.adoc#connection-routers[connection router] in front of a cluster (or even a set of non-clustered brokers) to ensure all clients which need to use the same last-value queue are directed to the same node. |
| See the xref:connection-routers.adoc#connection-routers[connection router] for more details on configuration, etc. |
| |
| == Example |
| |
| See the xref:examples.adoc#last-value-queue[last-value queue example] which shows how last value queues are configured and used with JMS. |