From 0d01390e1661abdc25b2ecc87c5b6ed0d69bc2a2 Mon Sep 17 00:00:00 2001 From: Pascal Dal Farra Date: Sun, 10 Sep 2023 13:55:51 +0200 Subject: [PATCH 1/7] fix: Also take into account RabbitListener.queuesToDeclare --- .../annotation/RabbitListenerUtil.java | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java index 26d492c6c..25a3a78e0 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java @@ -26,6 +26,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.lang3.ArrayUtils; + @Slf4j public class RabbitListenerUtil { private static final Boolean DEFAULT_AUTO_DELETE = false; @@ -34,13 +36,12 @@ public class RabbitListenerUtil { private static final String DEFAULT_EXCHANGE_TYPE = ExchangeTypes.DIRECT; public static String getChannelName(RabbitListener annotation, StringValueResolver resolver) { - Stream annotationQueueNames = Arrays.stream(annotation.queues()); Stream annotationBindingChannelNames = Arrays.stream(annotation.bindings()) .flatMap(binding -> Stream.concat( Stream.of(binding.key()), // if routing key is configured, prefer it Stream.of(binding.value().name()))); - return Stream.concat(annotationQueueNames, annotationBindingChannelNames) + return Stream.concat(streamQueueNames(annotation), annotationBindingChannelNames) .map(resolver::resolveStringValue) .filter(Objects::nonNull) .peek(queue -> log.debug("Resolved channel name: {}", queue)) @@ -51,11 +52,10 @@ public static String getChannelName(RabbitListener annotation, StringValueResolv } public static String getQueueName(RabbitListener annotation, StringValueResolver resolver) { - Stream annotationQueueNames = Arrays.stream(annotation.queues()); Stream annotationBindingChannelNames = Arrays.stream(annotation.bindings()) .flatMap(binding -> Stream.of(binding.value().name())); - return Stream.concat(annotationQueueNames, annotationBindingChannelNames) + return Stream.concat(streamQueueNames(annotation), annotationBindingChannelNames) .map(resolver::resolveStringValue) .filter(Objects::nonNull) .peek(queue -> log.debug("Resolved queue name: {}", queue)) @@ -65,6 +65,26 @@ public static String getQueueName(RabbitListener annotation, StringValueResolver "No queue name was found in @RabbitListener annotation (neither in queues nor bindings property)")); } + /** + * + * @param rabbitListenerAnnotation a RabbitListener annotation + * @return A stream of ALL queue names as defined in the following 'locations': + *
    + *
  • {@link RabbitListener#queues()}
  • + *
  • {@link RabbitListener#queuesToDeclare()}.name
  • + *
+ */ + private static Stream streamQueueNames(RabbitListener rabbitListenerAnnotation) { + return Arrays.stream( + ArrayUtils.addAll( + rabbitListenerAnnotation.queues(), + Arrays.stream(rabbitListenerAnnotation.queuesToDeclare()) + .map(queue -> queue.name()) + .toArray(String[]::new) + ) + ); + } + public static Map buildChannelBinding( RabbitListener annotation, StringValueResolver resolver, RabbitListenerUtilContext context) { AMQPChannelBinding.AMQPChannelBindingBuilder channelBinding = AMQPChannelBinding.builder(); From 9c061defb7dd4066a34d804e9c09c452c5a3b575 Mon Sep 17 00:00:00 2001 From: Pascal Dal Farra Date: Sun, 10 Sep 2023 13:59:06 +0200 Subject: [PATCH 2/7] fix: Also take into account RabbitListener.queuesToDeclare --- springwolf-plugins/springwolf-amqp-plugin/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/springwolf-plugins/springwolf-amqp-plugin/build.gradle b/springwolf-plugins/springwolf-amqp-plugin/build.gradle index 3f2c81897..e03ae0444 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/build.gradle +++ b/springwolf-plugins/springwolf-amqp-plugin/build.gradle @@ -20,6 +20,8 @@ dependencies { implementation "org.springframework.amqp:spring-amqp" implementation "org.springframework.amqp:spring-rabbit" + implementation "org.apache.commons:commons-lang3:${commonsLang3Version}" + implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" From 8d93429dd28c69009082ea58b837f87d6353d39e Mon Sep 17 00:00:00 2001 From: Pascal Dal Farra Date: Thu, 14 Sep 2023 08:42:10 +0200 Subject: [PATCH 3/7] feat: Add unit test for queuesToDeclare --- .../springwolf-amqp-plugin/build.gradle | 1 + .../annotation/RabbitListenerUtil.java | 16 +++---- ...lRabbitListenerScannerIntegrationTest.java | 44 +++++++++++-------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/springwolf-plugins/springwolf-amqp-plugin/build.gradle b/springwolf-plugins/springwolf-amqp-plugin/build.gradle index e03ae0444..4fd7c1ed2 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/build.gradle +++ b/springwolf-plugins/springwolf-amqp-plugin/build.gradle @@ -35,6 +35,7 @@ dependencies { testImplementation "org.assertj:assertj-core:${assertjCoreVersion}" testImplementation "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}" + testImplementation("org.junit.jupiter:junit-jupiter-params:${junitJupiterVersion}") testImplementation "org.mockito:mockito-core:${mockitoCoreVersion}" testImplementation "org.springframework.boot:spring-boot-test" diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java index 25a3a78e0..6dd5e4d0d 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java @@ -7,6 +7,7 @@ import com.asyncapi.v2.binding.operation.OperationBinding; import com.asyncapi.v2.binding.operation.amqp.AMQPOperationBinding; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Exchange; import org.springframework.amqp.core.ExchangeTypes; @@ -26,8 +27,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.commons.lang3.ArrayUtils; - @Slf4j public class RabbitListenerUtil { private static final Boolean DEFAULT_AUTO_DELETE = false; @@ -75,14 +74,11 @@ public static String getQueueName(RabbitListener annotation, StringValueResolver * */ private static Stream streamQueueNames(RabbitListener rabbitListenerAnnotation) { - return Arrays.stream( - ArrayUtils.addAll( - rabbitListenerAnnotation.queues(), - Arrays.stream(rabbitListenerAnnotation.queuesToDeclare()) - .map(queue -> queue.name()) - .toArray(String[]::new) - ) - ); + return Arrays.stream(ArrayUtils.addAll( + rabbitListenerAnnotation.queues(), + Arrays.stream(rabbitListenerAnnotation.queuesToDeclare()) + .map(queue -> queue.name()) + .toArray(String[]::new))); } public static Map buildChannelBinding( diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java index ebfa2d918..3e84a7a55 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java @@ -12,13 +12,14 @@ import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.PayloadReference; import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeaders; import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.HeaderReference; -import io.github.stavshamir.springwolf.configuration.AsyncApiDocket; import io.github.stavshamir.springwolf.schemas.DefaultSchemasService; import io.github.stavshamir.springwolf.schemas.example.ExampleJsonGenerator; import lombok.Data; import lombok.NoArgsConstructor; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.ExchangeTypes; import org.springframework.amqp.rabbit.annotation.Exchange; @@ -33,11 +34,7 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; @@ -61,9 +58,6 @@ class MethodLevelRabbitListenerScannerIntegrationTest { @MockBean private ComponentClassScanner componentsScanner; - @MockBean - private AsyncApiDocket asyncApiDocket; - private static final String QUEUE = "test-queue"; private static final Map defaultOperationBinding = Map.of("amqp", AMQPOperationBinding.builder().cc(List.of(QUEUE)).build()); @@ -103,10 +97,15 @@ void scan_componentHasNoRabbitListenerMethods() { assertThat(channels).isEmpty(); } - @Test - void scan_componentHasRabbitListenerMethods_hardCodedTopic() { + @ParameterizedTest + @ValueSource( + classes = { + ClassWithRabbitListenerAnnotationHardCodedTopic.class, + ClassWithRabbitListenerAnnotationUsingQueuesToDeclare.class + }) + void scan_componentHasRabbitListenerMethods_hardCodedTopic(Class classWithRabbitListenerAnnotation) { // Given a class with methods annotated with RabbitListener, whose queues attribute is hard coded - setClassToScan(ClassWithRabbitListenerAnnotationHardCodedTopic.class); + setClassToScan(classWithRabbitListenerAnnotation); // When scan is called Map actualChannelItems = rabbitListenerScanner.scan(); @@ -128,7 +127,7 @@ void scan_componentHasRabbitListenerMethods_hardCodedTopic() { Operation operation = Operation.builder() .description("Auto-generated description") - .operationId("test-queue_publish_methodWithAnnotation") + .operationId(QUEUE + "_publish_methodWithAnnotation") .bindings(defaultOperationBinding) .message(message) .build(); @@ -177,7 +176,7 @@ void scan_componentHasRabbitListenerMethods_embeddedValueTopic() { Operation operation = Operation.builder() .description("Auto-generated description") - .operationId("test-queue_publish_methodWithAnnotation1") + .operationId(QUEUE + "_publish_methodWithAnnotation1") .bindings(defaultOperationBinding) .message(message) .build(); @@ -223,7 +222,7 @@ void scan_componentHasRabbitListenerMethods_bindingsAnnotation() { Operation operation = Operation.builder() .description("Auto-generated description") - .operationId("key_publish_methodWithAnnotation1") + .operationId("key_publish_methodWithAnnotation") .bindings(Map.of( "amqp", AMQPOperationBinding.builder() @@ -329,7 +328,7 @@ void scan_componentHasRabbitListenerMethods_multipleParamsWithPayloadAnnotation( Operation operation = Operation.builder() .description("Auto-generated description") - .operationId("test-queue_publish_methodWithAnnotation") + .operationId(QUEUE + "_publish_methodWithAnnotation") .bindings(defaultOperationBinding) .message(message) .build(); @@ -362,9 +361,18 @@ private static class ClassWithRabbitListenerAnnotationUsingBindings { @QueueBinding( exchange = @Exchange(name = "name", type = "topic"), key = "key", - value = @Queue(name = "test-queue")) + value = @Queue(name = QUEUE)) }) - private void methodWithAnnotation1(SimpleFoo payload) {} + private void methodWithAnnotation(SimpleFoo payload) {} + } + + /** + * Note: bindings, queues, and queuesToDeclare are mutually exclusive + * @see RabbitListener.queuesToDeclare + */ + private static class ClassWithRabbitListenerAnnotationUsingQueuesToDeclare { + @RabbitListener(queuesToDeclare = @Queue(name = QUEUE)) + private void methodWithAnnotation(SimpleFoo payload) {} } public static class ClassWithRabbitListenerAnnotationsBindingBean { From 5d20823ff47063f684717a7656de87c6a8c23367 Mon Sep 17 00:00:00 2001 From: Pascal Dal Farra Date: Thu, 14 Sep 2023 08:45:00 +0200 Subject: [PATCH 4/7] chore: update doc --- .../scanners/channels/annotation/RabbitListenerUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java index 6dd5e4d0d..a5c236203 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java @@ -72,7 +72,9 @@ public static String getQueueName(RabbitListener annotation, StringValueResolver *
  • {@link RabbitListener#queues()}
  • *
  • {@link RabbitListener#queuesToDeclare()}.name
  • * - */ + * Note: queues, queuesToDeclare (and bindings) are mutually exclusive + * @see RabbitListener.queuesToDeclare + * */ private static Stream streamQueueNames(RabbitListener rabbitListenerAnnotation) { return Arrays.stream(ArrayUtils.addAll( rabbitListenerAnnotation.queues(), From 26680eb85ed1e72e02b351a6a16d64ec3c01b262 Mon Sep 17 00:00:00 2001 From: Pascal Dal Farra Date: Thu, 14 Sep 2023 10:27:24 +0200 Subject: [PATCH 5/7] fix: organize import using :spotlessApply --- .../MethodLevelRabbitListenerScannerIntegrationTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java index 3e84a7a55..0e449f1ca 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java @@ -34,8 +34,6 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -import java.util.*; - import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; From 0e5b6a0fe1b99ba0716e1ae10a8bd2d605b7fa74 Mon Sep 17 00:00:00 2001 From: Pascal Dal Farra Date: Thu, 14 Sep 2023 14:01:45 +0200 Subject: [PATCH 6/7] fix: disable IntelliJ auto-organize import using and fix imports to comply to GitHub requirements --- .../MethodLevelRabbitListenerScannerIntegrationTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java index 0e449f1ca..1081164d7 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelRabbitListenerScannerIntegrationTest.java @@ -34,6 +34,12 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; From 66c5106ea81f04fa6a5a15df8f8df9224e2903b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Fri, 15 Sep 2023 14:15:39 +0200 Subject: [PATCH 7/7] refactor(amqp-plugin): replace ArrayUtils.addAll with Stream.concat to remove dependency on commons-lang3 --- springwolf-plugins/springwolf-amqp-plugin/build.gradle | 2 -- .../scanners/channels/annotation/RabbitListenerUtil.java | 9 +++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/springwolf-plugins/springwolf-amqp-plugin/build.gradle b/springwolf-plugins/springwolf-amqp-plugin/build.gradle index 4fd7c1ed2..29c0b4669 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/build.gradle +++ b/springwolf-plugins/springwolf-amqp-plugin/build.gradle @@ -20,8 +20,6 @@ dependencies { implementation "org.springframework.amqp:spring-amqp" implementation "org.springframework.amqp:spring-rabbit" - implementation "org.apache.commons:commons-lang3:${commonsLang3Version}" - implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java index a5c236203..64c464081 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtil.java @@ -7,7 +7,6 @@ import com.asyncapi.v2.binding.operation.OperationBinding; import com.asyncapi.v2.binding.operation.amqp.AMQPOperationBinding; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ArrayUtils; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Exchange; import org.springframework.amqp.core.ExchangeTypes; @@ -76,11 +75,9 @@ public static String getQueueName(RabbitListener annotation, StringValueResolver * @see RabbitListener.queuesToDeclare * */ private static Stream streamQueueNames(RabbitListener rabbitListenerAnnotation) { - return Arrays.stream(ArrayUtils.addAll( - rabbitListenerAnnotation.queues(), - Arrays.stream(rabbitListenerAnnotation.queuesToDeclare()) - .map(queue -> queue.name()) - .toArray(String[]::new))); + return Stream.concat( + Arrays.stream(rabbitListenerAnnotation.queues()), + Arrays.stream(rabbitListenerAnnotation.queuesToDeclare()).map(Queue::name)); } public static Map buildChannelBinding(