Improve RabbitAmqpUtils.toAmqpMessage()

The `RabbitAmqpUtils.toAmqpMessage()` utility is used on the publisher side,
so, it is natural to treat such a message as a reply.
Therefore, the `correlationId` is set to `messageId` of `correlationId` is not present.
The `replyTo` of the Spring message is set into `to` of the AMQP message

* Mention in the `Address` JavaDocs that just `routingKey` can be treated differently by clients
* Fix error message in the `RabbitAmqpMessageListenerAdapter`
This commit is contained in:
Artem Bilan
2025-03-10 10:29:53 -04:00
parent 355be1ee4c
commit b6b61c4cfe
3 changed files with 21 additions and 11 deletions

View File

@@ -23,8 +23,8 @@ import java.util.regex.Pattern;
import org.springframework.util.StringUtils;
/**
* Represents an address for publication of an AMQP message. The AMQP 0-8 and 0-9
* specifications have an unstructured string that is used as a "reply to" address.
* Represents an address for publication of an AMQP message. The AMQP 0.9
* specification has an unstructured string that is used as a "reply to" address.
* There are however conventions in use and this class makes it easier to
* follow these conventions, which can be easily summarised as:
*
@@ -33,7 +33,10 @@ import org.springframework.util.StringUtils;
* </pre>
*
* Here we also the exchange name to default to empty
* (so just a routing key will work if you know the queue name).
* (so just a routing key will work as a queue name).
* <p>
* For AMQP 1.0, only routing key is treated as target destination.
*
*
* @author Mark Pollack
* @author Mark Fisher
@@ -58,11 +61,11 @@ public class Address {
/**
* Create an Address instance from a structured String with the form
*
* <pre class="code">
* (exchange)/(routingKey)
* </pre>
* .
* If exchange is parsed to empty string, then routing key is treated as a queue name.
* @param address a structured string.
*/
public Address(String address) {
@@ -120,9 +123,9 @@ public class Address {
@Override
public int hashCode() {
int result = this.exchangeName != null ? this.exchangeName.hashCode() : 0;
int result = this.exchangeName.hashCode();
int prime = 31; // NOSONAR magic #
result = prime * result + (this.routingKey != null ? this.routingKey.hashCode() : 0);
result = prime * result + this.routingKey.hashCode();
return result;
}

View File

@@ -19,6 +19,7 @@ package org.springframework.amqp.rabbitmq.client;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import com.rabbitmq.client.amqp.Consumer;
@@ -72,8 +73,12 @@ public final class RabbitAmqpUtils {
}
/**
* Convert {@link com.rabbitmq.client.amqp.Message} into {@link Message}.
* @param amqpMessage the {@link com.rabbitmq.client.amqp.Message} convert from.
* Convert {@link Message} into {@link com.rabbitmq.client.amqp.Message}.
* The {@link MessageProperties#getReplyTo()} is set into {@link com.rabbitmq.client.amqp.Message#to(String)}.
* The {@link com.rabbitmq.client.amqp.Message#correlationId(long)} is set to
* {@link MessageProperties#getCorrelationId()} if present, or to {@link MessageProperties#getMessageId()}.
* @param message the {@link Message} convert from.
* @param amqpMessage the {@link com.rabbitmq.client.amqp.Message} convert into.
*/
public static void toAmqpMessage(Message message, com.rabbitmq.client.amqp.Message amqpMessage) {
MessageProperties messageProperties = message.getMessageProperties();
@@ -83,9 +88,11 @@ public final class RabbitAmqpUtils {
.contentEncoding(messageProperties.getContentEncoding())
.contentType(messageProperties.getContentType())
.messageId(messageProperties.getMessageId())
.correlationId(messageProperties.getCorrelationId())
.correlationId(
Objects.requireNonNullElse(
messageProperties.getCorrelationId(), messageProperties.getMessageId()))
.priority(messageProperties.getPriority().byteValue())
.replyTo(messageProperties.getReplyTo());
.to(messageProperties.getReplyTo());
Map<String, @Nullable Object> headers = messageProperties.getHeaders();
if (!headers.isEmpty()) {

View File

@@ -120,7 +120,7 @@ public class RabbitAmqpMessageListenerAdapter extends MessagingMessageListenerAd
InvocationResult result = getHandlerAdapter()
.invoke(converted, amqpAcknowledgment);
if (result.getReturnValue() != null) {
logger.warn("Replies are not currently supported with RabbitMQ AMQP 1.0 listeners");
logger.warn("Replies for batches are not currently supported with RabbitMQ AMQP 1.0 listeners");
}
}
catch (Exception ex) {