11/*
2- * Copyright 2002-2017 the original author or authors.
2+ * Copyright 2002-2018 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
135135 * @author Gary Russell
136136 * @author Artem Bilan
137137 * @author Ernest Sadykov
138+ * @author Mark Norkin
138139 * @since 1.0
139140 */
140141public class RabbitTemplate extends RabbitAccessor implements BeanFactoryAware , RabbitOperations , MessageListener ,
@@ -341,7 +342,7 @@ public String getEncoding() {
341342 * exchange and routing key.
342343 * @param replyAddress the replyAddress to set
343344 */
344- public void setReplyAddress (String replyAddress ) {
345+ public synchronized void setReplyAddress (String replyAddress ) {
345346 this .replyAddress = replyAddress ;
346347 this .evaluatedFastReplyTo = false ;
347348 }
@@ -726,13 +727,11 @@ public Collection<String> expectedQueueNames() {
726727 */
727728 public Collection <CorrelationData > getUnconfirmed (long age ) {
728729 Set <CorrelationData > unconfirmed = new HashSet <>();
729- synchronized (this .publisherConfirmChannels ) {
730- long cutoffTime = System .currentTimeMillis () - age ;
731- for (Channel channel : this .publisherConfirmChannels .keySet ()) {
732- Collection <PendingConfirm > confirms = ((PublisherCallbackChannel ) channel ).expire (this , cutoffTime );
733- for (PendingConfirm confirm : confirms ) {
734- unconfirmed .add (confirm .getCorrelationData ());
735- }
730+ long cutoffTime = System .currentTimeMillis () - age ;
731+ for (Channel channel : this .publisherConfirmChannels .keySet ()) {
732+ Collection <PendingConfirm > confirms = ((PublisherCallbackChannel ) channel ).expire (this , cutoffTime );
733+ for (PendingConfirm confirm : confirms ) {
734+ unconfirmed .add (confirm .getCorrelationData ());
736735 }
737736 }
738737 return unconfirmed .size () > 0 ? unconfirmed : null ;
@@ -744,12 +743,10 @@ public Collection<CorrelationData> getUnconfirmed(long age) {
744743 * @since 2.0
745744 */
746745 public int getUnconfirmedCount () {
747- synchronized (this .publisherConfirmChannels ) {
748- return this .publisherConfirmChannels .keySet ()
749- .stream ()
750- .mapToInt (channel -> ((PublisherCallbackChannel ) channel ).getPendingConfirmsCount (this ))
751- .sum ();
752- }
746+ return this .publisherConfirmChannels .keySet ()
747+ .stream ()
748+ .mapToInt (channel -> ((PublisherCallbackChannel ) channel ).getPendingConfirmsCount (this ))
749+ .sum ();
753750 }
754751
755752 @ Override
@@ -788,11 +785,9 @@ protected void doStop() {
788785 @ Override
789786 public boolean isRunning () {
790787 synchronized (this .directReplyToContainers ) {
791- synchronized (this .directReplyToContainers ) {
792- return this .directReplyToContainers .values ()
793- .stream ()
794- .anyMatch (AbstractMessageListenerContainer ::isRunning );
795- }
788+ return this .directReplyToContainers .values ()
789+ .stream ()
790+ .anyMatch (AbstractMessageListenerContainer ::isRunning );
796791 }
797792 }
798793
@@ -1138,19 +1133,18 @@ public <R, S> boolean receiveAndReply(String queueName, ReceiveAndReplyCallback<
11381133 private <R , S > boolean doReceiveAndReply (final String queueName , final ReceiveAndReplyCallback <R , S > callback ,
11391134 final ReplyToAddressCallback <S > replyToAddressCallback ) throws AmqpException {
11401135 return execute (channel -> {
1141- Message receiveMessage = null ;
1142-
1143- receiveMessage = receiveForReply (queueName , channel , receiveMessage );
1136+ Message receiveMessage = receiveForReply (queueName , channel );
11441137 if (receiveMessage != null ) {
11451138 return sendReply (callback , replyToAddressCallback , channel , receiveMessage );
11461139 }
11471140 return false ;
11481141 }, obtainTargetConnectionFactory (this .receiveConnectionFactorySelectorExpression , queueName ));
11491142 }
11501143
1151- private Message receiveForReply (final String queueName , Channel channel , Message receiveMessage ) throws Exception {
1144+ private Message receiveForReply (final String queueName , Channel channel ) throws Exception {
11521145 boolean channelTransacted = isChannelTransacted ();
11531146 boolean channelLocallyTransacted = isChannelLocallyTransacted (channel );
1147+ Message receiveMessage = null ;
11541148 if (RabbitTemplate .this .receiveTimeout == 0 ) {
11551149 GetResponse response = channel .basicGet (queueName , !channelTransacted );
11561150 // Response can be null in the case that there is no message on the queue.
@@ -1189,7 +1183,7 @@ else if (channelTransacted) {
11891183
11901184 private Delivery consumeDelivery (Channel channel , String queueName , long timeoutMillis ) throws Exception {
11911185 Delivery delivery = null ;
1192- Throwable exception = null ;
1186+ RuntimeException exception = null ;
11931187 CompletableFuture <Delivery > future = new CompletableFuture <>();
11941188 DefaultConsumer consumer = createConsumer (queueName , channel , future ,
11951189 timeoutMillis < 0 ? DEFAULT_CONSUME_TIMEOUT : timeoutMillis );
@@ -1202,34 +1196,20 @@ private Delivery consumeDelivery(Channel channel, String queueName, long timeout
12021196 }
12031197 }
12041198 catch (ExecutionException e ) {
1205- this .logger .error ("Consumer failed to receive message: " + consumer , e .getCause ());
1206- exception = e .getCause ();
1199+ Throwable cause = e .getCause ();
1200+ this .logger .error ("Consumer failed to receive message: " + consumer , cause );
1201+ exception = RabbitExceptionTranslator .convertRabbitAccessException (cause );
1202+ throw exception ;
12071203 }
12081204 catch (InterruptedException e ) {
12091205 Thread .currentThread ().interrupt ();
12101206 }
12111207 catch (TimeoutException e ) {
12121208 // no result in time
12131209 }
1214- try {
1210+ finally {
12151211 if (exception == null || !(exception instanceof ConsumerCancelledException )) {
1216- channel .basicCancel (consumer .getConsumerTag ());
1217- }
1218- }
1219- catch (Exception e ) {
1220- if (this .logger .isDebugEnabled ()) {
1221- this .logger .debug ("Failed to cancel consumer: " + consumer , e );
1222- }
1223- }
1224- if (exception != null ) {
1225- if (exception instanceof RuntimeException ) {
1226- throw (RuntimeException ) exception ;
1227- }
1228- else if (exception instanceof Error ) {
1229- throw (Error ) exception ;
1230- }
1231- else {
1232- throw new AmqpException (exception );
1212+ cancelConsumerQuietly (channel , consumer );
12331213 }
12341214 }
12351215 return delivery ;
@@ -1606,16 +1586,23 @@ public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProp
16061586 }
16071587 finally {
16081588 this .replyHolder .remove (messageTag );
1609- try {
1610- channel .basicCancel (consumerTag );
1611- }
1612- catch (Exception e ) {
1613- }
1589+ cancelConsumerQuietly (channel , consumer );
16141590 }
16151591 return reply ;
16161592 }, obtainTargetConnectionFactory (this .sendConnectionFactorySelectorExpression , message ));
16171593 }
16181594
1595+ private void cancelConsumerQuietly (Channel channel , DefaultConsumer consumer ) {
1596+ try {
1597+ channel .basicCancel (consumer .getConsumerTag ());
1598+ }
1599+ catch (Exception e ) {
1600+ if (this .logger .isDebugEnabled ()) {
1601+ this .logger .debug ("Failed to cancel consumer: " + consumer , e );
1602+ }
1603+ }
1604+ }
1605+
16191606 protected Message doSendAndReceiveWithFixed (final String exchange , final String routingKey , final Message message ,
16201607 final CorrelationData correlationData ) {
16211608 Assert .state (this .isListener , () -> "RabbitTemplate is not configured as MessageListener - "
0 commit comments