Skip to content

Commit 53c9150

Browse files
garyrussellartembilan
authored andcommitted
GH-1108: @QueueBinding.key recursive resolution
Fixes #1108 `@RabbitListener.queues()` resolves `String[]` recursively. AMQP-722 added support for multiple routing keys to `@queueBinding` but did not add support for recursive resolution. This is required to support constructs like `key = "#{'${my-app.amqp.routing-key}'.split(',')}"`. **cherry-pick to 2.1.x** # Conflicts: # spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/RabbitListenerAnnotationBeanPostProcessorTests.java Fix test
1 parent a69920d commit 53c9150

File tree

2 files changed

+21
-16
lines changed

2 files changed

+21
-16
lines changed

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/annotation/RabbitListenerAnnotationBeanPostProcessor.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ private String[] resolveQueues(RabbitListener rabbitListener) {
503503
List<String> result = new ArrayList<String>();
504504
if (queues.length > 0) {
505505
for (int i = 0; i < queues.length; i++) {
506-
resolveAsString(resolveExpression(queues[i]), result);
506+
resolveAsString(resolveExpression(queues[i]), result, true, "queues");
507507
}
508508
}
509509
if (queuesToDeclare.length > 0) {
@@ -526,25 +526,28 @@ private String[] resolveQueues(RabbitListener rabbitListener) {
526526
}
527527

528528
@SuppressWarnings("unchecked")
529-
private void resolveAsString(Object resolvedValue, List<String> result) {
529+
private void resolveAsString(Object resolvedValue, List<String> result, boolean canBeQueue, String what) {
530530
Object resolvedValueToUse = resolvedValue;
531531
if (resolvedValue instanceof String[]) {
532532
resolvedValueToUse = Arrays.asList((String[]) resolvedValue);
533533
}
534-
if (resolvedValueToUse instanceof Queue) {
534+
if (canBeQueue && resolvedValueToUse instanceof Queue) {
535535
result.add(((Queue) resolvedValueToUse).getName());
536536
}
537537
else if (resolvedValueToUse instanceof String) {
538538
result.add((String) resolvedValueToUse);
539539
}
540540
else if (resolvedValueToUse instanceof Iterable) {
541541
for (Object object : (Iterable<Object>) resolvedValueToUse) {
542-
resolveAsString(object, result);
542+
resolveAsString(object, result, canBeQueue, what);
543543
}
544544
}
545545
else {
546546
throw new IllegalArgumentException(String.format(
547-
"@RabbitListener can't resolve '%s' as either a String or a Queue",
547+
"@RabbitListener."
548+
+ what
549+
+ " can't resolve '%s' as a String[] or a String "
550+
+ (canBeQueue ? "or a Queue" : ""),
548551
resolvedValue));
549552
}
550553
}
@@ -632,15 +635,15 @@ private void declareExchangeAndBinding(QueueBinding binding, String queueName) {
632635
}
633636

634637
private void registerBindings(QueueBinding binding, String queueName, String exchangeName, String exchangeType) {
635-
final String[] routingKeys;
638+
final List<String> routingKeys;
636639
if (exchangeType.equals(ExchangeTypes.FANOUT) || binding.key().length == 0) {
637-
routingKeys = new String[] { "" };
640+
routingKeys = Collections.singletonList("");
638641
}
639642
else {
640643
final int length = binding.key().length;
641-
routingKeys = new String[length];
644+
routingKeys = new ArrayList<>();
642645
for (int i = 0; i < length; ++i) {
643-
routingKeys[i] = resolveExpressionAsString(binding.key()[i], "@QueueBinding.key");
646+
resolveAsString(resolveExpression(binding.key()[i]), routingKeys, false, "@QueueBinding.key");
644647
}
645648
}
646649
final Map<String, Object> bindingArguments = resolveArguments(binding.arguments());

spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/RabbitListenerAnnotationBeanPostProcessorTests.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ public void invalidValueInAnnotationTestBean() {
208208
catch (BeanCreationException e) {
209209
assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
210210
assertThat(e.getMessage(), allOf(
211-
containsString("@RabbitListener can't resolve"),
212-
containsString("as either a String or a Queue")
211+
containsString("@RabbitListener.queues can't resolve"),
212+
containsString("as a String[] or a String or a Queue")
213213
));
214214
}
215215
}
@@ -233,10 +233,11 @@ public void multipleRoutingKeysTestBean() {
233233
assertThat(context.getBeansOfType(org.springframework.amqp.core.Exchange.class).values(), hasSize(1));
234234

235235
final List<Binding> bindings = new ArrayList<>(context.getBeansOfType(Binding.class).values());
236-
assertThat(bindings, hasSize(2));
236+
assertThat(bindings, hasSize(3));
237237
bindings.sort(Comparator.comparing(Binding::getRoutingKey));
238-
assertEquals("Binding [destination=my_queue, exchange=my_exchange, routingKey=red]", bindings.get(0).toString());
239-
assertEquals("Binding [destination=my_queue, exchange=my_exchange, routingKey=yellow]", bindings.get(1).toString());
238+
assertEquals("Binding [destination=my_queue, exchange=my_exchange, routingKey=green]", bindings.get(0).toString());
239+
assertEquals("Binding [destination=my_queue, exchange=my_exchange, routingKey=red]", bindings.get(1).toString());
240+
assertEquals("Binding [destination=my_queue, exchange=my_exchange, routingKey=yellow]", bindings.get(2).toString());
240241

241242
context.close();
242243
}
@@ -394,8 +395,9 @@ public void handleIt(String body) {
394395
static class MultipleRoutingKeysTestBean {
395396

396397
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange("my_exchange"),
397-
value = @org.springframework.amqp.rabbit.annotation.Queue(value = "my_queue", arguments = @Argument(name = "foo", value = "bar")),
398-
key = {"${xxxxxxx:red}", "yellow"}))
398+
value = @org.springframework.amqp.rabbit.annotation.Queue(value = "my_queue",
399+
arguments = @Argument(name = "foo", value = "bar")),
400+
key = {"${xxxxxxx:red}", "#{'yellow,green'.split(',')}"}))
399401
public void handleIt(String body) {
400402
}
401403
}

0 commit comments

Comments
 (0)