static void Main(string[] args)
        {
            try
            {
                ConnectionFactory connectionFactory = new ConnectionFactory(URI);
                connectionFactory.UserName = USER;
                connectionFactory.Password = PASS;

                using (SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer())
                {
                    listenerContainer.ConnectionFactory = connectionFactory;
                    listenerContainer.DestinationName   = DESTINATION;
                    listenerContainer.MessageListener   = new Listener();
                    listenerContainer.AfterPropertiesSet();
                    Console.WriteLine("Listener started.");
                    Console.WriteLine("Press <ENTER> to exit.");
                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                Console.WriteLine("Press <ENTER> to exit.");
                Console.Read();
            }
            // comment when testing
            Console.ReadLine();
        }
Example #2
0
        static void Main(string[] args)
        {
            Tracer.Trace = new NLogAdapter();

            var brokerUri = "failover:(amqp://127.0.0.1:5672,amqp://127.0.0.1:5673)" +
                            "?failover.initialReconnectDelay=1000" +
                            "&failover.reconnectDelay=1000" +
                            "&failover.maxReconnectAttempts=10";
            var connectionFactory = new NmsConnectionFactory(brokerUri);
            var simpleMessageListenerContainer = new SimpleMessageListenerContainer
            {
                ConnectionFactory = connectionFactory,
                DestinationName   = DestinationName,
                MessageListener   = new MessageListener()
            };

            // start listener
            simpleMessageListenerContainer.AfterPropertiesSet();

            var cachingConnectionFactory = new CachingConnectionFactory(connectionFactory);
            var nmsTemplate = new NmsTemplate(cachingConnectionFactory)
            {
                DefaultDestinationName = DestinationName,
            };

            while (true)
            {
                Logger.Info("Enter your message.");
                var text = Console.ReadLine();
                nmsTemplate.SendWithDelegate(session => session.CreateTextMessage(text));
            }
        }
        public void RegisteredExceptionListenerIsInvokedOnException()
        {
            SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();

            ISession session = (ISession)mocks.CreateMock(typeof(ISession));

            Expect.Call(session.CreateQueue(DESTINATION_NAME)).Return(QUEUE_DESTINATION);
            Expect.Call(session.CreateConsumer(QUEUE_DESTINATION, null)).Return(messageConsumer);
            // an exception is thrown, so the rollback logic is being applied here...
            Expect.Call(session.Transacted).Return(false);

            IConnection connection = (IConnection)mocks.CreateMock(typeof(IConnection));

            //connection.ExceptionListener += container.OnException;
            connection.ExceptionListener = container;
            Expect.Call(connection.CreateSession(false, container.SessionAcknowledgeMode)).Return(session);
            connection.Start();

            IConnectionFactory connectionFactory = (IConnectionFactory)mocks.CreateMock(typeof(IConnectionFactory));

            Expect.Call(connectionFactory.CreateConnection()).Return(connection);

            EMSException theException = new EMSException(EXCEPTION_MESSAGE);

            IExceptionListener exceptionListener = (IExceptionListener)mocks.CreateMock(typeof(IExceptionListener));

            exceptionListener.OnException(theException);

            //IMessage message = (IMessage) mocks.CreateMock(typeof (IMessage));
            TextMessage message = new TextMessage(null, "hello");

            mocks.ReplayAll();


            container.ConnectionFactory = connectionFactory;
            container.DestinationName   = DESTINATION_NAME;
            container.MessageListener   = new BadSessionAwareMessageListener(theException);
            container.ExceptionListener = exceptionListener;
            container.AfterPropertiesSet();

            // manually trigger an Exception with the above bad MessageListener...
            messageConsumer.SendMessage(message);

            mocks.VerifyAll();
        }
Example #4
0
        public void TestDefaultConsumerCount()
        {
            var container = new SimpleMessageListenerContainer(new SingleConnectionFactory());

            container.MessageListener = new MessageListenerAdapter(this);
            container.QueueNames      = new[] { "foo" };
            container.AutoStartup     = false;
            container.AfterPropertiesSet();
            Assert.AreEqual(1, ReflectionUtils.GetInstanceFieldValue(container, "concurrentConsumers"));
        }
Example #5
0
        /// <summary>Does the test.</summary>
        /// <param name="concurrentConsumers">The concurrent consumers.</param>
        /// <param name="configurer">The configurer.</param>
        private void DoTest(int concurrentConsumers, IContainerConfigurer configurer)
        {
            var messageCount      = 10;
            var template          = new RabbitTemplate();
            var connectionFactory = new CachingConnectionFactory();

            connectionFactory.ChannelCacheSize = concurrentConsumers;
            connectionFactory.Port             = BrokerTestUtils.GetPort();
            template.ConnectionFactory         = connectionFactory;
            var messageConverter = new SimpleMessageConverter();

            messageConverter.CreateMessageIds = true;
            template.MessageConverter         = messageConverter;
            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue1.Name, i);
                template.ConvertAndSend(queue2.Name, i);
            }

            var container = new SimpleMessageListenerContainer(connectionFactory);
            var latch     = new CountdownEvent(messageCount * 2);
            var listener  = new MultiplePocoListener(latch);

            container.MessageListener     = new MessageListenerAdapter(listener);
            container.AcknowledgeMode     = AcknowledgeModeUtils.AcknowledgeMode.Auto;
            container.ChannelTransacted   = true;
            container.ConcurrentConsumers = concurrentConsumers;
            configurer.Configure(container);
            container.AfterPropertiesSet();
            container.Start();
            try
            {
                var timeout = Math.Min((1 + messageCount) / concurrentConsumers, 50);
                Logger.Info("Timeout: " + timeout);
                var waited = latch.Wait(timeout * 1000);
                Logger.Info("All messages recovered: " + waited);
                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                Assert.True(waited, "Timed out waiting for messages");
            }
            catch (ThreadInterruptedException e)
            {
                Thread.CurrentThread.Interrupt();
                throw new ThreadStateException("unexpected interruption");
            }
            finally
            {
                container.Shutdown();
                Assert.AreEqual(0, container.ActiveConsumerCount);
            }

            Assert.Null(template.ReceiveAndConvert(queue1.Name));
            Assert.Null(template.ReceiveAndConvert(queue2.Name));
        }
        private ReservationWorker()
        {
            ConnectionFactory factory = new ConnectionFactory(Config.Url);

            listenerContainer = new SimpleMessageListenerContainer
            {
                ConnectionFactory = factory,
                DestinationName   = Config.ReturnMessageQueue,
                MessageListener   = new GenericMessageListener <MessageDto>(new MessageHandler())
            };
            listenerContainer.AfterPropertiesSet();
        }
        /// <summary>Creates the container.</summary>
        /// <param name="queueName">Name of the queue.</param>
        /// <param name="listener">The listener.</param>
        /// <param name="connectionFactory">The connection factory.</param>
        /// <returns>The container.</returns>
        private SimpleMessageListenerContainer CreateContainer(string queueName, object listener, IConnectionFactory connectionFactory)
        {
            var container = new SimpleMessageListenerContainer(connectionFactory);

            container.MessageListener     = new MessageListenerAdapter(listener);
            container.QueueNames          = new[] { queueName };
            container.ConcurrentConsumers = this.concurrentConsumers;
            container.ChannelTransacted   = this.transactional;
            container.AcknowledgeMode     = this.acknowledgeMode;
            container.AfterPropertiesSet();
            container.Start();
            return(container);
        }
        private SimpleMessageListenerContainer CreateContainer(object listener)
        {
            var container = new SimpleMessageListenerContainer(this.template.ConnectionFactory);

            container.MessageListener     = new MessageListenerAdapter(listener);
            container.QueueNames          = new[] { this.queue.Name };
            container.TxSize              = this.txSize;
            container.PrefetchCount       = this.txSize;
            container.ConcurrentConsumers = this.concurrentConsumers;
            container.ChannelTransacted   = this.transactional;
            container.AcknowledgeMode     = AcknowledgeModeUtils.AcknowledgeMode.Auto;
            container.AfterPropertiesSet();
            container.Start();
            return(container);
        }
Example #9
0
        public void TestInconsistentAcknowledgeConfiguration()
        {
            var container = new SimpleMessageListenerContainer(new SingleConnectionFactory());

            container.MessageListener   = new MessageListenerAdapter(this);
            container.QueueNames        = new[] { "foo" };
            container.ChannelTransacted = true;
            container.AcknowledgeMode   = AcknowledgeModeUtils.AcknowledgeMode.None;

            try
            {
                container.AfterPropertiesSet();
            }
            catch (Exception e)
            {
                Assert.True(e is InvalidOperationException);
            }
        }
Example #10
0
        /// <summary>Creates the container.</summary>
        /// <param name="listener">The listener.</param>
        /// <returns>The container.</returns>
        private SimpleMessageListenerContainer CreateContainer(object listener)
        {
            var container = new SimpleMessageListenerContainer(this.template.ConnectionFactory);

            container.MessageListener     = listener;
            container.QueueNames          = new[] { this.queue.Name };
            container.TxSize              = this.txSize;
            container.PrefetchCount       = this.txSize;
            container.ConcurrentConsumers = this.concurrentConsumers;
            container.ChannelTransacted   = this.transactional;
            container.AcknowledgeMode     = this.acknowledgeMode;
            if (this.externalTransaction)
            {
                container.TransactionManager = new IntegrationTestTransactionManager();
            }

            container.AfterPropertiesSet();
            container.Start();
            return(container);
        }
Example #11
0
        /// <summary>Does the test.</summary>
        /// <param name="messageCount">The message count.</param>
        /// <param name="errorHandler">The error handler.</param>
        /// <param name="latch">The latch.</param>
        /// <param name="listener">The listener.</param>
        public void DoTest(int messageCount, IErrorHandler errorHandler, CountdownEvent latch, object listener)
        {
            var concurrentConsumers = 1;
            var template            = this.CreateTemplate(concurrentConsumers);

            // Send messages to the queue
            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var container = new SimpleMessageListenerContainer(template.ConnectionFactory);

            container.MessageListener     = listener;
            container.AcknowledgeMode     = AcknowledgeModeUtils.AcknowledgeMode.None;
            container.ChannelTransacted   = false;
            container.ConcurrentConsumers = concurrentConsumers;

            container.PrefetchCount = messageCount;
            container.TxSize        = messageCount;
            container.QueueNames    = new[] { queue.Name };
            container.ErrorHandler  = errorHandler;
            container.AfterPropertiesSet();
            container.Start();

            var waited = latch.Wait(1000);

            if (messageCount > 1)
            {
                Assert.True(waited, "Expected to receive all messages before stop");
            }

            try
            {
                Assert.Null(template.ReceiveAndConvert(queue.Name));
            }
            finally
            {
                container.Shutdown();
            }
        }
Example #12
0
        protected void listen(IMessageEventHandler <T> handler, string url, string queueName)
        {
            try
            {
                ConnectionFactory factory = new ConnectionFactory(url);

                SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
                listenerContainer.ConnectionFactory = factory;
                listenerContainer.DestinationName   = queueName;
                listenerContainer.MessageListener   = new GenericMessageListener <T>(handler);
                listenerContainer.AfterPropertiesSet();

                string info = String.Format("Service started!");
                writeToLog(info, LogMessage.LogType.INFO);
                Console.WriteLine(info);
                Console.WriteLine("Press ENTER to exit.");
                Console.ReadLine();
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        /// <summary>Does the test.</summary>
        /// <param name="level">The level.</param>
        /// <param name="concurrency">The concurrency.</param>
        /// <param name="transactionMode">The transaction mode.</param>
        private void DoTest(MessageCount level, Concurrency concurrency, TransactionModeUtils.TransactionMode transactionMode)
        {
            var messageCount        = (int)level;
            var concurrentConsumers = (int)concurrency;
            var transactional       = transactionMode.IsTransactional();

            var template = this.CreateTemplate(concurrentConsumers);

            var latch = new CountdownEvent(messageCount);

            for (var i = 0; i < messageCount; i++)
            {
                template.ConvertAndSend(queue.Name, i + "foo");
            }

            var container = new SimpleMessageListenerContainer(template.ConnectionFactory);
            var listener  = new LifecyclePocoListener(latch);

            container.MessageListener     = new MessageListenerAdapter(listener);
            container.AcknowledgeMode     = transactionMode.AcknowledgeMode();
            container.ChannelTransacted   = transactionMode.IsTransactional();
            container.ConcurrentConsumers = concurrentConsumers;

            if (transactionMode.Prefetch() > 0)
            {
                container.PrefetchCount = transactionMode.Prefetch();
                container.TxSize        = transactionMode.TxSize();
            }

            container.QueueNames = new[] { queue.Name };
            container.AfterPropertiesSet();
            container.Start();

            try
            {
                var waited = latch.Wait(50);
                Logger.Info("All messages received before stop: " + waited);
                if (messageCount > 1)
                {
                    Assert.False(waited, "Expected not to receive all messages before stop");
                }

                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                container.Stop();
                Thread.Sleep(500);
                Assert.AreEqual(0, container.ActiveConsumerCount);
                if (!transactional)
                {
                    var messagesReceivedAfterStop = listener.Count;
                    waited = latch.Wait(500);
                    Logger.Info("All messages received after stop: " + waited);
                    if (messageCount < 100)
                    {
                        Assert.True(waited, "Expected to receive all messages after stop");
                    }

                    Assert.AreEqual(messagesReceivedAfterStop, listener.Count, "Unexpected additional messages received after stop");

                    for (var i = 0; i < messageCount; i++)
                    {
                        template.ConvertAndSend(queue.Name, i + "bar");
                    }

                    latch = new CountdownEvent(messageCount);
                    listener.Reset(latch);
                }

                var messagesReceivedBeforeStart = listener.Count;
                container.Start();
                var timeout = Math.Min(1 + messageCount / (4 * concurrentConsumers), 30);

                Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
                waited = latch.Wait(timeout * 1000);
                Logger.Info("All messages received after start: " + waited);
                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                if (transactional)
                {
                    Assert.True(waited, "Timed out waiting for message");
                }
                else
                {
                    var count = listener.Count;
                    Assert.True(messagesReceivedBeforeStart < count, "Expected additional messages received after start: " + messagesReceivedBeforeStart + ">=" + count);
                    Assert.Null(template.Receive(queue.Name), "Messages still available");
                }

                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
            }
            finally
            {
                // Wait for broker communication to finish before trying to stop
                // container
                Thread.Sleep(500);
                container.Shutdown();
                Assert.AreEqual(0, container.ActiveConsumerCount);
            }

            Assert.Null(template.ReceiveAndConvert(queue.Name));
        }
Example #14
0
        /// <summary>
        /// Listen for messages and consume when messages are received.
        /// </summary>
        public void Run()
        {
            try
            {
                if (string.IsNullOrEmpty(Uri))
                {
                    throw new ArgumentException("Uri can not be empty");
                }

                Logger.Info($"Uri : {Uri}");

                connectionFactory = new Spring.Messaging.Ems.Common.EmsConnectionFactory(Uri);
                if (!string.IsNullOrEmpty(User))
                {
                    connectionFactory.UserName = User;
                    Logger.Info($"User : {User}");
                }

                if (!string.IsNullOrEmpty(Pwd))
                {
                    connectionFactory.UserPassword = Pwd;
                    Logger.Info($"Pwd : {Pwd}");
                }

                if (!string.IsNullOrEmpty(TargetHostName))
                {
                    connectionFactory.TargetHostName = TargetHostName;
                    Logger.Info($"TargetHostName : {TargetHostName}");
                }

                if (UseSsl)
                {
                    if (!System.IO.File.Exists(SslClientCert))
                    {
                        throw new Exception("SslClientCert File is missing");
                    }

                    // Load client certificate from a file
                    var clientCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(SslClientCert, SslClientCertPassword);
                    Logger.Info($"Certificate File:{SslClientCert}");
                    Logger.Info($"Certificate Subject:{clientCert.Subject}");
                    Logger.Info($"Certificate Public Key:{clientCert.PublicKey.Key}");
                    Logger.Info($"Certificate Has private key?:{(clientCert.HasPrivateKey ? "Yes" : "No")}");
                    var sslStore = new EMSSSLFileStoreInfo();
                    sslStore.SetSSLClientIdentity(clientCert);
                    connectionFactory.NativeConnectionFactory.SetCertificateStoreType(EMSSSLStoreType.EMSSSL_STORE_TYPE_FILE, sslStore);
                }

                // Check if we have established a connection since the TargetHostName, Uri, User, or Pwd could be incorrect
                if (connectionFactory == null)
                {
                    throw new Exception("connectionFactory has not been initialized");
                }

                connectionFactory.ClientID = "This needs to be set right";
                Logger.Debug("connectionFactory initialized");
                try
                {
                    Logger.Debug($"Destination - {DestinationName}");
                    using (var listenerContainer = new SimpleMessageListenerContainer())
                    {
                        listenerContainer.ConnectionFactory           = connectionFactory;
                        listenerContainer.DestinationName             = DestinationName;
                        listenerContainer.ConcurrentConsumers         = 1;
                        listenerContainer.PubSubDomain                = false;
                        listenerContainer.MessageListener             = new MessageListener();
                        listenerContainer.ExceptionListener           = new ExceptionListener();
                        listenerContainer.MaxRecoveryTime             = new TimeSpan(MaxRecoveryTimeInDays, 0, 0, 0);
                        listenerContainer.RecoveryInterval            = new TimeSpan(0, 0, 0, 10, 0); // set to 10 Minutes
                        listenerContainer.AcceptMessagesWhileStopping = false;
                        listenerContainer.SessionAcknowledgeMode      = AckMode;
                        listenerContainer.AfterPropertiesSet();
                        if (listenerContainer.IsRunning)
                        {
                            Logger.Debug("Listener IsRunning.");
                        }

                        // TODO: Block to stay in the using and keep on listening.
                        // What are other ways of performing this same action.
                        Console.WriteLine("Press <ENTER> to exit.");
                        Console.ReadLine();
                    }
                }
                catch (EMSException e)
                {
                    Logger.Error($"EMSException : {e.Message}");

                    if (e.LinkedException != null)
                    {
                        Logger.Error($"EMSException Linked Exception error msg : {e.LinkedException.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"Exception : {ex.Message}");
                if (ex.InnerException != null)
                {
                    Logger.Error($"InnerException : {ex.InnerException.Message}");
                }
            }
        }
        public void TestMessageListener()
        {
            var mockConnectionFactory = new Mock <ConnectionFactory>();
            var mockConnection        = new Mock <IConnection>();
            var onlyChannel           = new Mock <IModel>();

            onlyChannel.Setup(m => m.IsOpen).Returns(true);
            onlyChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var cachingConnectionFactory = new CachingConnectionFactory(mockConnectionFactory.Object);

            mockConnectionFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(m => m.IsOpen).Returns(true);

            var tooManyChannels = new AtomicReference <Exception>();
            var done            = false;

            mockConnection.Setup(m => m.CreateModel()).Returns(
                () =>
            {
                if (!done)
                {
                    done = true;
                    return(onlyChannel.Object);
                }

                tooManyChannels.LazySet(new Exception("More than one channel requested"));
                var channel = new Mock <IModel>();
                channel.Setup(m => m.IsOpen).Returns(true);
                return(channel.Object);
            });

            var consumer = new BlockingCollection <IBasicConsumer>(1);

            onlyChannel.Setup(m => m.BasicConsume(It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <IBasicConsumer>())).Callback <string, bool, IBasicConsumer>(
                (a1, a2, a3) => consumer.Add(a3));

            var commitLatch = new CountdownEvent(1);

            onlyChannel.Setup(m => m.TxCommit()).Callback(
                () =>
            {
                if (commitLatch.CurrentCount > 0)
                {
                    commitLatch.Signal();
                }
            });

            var latch     = new CountdownEvent(1);
            var container = new SimpleMessageListenerContainer(cachingConnectionFactory);

            container.MessageListener = new Action <Message>(
                message =>
            {
                var rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
                rabbitTemplate.ChannelTransacted = true;

                // should use same channel as container
                rabbitTemplate.ConvertAndSend("foo", "bar", "baz");
                if (latch.CurrentCount > 0)
                {
                    latch.Signal();
                }
            });

            container.QueueNames         = new[] { "queue" };
            container.ChannelTransacted  = true;
            container.ShutdownTimeout    = 100;
            container.TransactionManager = DummyTxManager.Instance();
            container.AfterPropertiesSet();
            container.Start();

            IBasicConsumer currentConsumer;

            consumer.TryTake(out currentConsumer, this.timeout);
            Assert.IsNotNull(currentConsumer, "Timed out getting consumer.");
            currentConsumer.HandleBasicDeliver("qux", 1, false, "foo", "bar", new BasicProperties(), new byte[] { 0 });

            Assert.IsTrue(latch.Wait(new TimeSpan(0, 0, 10)));

            var e = tooManyChannels.Value;

            if (e != null)
            {
                throw e;
            }

            mockConnection.Verify(m => m.CreateModel(), Times.Once());
            Assert.True(commitLatch.Wait(new TimeSpan(0, 0, 10)));
            onlyChannel.Verify(m => m.TxCommit(), Times.Once());
            onlyChannel.Verify(m => m.BasicPublish(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <IBasicProperties>(), It.IsAny <byte[]>()), Times.Once());

            // verify close() was never called on the channel
            var cachedChannelsTransactionalField = typeof(CachingConnectionFactory).GetField("cachedChannelsTransactional", BindingFlags.NonPublic | BindingFlags.Instance);
            var channels = (LinkedList <IChannelProxy>)cachedChannelsTransactionalField.GetValue(cachingConnectionFactory);

            Assert.AreEqual(0, channels.Count);

            container.Stop();
            container.Dispose();
            container = null;
        }
        private void DoTestRetry(int messageCount, int txSize, int failFrequency, int concurrentConsumers, bool stateful)
        {
            var failedMessageCount = messageCount / failFrequency + (messageCount % failFrequency == 0 ? 0 : 1);

            this.template = this.CreateTemplate(concurrentConsumers);
            for (var i = 0; i < messageCount; i++)
            {
                this.template.ConvertAndSend(queue.Name, i.ToString());
            }

            var container = new SimpleMessageListenerContainer(this.template.ConnectionFactory);
            var listener  = new RetryPocoListener(failFrequency);

            container.MessageListener     = new MessageListenerAdapter(listener);
            container.AcknowledgeMode     = AcknowledgeModeUtils.AcknowledgeMode.Auto;
            container.ChannelTransacted   = true;
            container.TxSize              = txSize;
            container.ConcurrentConsumers = concurrentConsumers;

            var latch = new CountdownEvent(failedMessageCount);

            // container.AdviceChain = new IAdvice[] { CreateRetryInterceptor(latch, stateful) };
            container.QueueNames = new[] { queue.Name };
            container.AfterPropertiesSet();
            container.Start();

            try
            {
                var timeout = Math.Min(1 + messageCount / concurrentConsumers, 30);

                var count = messageCount;
                Logger.Debug("Waiting for messages with timeout = " + timeout + " (s)");
                Task.Factory.StartNew(
                    () =>
                {
                    while (container.ActiveConsumerCount > 0)
                    {
                        try
                        {
                            Thread.Sleep(100);
                        }
                        catch (ThreadInterruptedException e)
                        {
                            if (latch.CurrentCount > 0)
                            {
                                latch.Signal();
                            }

                            Thread.CurrentThread.Interrupt();
                            return;
                        }
                    }

                    for (var i = 0; i < count; i++)
                    {
                        if (latch.CurrentCount > 0)
                        {
                            latch.Signal();
                        }
                    }
                });
                var waited = latch.Wait(timeout * 1000);
                Logger.Info("All messages recovered: " + waited);
                Assert.AreEqual(concurrentConsumers, container.ActiveConsumerCount);
                Assert.True(waited, "Timed out waiting for messages");

                // Retried each failure 3 times (default retry policy)...
                Assert.AreEqual(3 * failedMessageCount, listener.Count);

                // All failed messages recovered
                Assert.AreEqual(null, this.template.ReceiveAndConvert(queue.Name));
            }
            finally
            {
                container.Shutdown();
                Assert.AreEqual(0, container.ActiveConsumerCount);
            }
        }
        public void TestChannelAwareMessageListenerDontExpose()
        {
            var mockConnectionFactory = new Mock <ConnectionFactory>();
            var mockConnection        = new Mock <IConnection>();
            var firstChannel          = new Mock <IModel>();

            firstChannel.Setup(m => m.IsOpen).Returns(true);
            firstChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var secondChannel = new Mock <IModel>();

            secondChannel.Setup(m => m.IsOpen).Returns(true);
            secondChannel.Setup(m => m.CreateBasicProperties()).Returns(() => new BasicProperties());

            var singleConnectionFactory = new SingleConnectionFactory(mockConnectionFactory.Object);

            mockConnectionFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);
            mockConnection.Setup(m => m.IsOpen).Returns(true);

            var tooManyChannels = new BlockingCollection <Exception>(1);
            var done            = false;

            mockConnection.Setup(m => m.CreateModel()).Returns(
                () =>
            {
                if (!done)
                {
                    done = true;
                    return(firstChannel.Object);
                }

                return(secondChannel.Object);
            });

            var consumer = new BlockingCollection <IBasicConsumer>(1);

            firstChannel.Setup(m => m.BasicConsume(It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <IBasicConsumer>())).Callback <string, bool, IBasicConsumer>(
                (a1, a2, a3) => consumer.Add(a3));

            var commitLatch = new CountdownEvent(1);

            firstChannel.Setup(m => m.TxCommit()).Callback(() => commitLatch.Signal());

            var latch        = new CountdownEvent(1);
            var exposed      = new AtomicReference <IModel>();
            var container    = new SimpleMessageListenerContainer(singleConnectionFactory);
            var mockListener = new Mock <IChannelAwareMessageListener>();

            mockListener.Setup(m => m.OnMessage(It.IsAny <Message>(), It.IsAny <IModel>())).Callback <Message, IModel>(
                (message, channel) =>
            {
                exposed.LazySet(channel);
                var rabbitTemplate = new RabbitTemplate(singleConnectionFactory);
                rabbitTemplate.ChannelTransacted = true;

                // should use same channel as container
                rabbitTemplate.ConvertAndSend("foo", "bar", "baz");
                latch.Signal();
            });
            container.MessageListener = mockListener.Object;

            container.QueueNames            = new[] { "queue" };
            container.ChannelTransacted     = true;
            container.ExposeListenerChannel = false;
            container.ShutdownTimeout       = 100;
            container.AfterPropertiesSet();
            container.Start();

            IBasicConsumer currentConsumer;

            consumer.TryTake(out currentConsumer, timeout);
            Assert.IsNotNull(currentConsumer, "Timed out getting consumer.");
            currentConsumer.HandleBasicDeliver("qux", 1, false, "foo", "bar", new BasicProperties(), new byte[] { 0 });

            Assert.IsTrue(latch.Wait(new TimeSpan(0, 0, 10)));

            var e = tooManyChannels.Count;

            if (e > 0)
            {
                throw tooManyChannels.Take();
            }

            // once for listener, once for exposed + 0 for template (used bound)
            mockConnection.Verify(m => m.CreateModel(), Times.Exactly(2));
            Assert.IsTrue(commitLatch.Wait(new TimeSpan(0, 0, 10)));
            firstChannel.Verify(m => m.TxCommit(), Times.Once());
            secondChannel.Verify(m => m.TxCommit(), Times.Once());
            secondChannel.Verify(m => m.BasicPublish(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <IBasicProperties>(), It.IsAny <byte[]>()), Times.Once());

            Assert.AreSame(secondChannel.Object, exposed.Value);

            firstChannel.Verify(m => m.Close(), Times.Never());
            secondChannel.Verify(m => m.Close(), Times.Once());
            container.Stop();
        }