All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rabbitmq.client.QueueingConsumer Maven / Gradle / Ivy

Go to download

The RabbitMQ Java client library allows Java applications to interface with RabbitMQ.

There is a newer version: 5.22.0
Show newest version
//  The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (the "License"); you may not use this file except in
//  compliance with the License. You may obtain a copy of the License
//  at http://www.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
//  the License for the specific language governing rights and
//  limitations under the License.
//
//  The Original Code is RabbitMQ.
//
//  The Initial Developer of the Original Code is VMware, Inc.
//  Copyright (c) 2007-2011 VMware, Inc.  All rights reserved.
//


package com.rabbitmq.client;

import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.utility.Utility;

/**
 * Convenience class: an implementation of {@link Consumer} with
 * straightforward blocking semantics.
 *
 * The general pattern for using QueueingConsumer is as follows:
 *
 * 
 * // Create connection and channel.
 * {@link ConnectionFactory} factory = new ConnectionFactory();
 * Connection conn = factory.newConnection();
 * {@link Channel} ch1 = conn.createChannel();
 *
 * // Declare a queue and bind it to an exchange.
 * String queueName = ch1.queueDeclare().{@link AMQP.Queue.DeclareOk#getQueue getQueue}();
 * ch1.{@link Channel#queueBind queueBind}(queueName, exchangeName, queueName);
 *
 * // Create the QueueingConsumer and have it consume from the queue
 * QueueingConsumer consumer = new {@link QueueingConsumer#QueueingConsumer QueueingConsumer}(ch1);
 * ch1.{@link Channel#basicConsume basicConsume}(queueName, false, consumer);
 *
 * // Process deliveries
 * while (/* some condition * /) {
 *     {@link QueueingConsumer.Delivery} delivery = consumer.{@link QueueingConsumer#nextDelivery nextDelivery}();
 *     // process delivery
 *     ch1.{@link Channel#basicAck basicAck}(delivery.{@link QueueingConsumer.Delivery#getEnvelope getEnvelope}().{@link Envelope#getDeliveryTag getDeliveryTag}(), false);
 * }
 * 
* *

For a more detailed explanation, see the java api guide.

* *

For a more complete example, see LogTail in the test/src/com/rabbitmq/examples * directory of the source distribution.

*/ public class QueueingConsumer extends DefaultConsumer { private final BlockingQueue _queue; // When this is non-null the queue is in shutdown mode and nextDelivery should // throw a shutdown signal exception. private volatile ShutdownSignalException _shutdown; private volatile ConsumerCancelledException _cancelled; // Marker object used to signal the queue is in shutdown mode. // It is only there to wake up consumers. The canonical representation // of shutting down is the presence of _shutdown. // Invariant: This is never on _queue unless _shutdown != null. private static final Delivery POISON = new Delivery(null, null, null); public QueueingConsumer(Channel ch) { this(ch, new LinkedBlockingQueue()); } public QueueingConsumer(Channel ch, BlockingQueue q) { super(ch); this._queue = q; } @Override public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { _shutdown = sig; _queue.add(POISON); } @Override public void handleCancel(String consumerTag) throws IOException { _cancelled = new ConsumerCancelledException(); _queue.add(POISON); } @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { checkShutdown(); this._queue.add(new Delivery(envelope, properties, body)); } /** * Encapsulates an arbitrary message - simple "bean" holder structure. */ public static class Delivery { private final Envelope _envelope; private final AMQP.BasicProperties _properties; private final byte[] _body; public Delivery(Envelope envelope, AMQP.BasicProperties properties, byte[] body) { _envelope = envelope; _properties = properties; _body = body; } /** * Retrieve the message envelope. * @return the message envelope */ public Envelope getEnvelope() { return _envelope; } /** * Retrieve the message properties. * @return the message properties */ public BasicProperties getProperties() { return _properties; } /** * Retrieve the message body. * @return the message body */ public byte[] getBody() { return _body; } } /** * Check if we are in shutdown mode and if so throw an exception. */ private void checkShutdown() { if (_shutdown != null) throw Utility.fixStackTrace(_shutdown); } /** * If this is a non-POISON non-null delivery simply return it. * If this is POISON we are in shutdown mode, throw _shutdown * If this is null, we may be in shutdown mode. Check and see. */ private Delivery handle(Delivery delivery) { if (delivery == POISON || delivery == null && (_shutdown != null || _cancelled != null)) { if (delivery == POISON) { _queue.add(POISON); if (_shutdown == null && _cancelled == null) { throw new IllegalStateException( "POISON in queue, but null _shutdown and null _cancelled. " + "This should never happen, please report as a BUG"); } } if (null != _shutdown) throw Utility.fixStackTrace(_shutdown); if (null != _cancelled) throw Utility.fixStackTrace(_cancelled); } return delivery; } /** * Main application-side API: wait for the next message delivery and return it. * @return the next message * @throws InterruptedException if an interrupt is received while waiting * @throws ShutdownSignalException if the connection is shut down while waiting */ public Delivery nextDelivery() throws InterruptedException, ShutdownSignalException, ConsumerCancelledException { return handle(_queue.take()); } /** * Main application-side API: wait for the next message delivery and return it. * @param timeout timeout in millisecond * @return the next message or null if timed out * @throws InterruptedException if an interrupt is received while waiting * @throws ShutdownSignalException if the connection is shut down while waiting */ public Delivery nextDelivery(long timeout) throws InterruptedException, ShutdownSignalException, ConsumerCancelledException { return handle(_queue.poll(timeout, TimeUnit.MILLISECONDS)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy