diff --git a/README.adoc b/README.adoc index 8bf85c9d5..6636bbb2c 100644 --- a/README.adoc +++ b/README.adoc @@ -889,9 +889,13 @@ Applies only when `requiredGroups` are provided and then only to those groups. Default: none - broker default will apply. routingKeyExpression:: A SpEL expression to determine the routing key to use when publishing messages. -For a fixed routing key, use a literal expression, such as `routingKeyExpression='my.routingKey'` in a properties file or `routingKeyExpression: '''my.routingKey'''` in a YAML file. +For a fixed routing key, use `routingKey`. + Default: `destination` or `destination-` for partitioned destinations. +routingKey:: +A string defining a fixed routing key to use when publishing messages. ++ +Default: see `routingKeyExpression` singleActiveConsumer:: Set to true to set the `x-single-active-consumer` queue property to true. Applies only when `requiredGroups` are provided and then only to those groups. diff --git a/docs/src/main/asciidoc/overview.adoc b/docs/src/main/asciidoc/overview.adoc index b06d65cb2..be7db5f23 100644 --- a/docs/src/main/asciidoc/overview.adoc +++ b/docs/src/main/asciidoc/overview.adoc @@ -928,9 +928,13 @@ Applies only when `requiredGroups` are provided and then only to those groups. Default: none - broker default will apply. routingKeyExpression:: A SpEL expression to determine the routing key to use when publishing messages. -For a fixed routing key, use a literal expression, such as `routingKeyExpression='my.routingKey'` in a properties file or `routingKeyExpression: '''my.routingKey'''` in a YAML file. +For a fixed routing key, use `routingKey`. + Default: `destination` or `destination-` for partitioned destinations. +routingKey:: +A string defining a fixed routing key to use when publishing messages. ++ +Default: see `routingKeyExpression` singleActiveConsumer:: Set to true to set the `x-single-active-consumer` queue property to true. Applies only when `requiredGroups` are provided and then only to those groups. diff --git a/spring-cloud-stream-binder-rabbit-core/src/main/java/org/springframework/cloud/stream/binder/rabbit/properties/RabbitProducerProperties.java b/spring-cloud-stream-binder-rabbit-core/src/main/java/org/springframework/cloud/stream/binder/rabbit/properties/RabbitProducerProperties.java index 81af376ee..7b8246e09 100644 --- a/spring-cloud-stream-binder-rabbit-core/src/main/java/org/springframework/cloud/stream/binder/rabbit/properties/RabbitProducerProperties.java +++ b/spring-cloud-stream-binder-rabbit-core/src/main/java/org/springframework/cloud/stream/binder/rabbit/properties/RabbitProducerProperties.java @@ -16,12 +16,17 @@ package org.springframework.cloud.stream.binder.rabbit.properties; +import java.util.Optional; + import jakarta.validation.constraints.Min; import org.springframework.amqp.core.MessageDeliveryMode; import org.springframework.expression.Expression; +import org.springframework.expression.common.LiteralExpression; import org.springframework.util.Assert; + + /** * @author Marius Bogoevici * @author Gary Russell @@ -102,6 +107,12 @@ public class RabbitProducerProperties extends RabbitCommonProperties { */ private Expression delayExpression; + /** + * a static routing key when publishing messages; default is the destination name; + * suffixed by "-partition" when partitioned. This is only used if `routingKeyExpression` is null + */ + private String routingKey; + /** * a custom routing key when publishing messages; default is the destination name; * suffixed by "-partition" when partitioned. @@ -232,13 +243,24 @@ public class RabbitProducerProperties extends RabbitCommonProperties { } public Expression getRoutingKeyExpression() { - return this.routingKeyExpression; + return Optional.ofNullable(this.routingKeyExpression) + .orElseGet(() -> Optional.ofNullable(this.routingKey) + .map(LiteralExpression::new) + .orElse(null)); } public void setRoutingKeyExpression(Expression routingKeyExpression) { this.routingKeyExpression = routingKeyExpression; } + public String getRoutingKey() { + return this.routingKey; + } + + public void setRoutingKey(String routingKey) { + this.routingKey = routingKey; + } + public String getConfirmAckChannel() { return this.confirmAckChannel; } diff --git a/spring-cloud-stream-binder-rabbit/src/test/java/org/springframework/cloud/stream/binder/rabbit/RabbitBinderTests.java b/spring-cloud-stream-binder-rabbit/src/test/java/org/springframework/cloud/stream/binder/rabbit/RabbitBinderTests.java index 917e46a23..de40c4de8 100644 --- a/spring-cloud-stream-binder-rabbit/src/test/java/org/springframework/cloud/stream/binder/rabbit/RabbitBinderTests.java +++ b/spring-cloud-stream-binder-rabbit/src/test/java/org/springframework/cloud/stream/binder/rabbit/RabbitBinderTests.java @@ -2064,6 +2064,38 @@ public class RabbitBinderTests extends producerBinding.unbind(); } + @Test + public void testRoutingKey(TestInfo testInfo) throws Exception { + String routingKey = "static.key"; + RabbitTestBinder binder = getBinder(); + ExtendedProducerProperties producerProperties = createProducerProperties(testInfo); + producerProperties.getExtension().setRoutingKey(routingKey); + + DirectChannel output = createBindableChannel("output", + createProducerBindingProperties(producerProperties)); + output.setBeanName("rkeProducer"); + Binding producerBinding = binder.bindProducer("rke", output, + producerProperties); + + RabbitAdmin admin = new RabbitAdmin(this.rabbitAvailableRule.getResource()); + Queue queue = new AnonymousQueue(); + DirectExchange exchange = new DirectExchange("rke"); + org.springframework.amqp.core.Binding binding = BindingBuilder.bind(queue) + .to(exchange).with(routingKey); + admin.declareQueue(queue); + admin.declareBinding(binding); + + output.send(new GenericMessage<>(new Pojo("rkeTest"))); + + Object out = spyOn(queue.getName()).receive(false); + assertThat(out).isInstanceOf(byte[].class); + assertThat(new String((byte[]) out, StandardCharsets.UTF_8)) + .isEqualTo("{\"field\":\"rkeTest\"}"); + + + producerBinding.unbind(); + } + @Test public void testRoutingKeyExpressionPartitionedAndDelay(TestInfo testInfo) throws Exception { RabbitTestBinder binder = getBinder();