diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/SpringwolfScannerConfiguration.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/SpringwolfScannerConfiguration.java index 2aa5fa097..2b193e994 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/SpringwolfScannerConfiguration.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/SpringwolfScannerConfiguration.java @@ -122,7 +122,7 @@ public AsyncOperation getAsyncOperation(AsyncListener annotation) { @Override public OperationAction getOperationType() { - return OperationAction.SEND; + return OperationAction.RECEIVE; } }; } @@ -142,7 +142,7 @@ public AsyncOperation getAsyncOperation(AsyncPublisher annotation) { @Override public OperationAction getOperationType() { - return OperationAction.RECEIVE; + return OperationAction.SEND; } }; } diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMerger.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMerger.java index b38169854..2f21e0e94 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMerger.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMerger.java @@ -52,7 +52,7 @@ public static Map mergeChannels(List mergeOperations(List> operationEntries) { Map mergedOperations = new HashMap<>(); diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScanner.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScanner.java index a73d72af6..4c3fd07a6 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScanner.java @@ -118,12 +118,14 @@ private Map.Entry buildChannel(MethodAndAnnotation met private Map.Entry buildOperation(MethodAndAnnotation methodAndAnnotation) { AsyncOperation operationAnnotation = this.asyncAnnotationProvider.getAsyncOperation(methodAndAnnotation.annotation()); - String operationName = resolver.resolveStringValue(operationAnnotation.channelName()); + String channelName = resolver.resolveStringValue(operationAnnotation.channelName()); + String operationId = channelName + "_" + this.asyncAnnotationProvider.getOperationType().type + "_" + + methodAndAnnotation.method.getName(); - Operation operation = buildOperation(operationAnnotation, methodAndAnnotation.method(), operationName); + Operation operation = buildOperation(operationAnnotation, methodAndAnnotation.method(), channelName); operation.setAction(this.asyncAnnotationProvider.getOperationType()); - return Map.entry(operationName, operation); + return Map.entry(operationId, operation); } private Operation buildOperation(AsyncOperation asyncOperation, Method method, String channelName) { diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationScannerUtil.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationScannerUtil.java index 3ad94e583..dfc9d3cb3 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationScannerUtil.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationScannerUtil.java @@ -93,7 +93,7 @@ public static Map processMessageBindingFromAnnotation( .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toMap( - ProcessedMessageBinding::getType, ProcessedMessageBinding::getBinding, (e1, e2) -> e2)); + ProcessedMessageBinding::getType, ProcessedMessageBinding::getBinding, (e1, e2) -> e1)); } public static void processAsyncMessageAnnotation( diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScanner.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScanner.java index 3d71d9e4f..8952e9c88 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScanner.java @@ -113,7 +113,7 @@ private Stream> mapClassToOperation(Class compon } String channelName = bindingFactory.getChannelName(classAnnotation); - String operationId = channelName + "_receive_" + component.getSimpleName(); + String operationId = channelName + "_" + OperationAction.RECEIVE + "_" + component.getSimpleName(); Operation operation = buildOperation(classAnnotation, annotatedMethods); diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScanner.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScanner.java index 60dd32992..02c226807 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScanner.java @@ -85,7 +85,7 @@ private Map.Entry mapMethodToOperation(Method method) { MethodAnnotation annotation = AnnotationUtil.findAnnotationOrThrow(methodAnnotationClass, method); String channelName = bindingFactory.getChannelName(annotation); - String operationId = channelName + "_receive_" + method.getName(); + String operationId = channelName + "_" + OperationAction.RECEIVE + "_" + method.getName(); Class payload = payloadClassExtractor.extractFrom(method); Operation operation = buildOperation(annotation, payload); diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/schemas/postprocessor/SchemasPostProcessor.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/schemas/postprocessor/SchemasPostProcessor.java index 3cb450cf4..1c75936ed 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/schemas/postprocessor/SchemasPostProcessor.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/schemas/postprocessor/SchemasPostProcessor.java @@ -8,7 +8,7 @@ /** * Internal interface to allow post-processing of a new schema (and their definition) after detection. *
- * It is closely coupled with the data structure of the SchemaService. + * It is closely coupled with the data structure of the SchemasService. */ public interface SchemasPostProcessor { void process(Schema schema, Map definitions); diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiSerializerServiceIntegrationTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiSerializerServiceIntegrationTest.java index 241a6a4c4..653152b1f 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiSerializerServiceIntegrationTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiSerializerServiceIntegrationTest.java @@ -95,8 +95,7 @@ private AsyncAPI getAsyncAPITestObject() { Operation newUserOperation = Operation.builder() .action(OperationAction.SEND) - // FIXME: Generate Ref from Channel Instance - .channel(ChannelReference.builder().ref("#/channels/new-user").build()) + .channel(ChannelReference.fromChannel("new-user")) .messages(List.of(MessageReference.toChannelMessage("new-user", message.getName()))) .bindings(Map.of("kafka", operationBinding)) .build(); diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMergerTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMergerTest.java index 12dc4e9b2..acdd148fb 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMergerTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelMergerTest.java @@ -35,16 +35,16 @@ void shouldNotMergeDifferentChannelNames() { } @Test - void shouldNotMergeDifferentOperationNames() { + void shouldNotMergeDifferentoperationIds() { // given - String operationName1 = "operation1"; - String operationName2 = "operation2"; + String operationId1 = "operation1"; + String operationId2 = "operation2"; Operation publisherOperation = Operation.builder().build(); Operation subscriberOperation = Operation.builder().build(); // when Map mergedOperations = ChannelMerger.mergeOperations(Arrays.asList( - Map.entry(operationName1, publisherOperation), Map.entry(operationName2, subscriberOperation))); + Map.entry(operationId1, publisherOperation), Map.entry(operationId2, subscriberOperation))); // then assertThat(mergedOperations).hasSize(2); @@ -66,9 +66,9 @@ void shouldMergeEqualChannelNamesIntoOneChannel() { } @Test - void shouldMergeEqualOperationNamesIntoOneOperation() { + void shouldMergeEqualoperationIdsIntoOneOperation() { // given - String operationName = "operation"; + String operationId = "operation"; Operation publishOperation = Operation.builder() .action(OperationAction.SEND) .title("publisher") @@ -79,8 +79,8 @@ void shouldMergeEqualOperationNamesIntoOneOperation() { .build(); // when - Map mergedOperations = ChannelMerger.mergeOperations(Arrays.asList( - Map.entry(operationName, publishOperation), Map.entry(operationName, subscribeOperation))); + Map mergedOperations = ChannelMerger.mergeOperations( + Arrays.asList(Map.entry(operationId, publishOperation), Map.entry(operationId, subscribeOperation))); // then assertThat(mergedOperations).hasSize(1); @@ -108,7 +108,7 @@ void shouldUseFirstChannelFound() { @Test void shouldUseFirstOperationFound() { // given - String operationName = "operation"; + String operationId = "operation"; Operation senderOperation = Operation.builder().action(OperationAction.SEND).build(); Operation receiverOperation = @@ -116,10 +116,10 @@ void shouldUseFirstOperationFound() { // when Map mergedOperations = ChannelMerger.mergeOperations( - Arrays.asList(Map.entry(operationName, senderOperation), Map.entry(operationName, receiverOperation))); + Arrays.asList(Map.entry(operationId, senderOperation), Map.entry(operationId, receiverOperation))); // then - assertThat(mergedOperations).hasSize(1).hasEntrySatisfying(operationName, it -> { + assertThat(mergedOperations).hasSize(1).hasEntrySatisfying(operationId, it -> { assertThat(it.getAction()).isEqualTo(OperationAction.SEND); }); } @@ -171,7 +171,7 @@ void shouldMergeDifferentMessagesForSameChannel() { void shouldMergeDifferentMessageForSameOperation() { // given String channelName = "channel"; - String operationName = "operation"; + String operationId = "operation"; MessageObject message1 = MessageObject.builder() .messageId("message1") .name(String.class.getCanonicalName()) @@ -209,13 +209,13 @@ void shouldMergeDifferentMessageForSameOperation() { // when Map mergedOperations = ChannelMerger.mergeOperations(List.of( - Map.entry(operationName, senderOperation1), - Map.entry(operationName, senderOperation2), - Map.entry(operationName, senderOperation3))); + Map.entry(operationId, senderOperation1), + Map.entry(operationId, senderOperation2), + Map.entry(operationId, senderOperation3))); // then expectedMessage only includes message1 and message2. // Message3 is not included as it is identical in terms of payload type (Message#name) to message 2 - assertThat(mergedOperations).hasSize(1).hasEntrySatisfying(operationName, it -> { + assertThat(mergedOperations).hasSize(1).hasEntrySatisfying(operationId, it -> { assertThat(it.getMessages()).containsExactlyInAnyOrder(messageRef1, messageRef2); }); } diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScannerTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScannerTest.java index dbb7d7db1..57bca30e3 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScannerTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/AsyncAnnotationChannelsScannerTest.java @@ -214,7 +214,8 @@ void scan_componentHasListenerMethodWithAllAttributes() { .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); - assertThat(actualOperations).containsExactly(Map.entry("test-channel", expectedOperation)); + assertThat(actualOperations) + .containsExactly(Map.entry("test-channel_send_methodWithAnnotation", expectedOperation)); } @Test @@ -275,8 +276,8 @@ void scan_componentHasMultipleListenerAnnotations() { "test-channel-2", expectedChannel2)); assertThat(actualOperations) .containsExactlyInAnyOrderEntriesOf(Map.of( - "test-channel-1", expectedOperation1, - "test-channel-2", expectedOperation2)); + "test-channel-1_send_methodWithMultipleAnnotation", expectedOperation1, + "test-channel-2_send_methodWithMultipleAnnotation", expectedOperation2)); } @Test @@ -318,7 +319,8 @@ void scan_componentHasAsyncMethodAnnotation() { .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); - assertThat(actualOperations).containsExactly(Map.entry("test-channel", expectedOperation)); + assertThat(actualOperations) + .containsExactly(Map.entry("test-channel_send_methodWithAnnotation", expectedOperation)); } private static class ClassWithoutListenerAnnotation { @@ -435,7 +437,8 @@ void scan_componentHasOnlyDeclaredMethods(Class clazz) { .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); - assertThat(actualOperations).containsExactly(Map.entry("test-channel", expectedOperation)); + assertThat(actualOperations) + .containsExactly(Map.entry("test-channel_send_methodFromInterface", expectedOperation)); } private static class ClassImplementingInterface implements ClassInterface { @@ -510,7 +513,8 @@ void scan_componentHasListenerMethodWithMetaAnnotation() { .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); - assertThat(actualOperations).containsExactly(Map.entry("test-channel", expectedOperation)); + assertThat(actualOperations) + .containsExactly(Map.entry("test-channel_send_methodFromInterface", expectedOperation)); } public static class ClassWithMetaAnnotation { diff --git a/springwolf-examples/springwolf-amqp-example/src/test/resources/asyncapi.json b/springwolf-examples/springwolf-amqp-example/src/test/resources/asyncapi.json index fe11535c8..b72809d6a 100644 --- a/springwolf-examples/springwolf-amqp-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-amqp-example/src/test/resources/asyncapi.json @@ -245,12 +245,12 @@ } ] }, - "example-producer-channel-publisher": { - "action": "receive", + "example-producer-channel-publisher_send_sendMessage": { + "action": "send", "channel": { "$ref": "#/channels/example-producer-channel-publisher" }, - "title": "example-producer-channel-publisher_receive", + "title": "example-producer-channel-publisher_send", "description": "Custom, optional description defined in the AsyncPublisher annotation", "bindings": { "amqp": { diff --git a/springwolf-examples/springwolf-cloud-stream-example/src/test/resources/asyncapi.json b/springwolf-examples/springwolf-cloud-stream-example/src/test/resources/asyncapi.json index 4135d0d12..d63f5b86e 100644 --- a/springwolf-examples/springwolf-cloud-stream-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-cloud-stream-example/src/test/resources/asyncapi.json @@ -25,17 +25,7 @@ "another-topic": { "messages": { "io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto": { - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, - "payload": { - "$ref": "#/components/schemas/AnotherPayloadDto" - }, - "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", - "bindings": { - "kafka": { } - } + "$ref": "#/components/messages/io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto" } }, "bindings": { @@ -45,17 +35,7 @@ "example-topic": { "messages": { "io.github.stavshamir.springwolf.example.cloudstream.dtos.ExamplePayloadDto": { - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, - "payload": { - "$ref": "#/components/schemas/ExamplePayloadDto" - }, - "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.ExamplePayloadDto", - "title": "ExamplePayloadDto", - "bindings": { - "kafka": { } - } + "$ref": "#/components/messages/io.github.stavshamir.springwolf.example.cloudstream.dtos.ExamplePayloadDto" } }, "bindings": { @@ -132,7 +112,40 @@ "example": { } } }, - "messages": { } + "messages": { + "io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto": { + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, + "payload": { + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/AnotherPayloadDto" + } + }, + "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", + "bindings": { + "kafka": { } + } + }, + "io.github.stavshamir.springwolf.example.cloudstream.dtos.ExamplePayloadDto": { + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, + "payload": { + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/ExamplePayloadDto" + } + }, + "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.ExamplePayloadDto", + "title": "ExamplePayloadDto", + "bindings": { + "kafka": { } + } + } + } }, "operations": { "another-topic_publish_consumerMethod": { diff --git a/springwolf-examples/springwolf-jms-example/src/test/resources/asyncapi.json b/springwolf-examples/springwolf-jms-example/src/test/resources/asyncapi.json index 959b8e02f..fa7feec64 100644 --- a/springwolf-examples/springwolf-jms-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-jms-example/src/test/resources/asyncapi.json @@ -151,20 +151,13 @@ } }, "operations": { - "another-queue": { + "another-queue_receive_receiveAnotherPayload": { "action": "receive", "channel": { "$ref": "#/channels/another-queue" }, - "title": "another-queue_receive", - "description": "Custom, optional description defined in the AsyncPublisher annotation", "bindings": { - "jms": { - "internal-field": "customValue", - "nested": { - "key": "nestedValue" - } - } + "jms": { } }, "messages": [ { @@ -172,13 +165,20 @@ } ] }, - "another-queue_receive_receiveAnotherPayload": { - "action": "receive", + "another-queue_send_sendMessage": { + "action": "send", "channel": { "$ref": "#/channels/another-queue" }, + "title": "another-queue_send", + "description": "Custom, optional description defined in the AsyncPublisher annotation", "bindings": { - "jms": { } + "jms": { + "internal-field": "customValue", + "nested": { + "key": "nestedValue" + } + } }, "messages": [ { diff --git a/springwolf-examples/springwolf-kafka-example/src/test/resources/asyncapi.json b/springwolf-examples/springwolf-kafka-example/src/test/resources/asyncapi.json index dade7a0e9..19ced46b0 100644 --- a/springwolf-examples/springwolf-kafka-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-kafka-example/src/test/resources/asyncapi.json @@ -802,6 +802,13 @@ "description": "Payload model with nested complex types", "bindings": { "kafka": { + "key": { + "type": "string", + "description": "Kafka Producer Message Key", + "examples": [ + "example-key" + ] + }, "bindingVersion": "0.4.0" } } @@ -867,12 +874,12 @@ } ] }, - "avro-topic": { - "action": "send", + "avro-topic_receive_receiveExampleAvroPayload": { + "action": "receive", "channel": { "$ref": "#/channels/avro-topic" }, - "title": "avro-topic_send", + "title": "avro-topic_receive", "description": "Requires a running kafka-schema-registry. See docker-compose.yml to start it", "bindings": { "kafka": { @@ -885,10 +892,10 @@ } ] }, - "avro-topic_receive_receiveExampleAvroPayload": { + "example-topic_receive_receiveExamplePayload": { "action": "receive", "channel": { - "$ref": "#/channels/avro-topic" + "$ref": "#/channels/example-topic" }, "bindings": { "kafka": { @@ -897,14 +904,14 @@ }, "messages": [ { - "$ref": "#/channels/avro-topic/messages/io.github.stavshamir.springwolf.example.kafka.dto.avro.ExamplePayloadAvroDto" + "$ref": "#/channels/example-topic/messages/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" } ] }, - "example-topic_receive_receiveExamplePayload": { + "multi-payload-topic_receive_ExampleClassLevelKafkaListener": { "action": "receive", "channel": { - "$ref": "#/channels/example-topic" + "$ref": "#/channels/multi-payload-topic" }, "bindings": { "kafka": { @@ -913,16 +920,22 @@ }, "messages": [ { - "$ref": "#/channels/example-topic/messages/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" + "$ref": "#/channels/multi-payload-topic/messages/io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto" + }, + { + "$ref": "#/channels/multi-payload-topic/messages/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" + }, + { + "$ref": "#/channels/multi-payload-topic/messages/javax.money.MonetaryAmount" } ] }, - "multi-payload-topic": { - "action": "send", + "multi-payload-topic_receive_receiveMonetaryAmount": { + "action": "receive", "channel": { "$ref": "#/channels/multi-payload-topic" }, - "title": "multi-payload-topic_send", + "title": "multi-payload-topic_receive", "description": "Override description in the AsyncListener annotation with servers at kafka:29092", "bindings": { "kafka": { @@ -947,28 +960,6 @@ } ] }, - "multi-payload-topic_receive_ExampleClassLevelKafkaListener": { - "action": "receive", - "channel": { - "$ref": "#/channels/multi-payload-topic" - }, - "bindings": { - "kafka": { - "bindingVersion": "0.4.0" - } - }, - "messages": [ - { - "$ref": "#/channels/multi-payload-topic/messages/io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto" - }, - { - "$ref": "#/channels/multi-payload-topic/messages/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" - }, - { - "$ref": "#/channels/multi-payload-topic/messages/javax.money.MonetaryAmount" - } - ] - }, "protobuf-topic_receive_receiveExampleProtobufPayload": { "action": "receive", "channel": { @@ -985,12 +976,12 @@ } ] }, - "string-topic": { - "action": "send", + "string-topic_receive_receiveStringPayload": { + "action": "receive", "channel": { "$ref": "#/channels/string-topic" }, - "title": "string-topic_send", + "title": "string-topic_receive", "description": "Final classes (like String) can be documented using an envelope class and the @AsyncApiPayload annotation.", "bindings": { "kafka": { @@ -1000,31 +991,18 @@ "messages": [ { "$ref": "#/channels/string-topic/messages/io.github.stavshamir.springwolf.example.kafka.consumers.StringConsumer$StringEnvelope" - } - ] - }, - "string-topic_receive_receiveStringPayload": { - "action": "receive", - "channel": { - "$ref": "#/channels/string-topic" - }, - "bindings": { - "kafka": { - "bindingVersion": "0.4.0" - } - }, - "messages": [ + }, { "$ref": "#/channels/string-topic/messages/java.lang.String" } ] }, - "topic-defined-via-asyncPublisher-annotation": { - "action": "receive", + "topic-defined-via-asyncPublisher-annotation_send_sendMessage": { + "action": "send", "channel": { "$ref": "#/channels/topic-defined-via-asyncPublisher-annotation" }, - "title": "topic-defined-via-asyncPublisher-annotation_receive", + "title": "topic-defined-via-asyncPublisher-annotation_send", "description": "Custom, optional description defined in the AsyncPublisher annotation", "bindings": { "kafka": { diff --git a/springwolf-examples/springwolf-sns-example/src/test/resources/asyncapi.json b/springwolf-examples/springwolf-sns-example/src/test/resources/asyncapi.json index 483c2c5f8..eed8129d4 100644 --- a/springwolf-examples/springwolf-sns-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-sns-example/src/test/resources/asyncapi.json @@ -230,12 +230,12 @@ } }, "operations": { - "another-topic": { - "action": "send", + "another-topic_receive_receiveAnotherPayload": { + "action": "receive", "channel": { "$ref": "#/channels/another-topic" }, - "title": "another-topic_send", + "title": "another-topic_receive", "description": "Auto-generated description", "bindings": { "sns": { @@ -256,12 +256,38 @@ } ] }, - "example-topic": { + "another-topic_send_sendMessage": { "action": "send", + "channel": { + "$ref": "#/channels/another-topic" + }, + "title": "another-topic_send", + "description": "Custom, optional description defined in the AsyncPublisher annotation", + "bindings": { + "sns": { + "consumers": [ + { + "protocol": "sqs", + "endpoint": { }, + "filterPolicyScope": "MessageAttributes", + "rawMessageDelivery": true + } + ], + "bindingVersion": "0.1.0" + } + }, + "messages": [ + { + "$ref": "#/channels/another-topic/messages/io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto" + } + ] + }, + "example-topic_receive_receiveExamplePayload": { + "action": "receive", "channel": { "$ref": "#/channels/example-topic" }, - "title": "example-topic_send", + "title": "example-topic_receive", "description": "Auto-generated description", "bindings": { "sns": { diff --git a/springwolf-examples/springwolf-sqs-example/src/test/resources/asyncapi.json b/springwolf-examples/springwolf-sqs-example/src/test/resources/asyncapi.json index 239a90573..16adb93b0 100644 --- a/springwolf-examples/springwolf-sqs-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-sqs-example/src/test/resources/asyncapi.json @@ -155,18 +155,16 @@ } }, "operations": { - "another-queue": { + "another-queue_receive_receiveAnotherPayload": { "action": "receive", "channel": { "$ref": "#/channels/another-queue" }, - "title": "another-queue_receive", - "description": "Custom, optional description defined in the AsyncPublisher annotation", "bindings": { "sqs": { "queues": [ { - "name": "queue-name", + "name": "another-queue", "fifoQueue": true, "deliveryDelay": 0, "visibilityTimeout": 30, @@ -183,16 +181,18 @@ } ] }, - "another-queue_receive_receiveAnotherPayload": { - "action": "receive", + "another-queue_send_sendMessage": { + "action": "send", "channel": { "$ref": "#/channels/another-queue" }, + "title": "another-queue_send", + "description": "Custom, optional description defined in the AsyncPublisher annotation", "bindings": { "sqs": { "queues": [ { - "name": "another-queue", + "name": "queue-name", "fifoQueue": true, "deliveryDelay": 0, "visibilityTimeout": 30, diff --git a/springwolf-plugins/springwolf-cloud-stream-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScanner.java b/springwolf-plugins/springwolf-cloud-stream-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScanner.java index c3792d232..f6128228c 100644 --- a/springwolf-plugins/springwolf-cloud-stream-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScanner.java +++ b/springwolf-plugins/springwolf-cloud-stream-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScanner.java @@ -19,6 +19,8 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.OperationAction; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.server.Server; import io.github.stavshamir.springwolf.configuration.AsyncApiDocket; import io.github.stavshamir.springwolf.configuration.AsyncApiDocketService; @@ -96,18 +98,23 @@ private ChannelObject buildChannel(FunctionalChannelBeanData beanData) { String modelName = schemasService.registerSchema(payloadType); String headerModelName = schemasService.registerSchema(AsyncHeaders.NOT_DOCUMENTED); + var messagePayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(modelName)) + .build()); + MessageObject message = MessageObject.builder() .name(payloadType.getName()) .title(modelName) - .payload(MessagePayload.of(MessageReference.toSchema(modelName))) + .payload(messagePayload) .headers(MessageHeaders.of(MessageReference.toSchema(headerModelName))) .bindings(buildMessageBinding()) .build(); + this.schemasService.registerMessage(message); Map channelBinding = buildChannelBinding(); return ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(message.getName(), message)) + .messages(Map.of(message.getName(), MessageReference.toComponentMessage(message))) .build(); } diff --git a/springwolf-plugins/springwolf-cloud-stream-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScannerIntegrationTest.java b/springwolf-plugins/springwolf-cloud-stream-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScannerIntegrationTest.java index 5b8c05cae..34d7d7865 100644 --- a/springwolf-plugins/springwolf-cloud-stream-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScannerIntegrationTest.java +++ b/springwolf-plugins/springwolf-cloud-stream-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/cloudstream/CloudStreamFunctionChannelsScannerIntegrationTest.java @@ -19,9 +19,12 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.OperationAction; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.configuration.DefaultAsyncApiDocketService; import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties; import io.github.stavshamir.springwolf.schemas.DefaultSchemasService; +import io.github.stavshamir.springwolf.schemas.SchemasService; import io.github.stavshamir.springwolf.schemas.example.ExampleJsonGenerator; import org.apache.kafka.streams.kstream.KStream; import org.junit.jupiter.api.Test; @@ -81,6 +84,9 @@ class CloudStreamFunctionChannelsScannerIntegrationTest { @Autowired private CloudStreamFunctionChannelsScanner scanner; + @Autowired + private SchemasService schemasService; + private Map messageBinding = Map.of("kafka", new EmptyMessageBinding()); private Map operationBinding = Map.of("kafka", new EmptyOperationBinding()); private Map channelBinding = Map.of("kafka", new EmptyChannelBinding()); @@ -108,14 +114,16 @@ void testConsumerBinding() { MessageObject message = MessageObject.builder() .name(String.class.getName()) .title(String.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(String.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); ChannelObject expectedChannel = ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(message.getName(), message)) + .messages(Map.of(message.getName(), MessageReference.toComponentMessage(message))) .build(); Operation expectedOperation = Operation.builder() @@ -129,6 +137,7 @@ void testConsumerBinding() { assertThat(actualChannels).containsExactly(Map.entry(topicName, expectedChannel)); assertThat(actualOperations) .containsExactly(Map.entry("test-consumer-input-topic_publish_testConsumer", expectedOperation)); + assertThat(schemasService.getMessages()).contains(Map.entry(String.class.getName(), message)); } @Test @@ -148,7 +157,9 @@ void testSupplierBinding() { MessageObject message = MessageObject.builder() .name(String.class.getName()) .title(String.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(String.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -164,12 +175,13 @@ void testSupplierBinding() { ChannelObject expectedChannel = ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(message.getName(), message)) + .messages(Map.of(message.getName(), MessageReference.toComponentMessage(message))) .build(); assertThat(actualChannels).containsExactly(Map.entry(topicName, expectedChannel)); assertThat(actualOperations) .containsExactly(Map.entry("test-supplier-output-topic_subscribe_testSupplier", expectedOperation)); + assertThat(schemasService.getMessages()).contains(Map.entry(String.class.getName(), message)); } @Test @@ -196,7 +208,9 @@ void testFunctionBinding() { MessageObject subscribeMessage = MessageObject.builder() .name(Integer.class.getName()) .title(Integer.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(Integer.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(Integer.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -212,13 +226,15 @@ void testFunctionBinding() { ChannelObject subscribeChannel = ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(subscribeMessage.getName(), subscribeMessage)) + .messages(Map.of(subscribeMessage.getName(), MessageReference.toComponentMessage(subscribeMessage))) .build(); MessageObject publishMessage = MessageObject.builder() .name(String.class.getName()) .title(String.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(String.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -234,7 +250,7 @@ void testFunctionBinding() { ChannelObject publishChannel = ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(publishMessage.getName(), publishMessage)) + .messages(Map.of(publishMessage.getName(), MessageReference.toComponentMessage(publishMessage))) .build(); assertThat(actualChannels) @@ -269,7 +285,9 @@ void testKStreamFunctionBinding() { MessageObject subscribeMessage = MessageObject.builder() .name(Integer.class.getName()) .title(Integer.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(Integer.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(Integer.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -285,13 +303,15 @@ void testKStreamFunctionBinding() { ChannelObject subscribeChannel = ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(subscribeMessage.getName(), subscribeMessage)) + .messages(Map.of(subscribeMessage.getName(), MessageReference.toComponentMessage(subscribeMessage))) .build(); MessageObject publishMessage = MessageObject.builder() .name(String.class.getName()) .title(String.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(String.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -307,7 +327,7 @@ void testKStreamFunctionBinding() { ChannelObject publishChannel = ChannelObject.builder() .bindings(channelBinding) - .messages(Map.of(publishMessage.getName(), publishMessage)) + .messages(Map.of(publishMessage.getName(), MessageReference.toComponentMessage(publishMessage))) .build(); assertThat(actualChannels) @@ -316,6 +336,8 @@ void testKStreamFunctionBinding() { .contains( Map.entry("test-in-topic_publish_kStreamTestFunction", publishOperation), Map.entry("test-out-topic_subscribe_kStreamTestFunction", subscribeOperation)); + assertThat(schemasService.getMessages()).contains(Map.entry(String.class.getName(), publishMessage)); + assertThat(schemasService.getMessages()).contains(Map.entry(Integer.class.getName(), subscribeMessage)); } @Test @@ -341,7 +363,9 @@ void testFunctionBindingWithSameTopicName() { MessageObject subscribeMessage = MessageObject.builder() .name(Integer.class.getName()) .title(Integer.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(Integer.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(Integer.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -358,7 +382,9 @@ void testFunctionBindingWithSameTopicName() { MessageObject publishMessage = MessageObject.builder() .name(String.class.getName()) .title(String.class.getSimpleName()) - .payload(MessagePayload.of(MessageReference.toSchema(String.class.getSimpleName()))) + .payload(MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build())) .headers(MessageHeaders.of(MessageReference.toSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(Map.of("kafka", new EmptyMessageBinding())) .build(); @@ -375,8 +401,11 @@ void testFunctionBindingWithSameTopicName() { ChannelObject mergedChannel = ChannelObject.builder() .bindings(channelBinding) - .messages( - Map.of(publishMessage.getName(), publishMessage, subscribeMessage.getName(), subscribeMessage)) + .messages(Map.of( + publishMessage.getName(), + MessageReference.toComponentMessage(publishMessage), + subscribeMessage.getName(), + MessageReference.toComponentMessage(subscribeMessage))) .build(); assertThat(actualChannels).contains(Map.entry(topicName, mergedChannel)); @@ -384,6 +413,8 @@ void testFunctionBindingWithSameTopicName() { .contains( Map.entry("test-topic_publish_testFunction", publishOperation), Map.entry("test-topic_subscribe_testFunction", subscribeOperation)); + assertThat(schemasService.getMessages()).contains(Map.entry(String.class.getName(), publishMessage)); + assertThat(schemasService.getMessages()).contains(Map.entry(Integer.class.getName(), subscribeMessage)); } @TestConfiguration diff --git a/springwolf-plugins/springwolf-kafka-plugin/build.gradle b/springwolf-plugins/springwolf-kafka-plugin/build.gradle index 55896f4cf..28329d5e3 100644 --- a/springwolf-plugins/springwolf-kafka-plugin/build.gradle +++ b/springwolf-plugins/springwolf-kafka-plugin/build.gradle @@ -11,6 +11,7 @@ dependencies { api project(":springwolf-core") implementation "io.swagger.core.v3:swagger-models:${swaggerVersion}" + permitUnusedDeclared "io.swagger.core.v3:swagger-models:${swaggerVersion}" implementation "org.apache.kafka:kafka-clients:${kafkaClientsVersion}" implementation "org.slf4j:slf4j-api:${slf4jApiVersion}" diff --git a/springwolf-plugins/springwolf-kafka-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/KafkaMessageBindingProcessor.java b/springwolf-plugins/springwolf-kafka-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/KafkaMessageBindingProcessor.java index aaec56a7d..1aadfef14 100644 --- a/springwolf-plugins/springwolf-kafka-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/KafkaMessageBindingProcessor.java +++ b/springwolf-plugins/springwolf-kafka-plugin/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/KafkaMessageBindingProcessor.java @@ -6,14 +6,15 @@ import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.annotation.KafkaAsyncOperationBinding; import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.annotation.KafkaAsyncOperationBinding.KafkaAsyncMessageBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.kafka.KafkaMessageBinding; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.Schema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaObject; import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.util.StringUtils; import org.springframework.util.StringValueResolver; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.List; import java.util.Optional; public class KafkaMessageBindingProcessor implements MessageBindingProcessor, EmbeddedValueResolverAware { @@ -37,6 +38,9 @@ private ProcessedMessageBinding mapToMessageBinding(KafkaAsyncOperationBinding b KafkaAsyncMessageBinding messageBinding = bindingAnnotation.messageBinding(); KafkaMessageBinding.KafkaMessageBindingBuilder kafkaMessageBindingBuilder = KafkaMessageBinding.builder(); + + kafkaMessageBindingBuilder.key(resolveSchemaOrNull(messageBinding)); + String bindingVersion = resolveOrNull(messageBinding.bindingVersion()); if (StringUtils.hasText(bindingVersion)) { kafkaMessageBindingBuilder.bindingVersion(bindingVersion); @@ -49,15 +53,17 @@ private String resolveOrNull(String stringValue) { return StringUtils.hasText(stringValue) ? resolver.resolveStringValue(stringValue) : null; } - private Schema resolveSchemaOrNull(KafkaAsyncMessageBinding messageBinding) { - Schema schemaDefinition = null; + private Schema resolveSchemaOrNull(KafkaAsyncMessageBinding messageBinding) { + Schema schemaDefinition = null; switch (messageBinding.key().type()) { case UNDEFINED_KEY: break; case STRING_KEY: - schemaDefinition = new StringSchema() - .example(messageBinding.key().example()) - .description(resolveOrNull(messageBinding.key().description())); + schemaDefinition = SchemaObject.builder() + .type("string") + .examples(List.of(messageBinding.key().example())) + .description(resolveOrNull(messageBinding.key().description())) + .build(); } return schemaDefinition; diff --git a/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.html b/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.html index 56484a9dd..7dfc7670d 100644 --- a/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.html +++ b/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.html @@ -27,7 +27,7 @@

Message Binding

" (keyup)=" recalculateLineCount( - 'massageBindingExample', + 'messageBindingExample', bindingTextArea.value ) " diff --git a/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.ts b/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.ts index ac4a8d00b..0d85e0205 100644 --- a/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.ts +++ b/springwolf-ui/src/app/components/channels/channel-main/channel-main.component.ts @@ -92,8 +92,8 @@ export class ChannelMainComponent implements OnInit { getExampleValue(bindingValue: string | Binding): any { if (typeof bindingValue === "string") { return bindingValue; - } else if (typeof bindingValue.example === "object") { - return bindingValue.example.value; + } else if (typeof bindingValue.examples === "object") { + return bindingValue.examples["0"]; } return undefined; } @@ -106,7 +106,7 @@ export class ChannelMainComponent implements OnInit { case "headers": this.headersTextAreaLineCount = text.split("\n").length; break; - case "massageBindingExample": + case "messageBindingExample": this.messageBindingExampleTextAreaLineCount = text.split("\n").length; break; } diff --git a/springwolf-ui/src/app/service/asyncapi/asyncapi-mapper.service.ts b/springwolf-ui/src/app/service/asyncapi/asyncapi-mapper.service.ts index dba6885a5..1f23d1023 100644 --- a/springwolf-ui/src/app/service/asyncapi/asyncapi-mapper.service.ts +++ b/springwolf-ui/src/app/service/asyncapi/asyncapi-mapper.service.ts @@ -90,6 +90,8 @@ export class AsyncApiMapperService { const operation = operations[operationsKey]; const channelName = this.resolveRef(operation.channel.$ref); + this.verifyBindings(operation.bindings, "operation " + operationsKey); + const operationMessages: Message[] = this.mapServerAsyncApiMessages( channelName, channels[channelName], @@ -125,14 +127,7 @@ export class AsyncApiMapperService { operationType: ServerOperationAction, operationBinding: ServerBindings ): ChannelOperation { - if ( - channel.bindings == undefined || - Object.keys(channel.bindings).length == 0 - ) { - this.notificationService.showWarning( - "No binding defined for channel " + channelName - ); - } + this.verifyBindings(channel.bindings, "channel " + channelName); const operation = this.mapOperation( operationType, @@ -172,6 +167,8 @@ export class AsyncApiMapperService { const channelMessageRef = this.resolveRef(channelMessage.$ref); const message = messages[channelMessageRef]; + this.verifyBindings(message.bindings, "message " + message.name); + return { name: message.name, title: message.title, @@ -307,6 +304,17 @@ export class AsyncApiMapperService { return ref?.split("/")?.pop(); } + private verifyBindings( + bindings: ServerBindings | undefined, + identifier: string + ) { + if (bindings == undefined || Object.keys(bindings).length == 0) { + this.notificationService.showWarning( + "No binding defined for " + identifier + ); + } + } + private parsingErrorBoundary(path: string, f: () => T): T | undefined { try { return f();