How to let messages expire

In this recipe, we are going to see how to let messages expire. The recipe sources can be found at Chapter02/Recipe01/Java/src/rmqexample in the code bundle that contains the following three executable classes:

  • Producer.java
  • Consumer.java
  • GetOne.java

Getting ready

In order to use this recipe, we need to set up the Java development environment, as indicated in the Introduction section of Chapter 1, Working with AMQP.

How to do it...

The core of this example is in the Producer.java file. To produce messages that expire with a given Time-To-Live (TTL), we have to perform the following steps:

  1. Create or declare an exchange to send messages and bind it to a queue, as seen in Chapter 1, Working with AMQP:
    channel.exchangeDeclare(exchange, "direct", false);
    channel.queueDeclare(queue, false, false, false, null);
    channel.queueBind(queue, exchange, routingKey);
  2. Initialize the TTL as an optional message property as follows:
    BasicPropertiesmsgProperties = new BasicProperties.Builder().expiration("20000").build();
  3. Publish the messages using the following code:
    channel.basicPublish(exchange, routingKey, msgProperties, statMsg.getBytes());

How it works...

In this example, the producer creates the exchange, a named queue, and binds them to each other; messages with expiration make sense when it is possible that the queue is not attached to any consumer.

Setting the expiration time, the TTL (set in milliseconds), just let RabbitMQ delete any message as soon as it expires, if not consumed by a client in time.

In our example, we suppose that an application publishes JVM resource statistics to the given queue. If there is a consumer bound, it will just get real-time data as usual.

Alternatively, if there is nothing attached, messages will expire in the queue after the given TTL. In this way, we are avoiding collecting too much data.

As soon as a consumer binds to the queue, it gets the previous (not expired) messages and the real-time ones.

To further experiment, you can run the GetOne.java file instead of the Consumer.java file. This lets you consume just one message at a time by calling channel.basicGet().

Tip

It's possible to use channel.basicGet() to inspect a queue without consuming messages. It's enough to invoke it by passing false to the second parameter, that is, the autoAck flag.

In the course of the experiments, we can monitor the RabbitMQ queue status issuing rabbitmqctl list_queues.

See also

The expired messages are lost by default but they can be rerouted to other destinations. Refer to the Managing rejected or expired messages recipe for more information.