@Override
 public Object invoke(MethodInvocation invocation) throws Throwable {
   String id = null;
   Message message = null;
   boolean redelivered = false;
   try {
     message = (Message) invocation.getArguments()[1];
     MessageProperties messageProperties = message.getMessageProperties();
     if (messageProperties.getMessageId() == null) {
       id = UUID.randomUUID().toString();
       messageProperties.setMessageId(id);
     }
     redelivered = messageProperties.isRedelivered();
     return invocation.proceed();
   } catch (Exception e) {
     if (id != null && redelivered) {
       if (logger.isDebugEnabled()) {
         logger.debug("Canceling delivery of retried message that has no ID");
       }
       throw new ListenerExecutionFailedException(
           "Cannot retry message without an ID",
           new AmqpRejectAndDontRequeueException(e),
           message);
     } else {
       throw e;
     }
   } finally {
     if (id != null) {
       retryContextCache.remove(id);
     }
   }
 }
 /** Extract "standard" headers from an AMQP MessageProperties instance. */
 @Override
 protected Map<String, Object> extractStandardHeaders(MessageProperties amqpMessageProperties) {
   Map<String, Object> headers = new HashMap<String, Object>();
   try {
     String appId = amqpMessageProperties.getAppId();
     if (StringUtils.hasText(appId)) {
       headers.put(AmqpHeaders.APP_ID, appId);
     }
     String clusterId = amqpMessageProperties.getClusterId();
     if (StringUtils.hasText(clusterId)) {
       headers.put(AmqpHeaders.CLUSTER_ID, clusterId);
     }
     String contentEncoding = amqpMessageProperties.getContentEncoding();
     if (StringUtils.hasText(contentEncoding)) {
       headers.put(AmqpHeaders.CONTENT_ENCODING, contentEncoding);
     }
     long contentLength = amqpMessageProperties.getContentLength();
     if (contentLength > 0) {
       headers.put(AmqpHeaders.CONTENT_LENGTH, contentLength);
     }
     String contentType = amqpMessageProperties.getContentType();
     if (StringUtils.hasText(contentType)) {
       headers.put(AmqpHeaders.CONTENT_TYPE, contentType);
     }
     byte[] correlationId = amqpMessageProperties.getCorrelationId();
     if (correlationId != null && correlationId.length > 0) {
       headers.put(AmqpHeaders.CORRELATION_ID, correlationId);
     }
     MessageDeliveryMode deliveryMode = amqpMessageProperties.getDeliveryMode();
     if (deliveryMode != null) {
       headers.put(AmqpHeaders.DELIVERY_MODE, deliveryMode);
     }
     long deliveryTag = amqpMessageProperties.getDeliveryTag();
     if (deliveryTag > 0) {
       headers.put(AmqpHeaders.DELIVERY_TAG, deliveryTag);
     }
     String expiration = amqpMessageProperties.getExpiration();
     if (StringUtils.hasText(expiration)) {
       headers.put(AmqpHeaders.EXPIRATION, expiration);
     }
     Integer messageCount = amqpMessageProperties.getMessageCount();
     if (messageCount != null && messageCount > 0) {
       headers.put(AmqpHeaders.MESSAGE_COUNT, messageCount);
     }
     String messageId = amqpMessageProperties.getMessageId();
     if (StringUtils.hasText(messageId)) {
       headers.put(AmqpHeaders.MESSAGE_ID, messageId);
     }
     Integer priority = amqpMessageProperties.getPriority();
     if (priority != null && priority > 0) {
       headers.put(MessageHeaders.PRIORITY, priority);
     }
     String receivedExchange = amqpMessageProperties.getReceivedExchange();
     if (StringUtils.hasText(receivedExchange)) {
       headers.put(AmqpHeaders.RECEIVED_EXCHANGE, receivedExchange);
     }
     String receivedRoutingKey = amqpMessageProperties.getReceivedRoutingKey();
     if (StringUtils.hasText(receivedRoutingKey)) {
       headers.put(AmqpHeaders.RECEIVED_ROUTING_KEY, receivedRoutingKey);
     }
     Boolean redelivered = amqpMessageProperties.isRedelivered();
     if (redelivered != null) {
       headers.put(AmqpHeaders.REDELIVERED, redelivered);
     }
     String replyTo = amqpMessageProperties.getReplyTo();
     if (replyTo != null) {
       headers.put(AmqpHeaders.REPLY_TO, replyTo);
     }
     Date timestamp = amqpMessageProperties.getTimestamp();
     if (timestamp != null) {
       headers.put(AmqpHeaders.TIMESTAMP, timestamp);
     }
     String type = amqpMessageProperties.getType();
     if (StringUtils.hasText(type)) {
       headers.put(AmqpHeaders.TYPE, type);
     }
     String userId = amqpMessageProperties.getUserId();
     if (StringUtils.hasText(userId)) {
       headers.put(AmqpHeaders.USER_ID, userId);
     }
     Object replyCorrelation =
         amqpMessageProperties.getHeaders().get(AmqpHeaders.STACKED_CORRELATION_HEADER);
     if (replyCorrelation instanceof String) {
       if (StringUtils.hasText((String) replyCorrelation)) {
         headers.put(AmqpHeaders.SPRING_REPLY_CORRELATION, replyCorrelation);
       }
     }
     Object replyToStack =
         amqpMessageProperties.getHeaders().get(AmqpHeaders.STACKED_REPLY_TO_HEADER);
     if (replyToStack instanceof String) {
       if (StringUtils.hasText((String) replyToStack)) {
         headers.put(AmqpHeaders.SPRING_REPLY_TO_STACK, replyToStack);
       }
     }
   } catch (Exception e) {
     if (logger.isWarnEnabled()) {
       logger.warn("error occurred while mapping from AMQP properties to MessageHeaders", e);
     }
   }
   return headers;
 }