title: spring amqp enable retry by default and prevent it according to a specified exception
body: <p>In case of Exception A : retrying for finite number of times and finally when number of retrials exhausted, message is written in a dead letter queue</p>
  
  <p>In case of Exception B : simply, message should be written to dead letter queue</p>
  
  <p>I am trying to implement the same use case as in and i have followed all the steps as per correct answer, still i see my custom exception getting wrapped into ListenerExecutionFailedException. I am unable to get it stop retrying on a custom exception.</p>
  
  <p>I have followed steps in below answers <a href="https://stackoverflow.com/questions/39272648/spring-amqp-enable-retry-by-configuration-and-prevent-it-according-to-a-specifie/39272873#39272873">spring amqp enable retry by configuration and prevent it according to a specified exception</a></p>
  
  <p>and </p>
  
  <p><a href="https://stackoverflow.com/questions/39853762/spring-rabbit-retries-to-deliver-rejected-message-is-it-ok">Spring rabbit retries to deliver rejected message..is it OK?</a></p>
  
  <pre><code>
  @Bean
      public SimpleRetryPolicy rejectionRetryPolicy(){
          Map&lt;Class&lt;? extends Throwable&gt; , Boolean&gt; exceptionsMap = new HashMap&lt;Class&lt;? extends Throwable&gt; , Boolean&gt;();        
          exceptionsMap.put(AmqpRejectAndDontRequeueException.class, false);//not retriable
          exceptionsMap.put(ListenerExecutionFailedException.class, true); //retriable
          SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3 , exceptionsMap ,true);
          return retryPolicy;
      }
  
      @Bean
      public RetryOperationsInterceptor workMessagesRetryInterceptor() {
          return RetryInterceptorBuilder.stateless().retryPolicy(rejectionRetryPolicy())
  
                  //.backOffOptions(1000, 2, 10000)
                  .recoverer(new RepublishMessageRecoverer(defaultTemplate, this.getDlqExchange(), this.getDlqroutingkey()))
                  .build();
      }
  
  
  /* My Rabbit MQ Error handler */
  
  @Component
  public class RabbitRetryHandler implements RabbitListenerErrorHandler {
  
      private static final Logger log = LoggerFactory.getLogger(RabbitRetryHandler.class);
  
      @Override
      public Object handleError(Message amqpMessage, org.springframework.messaging.Message&lt;?&gt; message,
              ListenerExecutionFailedException exception) throws Exception {      
          if (amqpMessage.getMessageProperties().isRedelivered() || exception.getCause().getMessage().equals("DontRetry")) {          
              throw new AmqpRejectAndDontRequeueException(exception.getCause());
          } else {
              throw exception;
          }
      }
  }
  
  /* And finally my Listener */
  
  @Override
      @RabbitListener(queues = "${queueconfig.queuename}",containerFactory = "sdRabbitListenerContainerFactory",errorHandler="rabbitRetryHandler")
      public void processMessage(Message incomingMsg) throws Exception {
          log.info("{} - Correlation ID: {} Received message: {} from {} queue.", Thread.currentThread().getId(),
                  incomingMsg.getMessageProperties().getCorrelationId(), new String(incomingMsg.getBody()),
                  incomingMsg.getMessageProperties().getConsumerQueue());
          try {
              performAction();
          } catch(CustomDontRequeueException cex) {
              throw cex;
          } catch (Exception ex) {
              throw ex;
          }
      }
  
  
  @Override
      public void performAction() throws Exception {
          try {
  
          } catch (HttpClientErrorException ex) {
              if (ex.getStatusCode() == HttpStatus.NOT_FOUND || ex.getStatusCode() == HttpStatus.REQUEST_TIMEOUT) {
  
                  throw new RuntimeException(ex);
              } else {
                  throw new CustomDontRequeueException("DontRetry",ex);
              }
          }catch (Exception e) {          
              throw new CustomDontRequeueException(e);
          } 
  
      }
  </code></pre>
  
  <p>Expected Result, if CustomDontRequeueException is thrown it should not requeue the message.</p>
  
  <p>Actual Result, message gets requeued irrespective of what exception it is for n number of times and then dropped to DLQ.</p>