private Message<?> sendAndReceive(
      String exchangeName,
      String routingKey,
      Message<?> requestMessage,
      CorrelationData correlationData) {
    Assert.isInstanceOf(
        RabbitTemplate.class,
        this.amqpTemplate,
        "RabbitTemplate implementation is required for publisher confirms");
    MessageConverter converter = ((RabbitTemplate) this.amqpTemplate).getMessageConverter();
    MessageProperties amqpMessageProperties = new MessageProperties();
    org.springframework.amqp.core.Message amqpMessage =
        converter.toMessage(requestMessage.getPayload(), amqpMessageProperties);
    this.headerMapper.fromHeadersToRequest(requestMessage.getHeaders(), amqpMessageProperties);
    checkDeliveryMode(requestMessage, amqpMessageProperties);
    org.springframework.amqp.core.Message amqpReplyMessage =
        ((RabbitTemplate) this.amqpTemplate)
            .sendAndReceive(exchangeName, routingKey, amqpMessage, correlationData);

    if (amqpReplyMessage == null) {
      return null;
    }
    Object replyObject = converter.fromMessage(amqpReplyMessage);
    AbstractIntegrationMessageBuilder<?> builder =
        (replyObject instanceof Message)
            ? this.getMessageBuilderFactory().fromMessage((Message<?>) replyObject)
            : this.getMessageBuilderFactory().withPayload(replyObject);
    Map<String, ?> headers =
        this.headerMapper.toHeadersFromReply(amqpReplyMessage.getMessageProperties());
    builder.copyHeadersIfAbsent(headers);
    return builder.build();
  }
 /**
  * Build a Rabbit message to be sent as response based on the given result object.
  *
  * @param channel the Rabbit Channel to operate on
  * @param result the content of the message, as returned from the listener method
  * @return the Rabbit <code>Message</code> (never <code>null</code>)
  * @throws Exception if thrown by Rabbit API methods
  * @see #setMessageConverter
  */
 @Override
 protected org.springframework.amqp.core.Message buildMessage(Channel channel, Object result)
     throws Exception {
   MessageConverter converter = getMessageConverter();
   if (converter != null && !(result instanceof org.springframework.amqp.core.Message)) {
     if (result instanceof org.springframework.messaging.Message) {
       return this.messagingMessageConverter.toMessage(result, new MessageProperties());
     } else {
       return converter.toMessage(result, new MessageProperties());
     }
   } else {
     if (!(result instanceof org.springframework.amqp.core.Message)) {
       throw new MessageConversionException(
           "No MessageConverter specified - cannot handle message [" + result + "]");
     }
     return (org.springframework.amqp.core.Message) result;
   }
 }
 @Override
 public void returnedMessage(
     org.springframework.amqp.core.Message message,
     int replyCode,
     String replyText,
     String exchange,
     String routingKey) {
   // safe to cast; we asserted we have a RabbitTemplate in doInit()
   MessageConverter converter = ((RabbitTemplate) this.amqpTemplate).getMessageConverter();
   Object returnedObject = converter.fromMessage(message);
   AbstractIntegrationMessageBuilder<?> builder =
       (returnedObject instanceof Message)
           ? this.getMessageBuilderFactory().fromMessage((Message<?>) returnedObject)
           : this.getMessageBuilderFactory().withPayload(returnedObject);
   Map<String, ?> headers = this.headerMapper.toHeadersFromReply(message.getMessageProperties());
   builder
       .copyHeadersIfAbsent(headers)
       .setHeader(AmqpHeaders.RETURN_REPLY_CODE, replyCode)
       .setHeader(AmqpHeaders.RETURN_REPLY_TEXT, replyText)
       .setHeader(AmqpHeaders.RETURN_EXCHANGE, exchange)
       .setHeader(AmqpHeaders.RETURN_ROUTING_KEY, routingKey);
   this.returnChannel.send(builder.build());
 }