From e17bbded9311492b60405a31de029f84653a2d2a Mon Sep 17 00:00:00 2001 From: Carlos Tasada Date: Fri, 12 Jan 2024 18:51:44 +0100 Subject: [PATCH] AsyncAPI v3 Migration Fixes (#533) * fix: Multiple fixes related with Channel Messages Some of the tests are failing due to some AssertJ recursion issue. Help is welcome * fix: Minor properties fixes * fix: Fixes to AMQP Some fixes to the AMQP plugin and example (Still not finished) * fix: Minor properties fixes * fix: Migrated asyncapi.json examples to v3 * fix: Migration to AsyncAPI v3 As per https://www.asyncapi.com/docs/migration/migrating-to-v3 For a channel with multiple messages, you specify multiple key-value pairs. For a channel with just one message, you use a single key-value pair. That means that the use of 'oneOf' is removed. * fix: Improved support for Channel Messages Fixed different bugs and limitations with the publishing of Messages in a Channel with the AsyncAPI v3 spec * fix: Fixed Channel Merger When merging Channels, the messages were not merged. This is now fixed. * fix: Added basic support for Operations Still plenty of errors, but Operations are now appearing in the AsyncAPI v3 output. * fix: AsyncAPI module test --- .../model/channel/message/MessageObject.java | 10 + .../channel/message/MessageReference.java | 8 +- .../asyncapi/v3/model/AsyncAPITest.java | 2 +- .../springwolf/asyncapi/ChannelsService.java | 10 +- .../asyncapi/DefaultAsyncApiService.java | 4 + .../asyncapi/DefaultChannelsService.java | 21 +- .../springwolf/asyncapi/MessageHelper.java | 37 +- .../scanners/channels/ChannelMerger.java | 91 ++++- .../scanners/channels/ChannelsScanner.java | 8 +- .../channels/SimpleChannelsScanner.java | 24 +- .../AsyncAnnotationChannelsScanner.java | 84 ++++- .../AsyncAnnotationScannerUtil.java | 18 +- .../ClassLevelAnnotationChannelsScanner.java | 90 +++-- .../MethodLevelAnnotationChannelsScanner.java | 79 +++- .../asyncapi/types/OperationData.java | 1 + .../header/AsyncHeadersNotDocumented.java | 2 +- ...DefaultChannelsServiceIntegrationTest.java | 36 +- .../asyncapi/MessageHelperTest.java | 56 ++- .../scanners/channels/ChannelMergerTest.java | 205 +++++++---- .../channels/SimpleChannelsScannerTest.java | 52 +-- .../AsyncAnnotationChannelsScannerTest.java | 121 +++--- ...otationChannelsScannerIntegrationTest.java | 80 ++-- ...assLevelAnnotationChannelsScannerTest.java | 27 +- ...otationChannelsScannerIntegrationTest.java | 91 ++--- ...hodLevelAnnotationChannelsScannerTest.java | 85 ++++- ...ngwolfConfigPropertiesIntegrationTest.java | 6 +- ...alIntegrationTestContextConfiguration.java | 2 +- .../src/main/resources/application.properties | 2 +- .../amqp/SpringContextIntegrationTest.java | 2 +- .../src/test/resources/asyncapi.json | 221 ++++++----- .../src/main/resources/application.properties | 2 +- .../SpringContextIntegrationTest.java | 2 +- .../src/test/resources/asyncapi.json | 116 ++++-- .../src/main/resources/application.properties | 2 +- .../src/test/resources/asyncapi.json | 126 ++++--- .../src/main/resources/application.properties | 2 +- .../kafka/SpringContextIntegrationTest.java | 2 +- .../src/test/resources/asyncapi.json | 343 +++++++++++------- .../src/main/resources/application.properties | 2 +- .../src/test/resources/asyncapi.json | 139 +++++-- .../src/main/resources/application.properties | 2 +- .../src/test/resources/asyncapi.json | 160 +++++--- .../springwolf-amqp-plugin/README.md | 2 +- .../annotation/RabbitListenerUtil.java | 1 - .../producer/SpringwolfAmqpProducer.java | 13 +- .../AmqpOperationBindingProcessorTest.java | 13 +- .../annotation/RabbitListenerUtilTest.java | 4 +- ...pProducerConfigurationIntegrationTest.java | 4 +- .../producer/SpringwolfAmqpProducerTest.java | 17 +- .../CloudStreamFunctionChannelsScanner.java | 11 +- ...unctionChannelsScannerIntegrationTest.java | 14 +- ...pringwolfJmsControllerIntegrationTest.java | 2 +- ...sProducerConfigurationIntegrationTest.java | 4 +- .../springwolf-kafka-plugin/README.md | 2 +- ...ingwolfKafkaControllerIntegrationTest.java | 2 +- ...aProducerConfigurationIntegrationTest.java | 4 +- ...sProducerConfigurationIntegrationTest.java | 4 +- ...sProducerConfigurationIntegrationTest.java | 4 +- 58 files changed, 1571 insertions(+), 903 deletions(-) diff --git a/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageObject.java b/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageObject.java index b50246464..d632512cb 100644 --- a/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageObject.java +++ b/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageObject.java @@ -118,4 +118,14 @@ public class MessageObject extends ExtendableObject implements Message { */ @JsonProperty(value = "traits") private List traits; + + /* + * Override the getMessageId to guarantee that there's always a value. Defaults to 'name' + */ + public String getMessageId() { + if (messageId == null) { + return this.name; + } + return messageId; + } } diff --git a/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageReference.java b/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageReference.java index e4e299b7b..86eca9043 100644 --- a/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageReference.java +++ b/springwolf-asyncapi/src/main/java/io/github/stavshamir/springwolf/asyncapi/v3/model/channel/message/MessageReference.java @@ -26,14 +26,10 @@ public String getRef() { /** * Convenient Builder to create a Message reference to an existing Message * @param message Message to create the reference to. This Message MUST have a 'messageId' field - * @return a Message with the 'ref' field pointing to "#/components/messages/{messageId" + * @return a Message with the 'ref' field pointing to "#/components/messages/{messageName}" */ public static MessageReference fromMessage(MessageObject message) { - var messageId = message.getMessageId(); - if (messageId == null) { - throw new IllegalArgumentException("The message must have a 'messageId' defined"); - } - return new MessageReference("#/components/messages/" + messageId); + return fromMessage(message.getName()); } public static MessageReference fromMessage(String messageName) { diff --git a/springwolf-asyncapi/src/test/java/io/github/stavshamir/springwolf/asyncapi/v3/model/AsyncAPITest.java b/springwolf-asyncapi/src/test/java/io/github/stavshamir/springwolf/asyncapi/v3/model/AsyncAPITest.java index 0f230b6b5..5f6a0c65d 100644 --- a/springwolf-asyncapi/src/test/java/io/github/stavshamir/springwolf/asyncapi/v3/model/AsyncAPITest.java +++ b/springwolf-asyncapi/src/test/java/io/github/stavshamir/springwolf/asyncapi/v3/model/AsyncAPITest.java @@ -59,7 +59,7 @@ void shouldCreateSimpleAsyncAPI() throws IOException { var channelUserSignedup = ChannelObject.builder() .channelId("userSignedup") .address("user/signedup") - .messages(Map.of(userSignUpMessage.getMessageId(), MessageReference.fromMessage(userSignUpMessage))) + .messages(Map.of(userSignUpMessage.getMessageId(), MessageReference.fromMessage("UserSignedUp"))) .build(); AsyncAPI asyncAPI = AsyncAPI.builder() diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/ChannelsService.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/ChannelsService.java index 80bdbec21..611277817 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/ChannelsService.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/ChannelsService.java @@ -2,6 +2,7 @@ package io.github.stavshamir.springwolf.asyncapi; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import java.util.Map; @@ -11,9 +12,16 @@ public interface ChannelsService { /** - * Detects all available AsyncAPI ChannelItem in the spring context. + * Detects all available AsyncAPI ChannelObject in the spring context. * * @return Map of channel names mapping to detected ChannelItems */ Map findChannels(); + + /** + * Detects all available AsyncAPI Operation in the spring context. + * + * @return Map of operation names mapping to detected Operations + */ + Map findOperations(); } diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiService.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiService.java index 6d06700fa..780118060 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiService.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultAsyncApiService.java @@ -4,6 +4,7 @@ import io.github.stavshamir.springwolf.asyncapi.types.AsyncAPI; import io.github.stavshamir.springwolf.asyncapi.types.Components; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import io.github.stavshamir.springwolf.configuration.AsyncApiDocket; import io.github.stavshamir.springwolf.configuration.AsyncApiDocketService; import io.github.stavshamir.springwolf.schemas.SchemasService; @@ -64,6 +65,8 @@ protected synchronized void initAsyncAPI() { // SchemasService. Map channels = channelsService.findChannels(); + Map operations = channelsService.findOperations(); + Components components = Components.builder() .schemas(schemasService.getDefinitions()) .build(); @@ -74,6 +77,7 @@ protected synchronized void initAsyncAPI() { .defaultContentType(docket.getDefaultContentType()) .servers(docket.getServers()) .channels(channels) + .operations(operations) .components(components) .build(); diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsService.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsService.java index 1415c85e2..97013eed9 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsService.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsService.java @@ -4,6 +4,7 @@ import io.github.stavshamir.springwolf.asyncapi.scanners.channels.ChannelMerger; import io.github.stavshamir.springwolf.asyncapi.scanners.channels.ChannelsScanner; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,12 +32,28 @@ public Map findChannels() { for (ChannelsScanner scanner : channelsScanners) { try { - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); foundChannelItems.addAll(channels.entrySet()); } catch (Exception e) { log.error("An error was encountered during channel scanning with {}: {}", scanner, e.getMessage(), e); } } - return ChannelMerger.merge(foundChannelItems); + return ChannelMerger.mergeChannels(foundChannelItems); + } + + // FIXME + @Override + public Map findOperations() { + List> foundOperations = new ArrayList<>(); + for (ChannelsScanner scanner : channelsScanners) { + try { + Map channels = scanner.scanOperations(); + foundOperations.addAll(channels.entrySet()); + } catch (Exception e) { + log.error("An error was encountered during operation scanning with {}: {}", scanner, e.getMessage(), e); + } + } + + return ChannelMerger.mergeOperations(foundOperations); } } diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/MessageHelper.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/MessageHelper.java index a75a58c48..b7ebfb45b 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/MessageHelper.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/MessageHelper.java @@ -1,51 +1,40 @@ // SPDX-License-Identifier: Apache-2.0 package io.github.stavshamir.springwolf.asyncapi; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.Message; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @Slf4j public class MessageHelper { - private static final String ONE_OF = "oneOf"; - private static final Comparator byMessageName = Comparator.comparing(MessageObject::getName); private static final Supplier> messageSupplier = () -> new TreeSet<>(byMessageName); - public static Object toMessageObjectOrComposition(Set messages) { - return switch (messages.size()) { - case 0 -> throw new IllegalArgumentException("messages must not be empty"); - case 1 -> messages.toArray()[0]; - default -> Map.of( - ONE_OF, new ArrayList<>(messages.stream().collect(Collectors.toCollection(messageSupplier)))); - }; - } + private MessageHelper() {} - @SuppressWarnings("unchecked") - public static Set messageObjectToSet(Object messageObject) { - if (messageObject instanceof MessageObject message) { - return new HashSet<>(Collections.singletonList(message)); + public static Map toMessagesMap(Set messages) { + if (messages.isEmpty()) { + throw new IllegalArgumentException("messages must not be empty"); } - if (messageObject instanceof Map) { - List messages = ((Map>) messageObject).get(ONE_OF); - return new HashSet<>(messages); - } + return new ArrayList<>(messages.stream().collect(Collectors.toCollection(messageSupplier))) + .stream().collect(Collectors.toMap(MessageObject::getMessageId, Function.identity())); + } - log.warn( - "Message object must contain either a Message or a Map, but contained: {}", - messageObject.getClass()); - return new HashSet<>(); + // FIXME: Do we need this method? + @SuppressWarnings("unchecked") + public static Set messageObjectToSet(Map messages) { + return new HashSet<>(messages.values()); } } 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 65622436e..e2024b4fc 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 @@ -4,7 +4,9 @@ import io.github.stavshamir.springwolf.asyncapi.MessageHelper; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.Channel; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.Message; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import java.util.HashMap; @@ -16,6 +18,8 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static io.github.stavshamir.springwolf.asyncapi.MessageHelper.toMessagesMap; + /** * Util to merge multiple {@link Channel}s */ @@ -27,52 +31,103 @@ private ChannelMerger() {} * Merges multiple channels by channel name *

* Given two channels for the same channel name, the first seen Channel is used - * If an operation is null, the next non-null operation is used - * Messages within operations are merged + * Messages within channels are merged * * @param channelEntries Ordered pairs of channel name to Channel * @return A map of channelName to a single Channel */ - public static Map merge(List> channelEntries) { + public static Map mergeChannels(List> channelEntries) { Map mergedChannels = new HashMap<>(); for (Map.Entry entry : channelEntries) { if (!mergedChannels.containsKey(entry.getKey())) { mergedChannels.put(entry.getKey(), entry.getValue()); } else { - ChannelObject channel = mergedChannels.get(entry.getKey()); - // channel.setPublish(mergeOperation(channel.getPublish(), entry.getValue().getPublish())); - // channel.setSubscribe(mergeOperation(channel.getSubscribe(), entry.getValue().getSubscribe())); + ChannelObject channel = mergeChannel(mergedChannels.get(entry.getKey()), entry.getValue()); + mergedChannels.put(entry.getKey(), channel); } } return mergedChannels; } + /** + * Merges multiple operations by operation name + *

+ * Given two operations for the same operation name, the first seen Operation is used + * If an operation is null, the next non-null operation is used + * Messages within operations are merged + * + * @param operationEntries Ordered pairs of operation name to Operation + * @return A map of operationName to a single Operation + */ + public static Map mergeOperations(List> operationEntries) { + Map mergedOperations = new HashMap<>(); + + for (Map.Entry entry : operationEntries) { + if (!mergedOperations.containsKey(entry.getKey())) { + mergedOperations.put(entry.getKey(), entry.getValue()); + } else { + Operation operation = mergeOperation(mergedOperations.get(entry.getKey()), entry.getValue()); + mergedOperations.put(entry.getKey(), operation); + } + } + + return mergedOperations; + } + + private static ChannelObject mergeChannel(ChannelObject channel, ChannelObject otherChannel) { + ChannelObject mergedChannel = channel != null ? channel : otherChannel; + + Set mergedMessages = mergeMessages(getMessages(channel), getMessages(otherChannel)); + if (!mergedMessages.isEmpty()) { + mergedChannel.setMessages(toMessagesMap(mergedMessages)); + } + return mergedChannel; + } + private static Operation mergeOperation(Operation operation, Operation otherOperation) { Operation mergedOperation = operation != null ? operation : otherOperation; - Set mergedMessages = mergeMessages(getMessages(operation), getMessages(otherOperation)); - // if (!mergedMessages.isEmpty()) { - // mergedOperation.setMessage(toMessageObjectOrComposition(mergedMessages)); FIXME - // } + List mergedMessages = + mergeMessageReferences(operation.getMessages(), otherOperation.getMessages()); + if (!mergedMessages.isEmpty()) { + mergedOperation.setMessages(mergedMessages); + } return mergedOperation; } - private static Set mergeMessages(Set messages, Set otherMessages) { - Map nameToMessage = - messages.stream().collect(Collectors.toMap(MessageObject::getName, Function.identity())); + private static Set mergeMessages(Set messages, Set otherMessages) { + // FIXME: We will lose any MessageReference we get + Map nameToMessage = messages.stream() + .filter(MessageObject.class::isInstance) + .map(MessageObject.class::cast) + .collect(Collectors.toMap(MessageObject::getName, Function.identity())); - for (MessageObject otherMessage : otherMessages) { - nameToMessage.putIfAbsent(otherMessage.getName(), otherMessage); + for (Message otherMessage : otherMessages) { + if (otherMessage instanceof MessageObject otherMessageObject) { + nameToMessage.putIfAbsent(otherMessageObject.getName(), otherMessageObject); + } } return new HashSet<>(nameToMessage.values()); } - private static Set getMessages(Operation operation) { - return Optional.ofNullable(operation) - .map(Operation::getMessages) + private static List mergeMessageReferences( + List messages, List otherMessages) { + var messageReferences = new HashSet(); + if (messages != null) { + messageReferences.addAll(messages); + } + if (otherMessages != null) { + messageReferences.addAll(otherMessages); + } + return messageReferences.stream().toList(); + } + + private static Set getMessages(ChannelObject channel) { + return Optional.ofNullable(channel) + .map(ChannelObject::getMessages) .map(MessageHelper::messageObjectToSet) .orElseGet(HashSet::new); } diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelsScanner.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelsScanner.java index 6528eb439..9ca09deb5 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/ChannelsScanner.java @@ -2,6 +2,7 @@ package io.github.stavshamir.springwolf.asyncapi.scanners.channels; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import java.util.Map; @@ -10,5 +11,10 @@ public interface ChannelsScanner { /** * @return A mapping of channel names to their respective channel object for a given protocol. */ - Map scan(); + Map scanChannels(); + + /** + * @return A mapping of operation names to their respective operation object for a given protocol. + */ + Map scanOperations(); } diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScanner.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScanner.java index f0fd884a8..c6729a139 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScanner.java @@ -3,6 +3,7 @@ import io.github.stavshamir.springwolf.asyncapi.scanners.classes.ClassScanner; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import lombok.RequiredArgsConstructor; import java.util.List; @@ -18,19 +19,34 @@ public class SimpleChannelsScanner implements ChannelsScanner { private final ClassProcessor classProcessor; @Override - public Map scan() { + public Map scanChannels() { Set> components = classScanner.scan(); List> channels = mapToChannels(components); - return ChannelMerger.merge(channels); + return ChannelMerger.mergeChannels(channels); + } + + @Override + public Map scanOperations() { + Set> components = classScanner.scan(); + + List> operations = mapToOperations(components); + + return ChannelMerger.mergeOperations(operations); } private List> mapToChannels(Set> components) { - return components.stream().flatMap(classProcessor::process).toList(); + return components.stream().flatMap(classProcessor::processChannels).toList(); + } + + private List> mapToOperations(Set> components) { + return components.stream().flatMap(classProcessor::processOperations).toList(); } public interface ClassProcessor { - Stream> process(Class clazz); + Stream> processChannels(Class clazz); + + Stream> processOperations(Class clazz); } } 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 716a9d6d0..7fe2ab2c5 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 @@ -14,8 +14,14 @@ import io.github.stavshamir.springwolf.asyncapi.v3.bindings.OperationBinding; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ServerReference; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; +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.AsyncApiDocketService; import io.github.stavshamir.springwolf.schemas.SchemasService; @@ -54,14 +60,25 @@ public void setEmbeddedValueResolver(StringValueResolver resolver) { } @Override - public Map scan() { + public Map scanChannels() { List> channels = classScanner.scan().stream() .flatMap(this::getAnnotatedMethods) .map(this::buildChannel) .filter(this::isInvalidChannel) .toList(); - return ChannelMerger.merge(channels); + return ChannelMerger.mergeChannels(channels); + } + + @Override + public Map scanOperations() { + List> operations = classScanner.scan().stream() + .flatMap(this::getAnnotatedMethods) + .map(this::buildOperation) + .filter(this::isInvalidOperation) + .toList(); + + return ChannelMerger.mergeOperations(operations); } private Stream> getAnnotatedMethods(Class type) { @@ -95,6 +112,25 @@ private boolean isInvalidChannel(Map.Entry entry) { return allNonNull; } + private boolean isInvalidOperation(Map.Entry entry) { + // Operation publish = entry.getValue().getPublish(); + // boolean publishBindingExists = publish != null && publish.getBindings() != null; + // + // Operation subscribe = entry.getValue().getSubscribe(); + // boolean subscribeBindingExists = subscribe != null && subscribe.getBindings() != null; + + boolean allNonNull = entry.getKey() != null; // && (publishBindingExists || subscribeBindingExists); FIXME + + if (!allNonNull) { + log.warn( + "Some data fields are null - method (channel={}) will not be documented: {}", + entry.getKey(), + entry.getValue()); + } + + return allNonNull; + } + private Map.Entry buildChannel(MethodAndAnnotation methodAndAnnotation) { ChannelObject.ChannelObjectBuilder channelBuilder = ChannelObject.builder(); @@ -103,11 +139,6 @@ private Map.Entry buildChannel(MethodAndAnnotation met String channelName = resolver.resolveStringValue(operationAnnotation.channelName()); Operation operation = buildOperation(operationAnnotation, methodAndAnnotation.method(), channelName); - // FIXME - // switch (this.asyncAnnotationProvider.getOperationType()) { - // case PUBLISH -> channelBuilder.publish(operation); - // case SUBSCRIBE -> channelBuilder.subscribe(operation); - // }; List servers = AsyncAnnotationScannerUtil.getServers(operationAnnotation, resolver); if (servers != null && !servers.isEmpty()) { @@ -117,11 +148,33 @@ private Map.Entry buildChannel(MethodAndAnnotation met .map(it -> ServerReference.builder().ref(it).build()) .toList()); } + MessageObject message = buildMessage(operationAnnotation, methodAndAnnotation.method()); - ChannelObject channelItem = channelBuilder.build(); + ChannelObject channelItem = + channelBuilder.messages(Map.of(message.getMessageId(), message)).build(); return Map.entry(channelName, channelItem); } + private Map.Entry buildOperation(MethodAndAnnotation methodAndAnnotation) { + Operation.OperationBuilder operationBuilder = Operation.builder(); + AsyncOperation operationAnnotation = + this.asyncAnnotationProvider.getAsyncOperation(methodAndAnnotation.annotation()); + String operationName = resolver.resolveStringValue(operationAnnotation.channelName()); + + Operation operation = buildOperation(operationAnnotation, methodAndAnnotation.method(), operationName); + switch (this.asyncAnnotationProvider.getOperationType()) { + case PUBLISH -> operation.setAction(OperationAction.RECEIVE); + case SUBSCRIBE -> operation.setAction(OperationAction.SEND); + } + + MessageObject message = buildMessage(operationAnnotation, methodAndAnnotation.method()); + + // FIXME + // Operation operation = + // operationBuilder.messages(Map.of(message.getMessageId(), message)).build(); + return Map.entry(operationName, operation); + } + private Operation buildOperation(AsyncOperation asyncOperation, Method method, String channelName) { String description = this.resolver.resolveStringValue(asyncOperation.description()); if (!StringUtils.hasText(description)) { @@ -133,12 +186,13 @@ private Operation buildOperation(AsyncOperation asyncOperation, Method method, S Map operationBinding = AsyncAnnotationScannerUtil.processOperationBindingFromAnnotation(method, operationBindingProcessors); Map opBinding = operationBinding != null ? new HashMap<>(operationBinding) : null; + MessageObject message = buildMessage(asyncOperation, method); return Operation.builder() .description(description) .title(operationTitle) - // FIXME: Message should be the reference - // .message(buildMessage(asyncOperation, method)) + // FIXME: We can use the message reference once everything else works + .messages(List.of(MessageReference.fromMessage(message))) .bindings(opBinding) .build(); } @@ -151,6 +205,7 @@ private MessageObject buildMessage(AsyncOperation operationData, Method method) String modelName = this.schemasService.register(payloadType); AsyncHeaders asyncHeaders = AsyncAnnotationScannerUtil.getAsyncHeaders(operationData, resolver); String headerModelName = this.schemasService.register(asyncHeaders); + var headers = MessageHeaders.of(MessageReference.fromSchema(headerModelName)); var schema = payloadType.getAnnotation(Schema.class); String description = schema != null ? schema.description() : null; @@ -158,12 +213,17 @@ private MessageObject buildMessage(AsyncOperation operationData, Method method) Map messageBinding = AsyncAnnotationScannerUtil.processMessageBindingFromAnnotation(method, messageBindingProcessors); + var messagePayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(modelName)) + .build()); + var builder = MessageObject.builder() + .messageId(payloadType.getName()) .name(payloadType.getName()) .title(payloadType.getSimpleName()) .description(description) - // .payload(PayloadReference.fromModelName(modelName)) FIXME - // .headers(HeaderReference.fromModelName(headerModelName)) FIXME + .payload(messagePayload) + .headers(headers) .bindings(messageBinding); // Retrieve the Message information obtained from the @AsyncMessage annotation. These values have higher 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 0638df171..8581ae2c1 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 @@ -25,6 +25,8 @@ import static java.util.stream.Collectors.groupingBy; class AsyncAnnotationScannerUtil { + private AsyncAnnotationScannerUtil() {} + public static AsyncHeaders getAsyncHeaders(AsyncOperation op, StringValueResolver resolver) { if (op.headers().values().length == 0) { return AsyncHeaders.NOT_DOCUMENTED; @@ -42,6 +44,14 @@ public static AsyncHeaders getAsyncHeaders(AsyncOperation op, StringValueResolve .enumValue(values) .example(exampleValue) .build()); + + // FIXME: Replace AsyncHeaders by proper AsyncAPI v3 Headers + // MessageHeaders.of( + // SchemaObject.builder() + // .description(getDescription(headers, resolver)) + // .enumValues(values) + // .examples(exampleValue != null ? List.of(exampleValue) : null) + // .build()); }); return asyncHeaders; @@ -53,7 +63,7 @@ private static List getHeaderValues( .map(AsyncOperation.Headers.Header::value) .map(resolver::resolveStringValue) .sorted() - .collect(Collectors.toList()); + .toList(); } private static String getDescription(List value, StringValueResolver resolver) { @@ -106,8 +116,8 @@ public static void processAsyncMessageAnnotation( } // FIXME - // String annotationSchemaFormat = asyncMessage.schemaFormat(); - // var schemaFormat = annotationSchemaFormat != null ? annotationSchemaFormat : + // String annotationSchemaFormat = asyncMessage.schemaFormat(); + // var schemaFormat = annotationSchemaFormat != null ? annotationSchemaFormat : // Message.DEFAULT_SCHEMA_FORMAT; // messageBuilder.schemaFormat(schemaFormat); @@ -118,7 +128,7 @@ public static void processAsyncMessageAnnotation( } /** - * extracts servers array from the given AsyncOperation, resolves placeholdes with spring variables and + * extracts servers array from the given AsyncOperation, resolves placeholders with spring variables and * return a List of server names. * * @param op the given AsyncOperation 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 68fc978e2..0c94c03f5 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 @@ -9,8 +9,14 @@ import io.github.stavshamir.springwolf.asyncapi.v3.bindings.MessageBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.OperationBinding; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.Message; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; +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.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.schemas.SchemasService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -24,7 +30,7 @@ import java.util.Set; import java.util.stream.Stream; -import static io.github.stavshamir.springwolf.asyncapi.MessageHelper.toMessageObjectOrComposition; +import static io.github.stavshamir.springwolf.asyncapi.MessageHelper.toMessagesMap; import static java.util.stream.Collectors.toSet; @RequiredArgsConstructor @@ -41,13 +47,21 @@ public class ClassLevelAnnotationChannelsScanner< private final SchemasService schemasService; @Override - public Stream> process(Class clazz) { + public Stream> processChannels(Class clazz) { log.debug( "Scanning class \"{}\" for @\"{}\" annotated methods", clazz.getName(), classAnnotationClass.getName()); return Stream.of(clazz).filter(this::isClassAnnotated).flatMap(this::mapClassToChannel); } + @Override + public Stream> processOperations(Class clazz) { + log.debug( + "Scanning class \"{}\" for @\"{}\" annotated methods", clazz.getName(), classAnnotationClass.getName()); + + return Stream.of(clazz).filter(this::isClassAnnotated).flatMap(this::mapClassToOperation); + } + private boolean isClassAnnotated(Class component) { return AnnotationUtil.findAnnotation(classAnnotationClass, component) != null; } @@ -75,20 +89,42 @@ private Stream> mapClassToChannel(Class comp } String channelName = bindingFactory.getChannelName(classAnnotation); - String operationId = channelName + "_publish_" + component.getSimpleName(); - ChannelObject channelItem = buildChannelItem(classAnnotation, operationId, annotatedMethods); + ChannelObject channelItem = buildChannelItem(classAnnotation, annotatedMethods); return Stream.of(Map.entry(channelName, channelItem)); } - private ChannelObject buildChannelItem(ClassAnnotation classAnnotation, String operationId, Set methods) { - Object message = buildMessageObject(classAnnotation, methods); - Operation operation = buildOperation(classAnnotation, operationId, message); - return buildChannelItem(classAnnotation, operation); + private Stream> mapClassToOperation(Class component) { + log.debug("Mapping class \"{}\" to channels", component.getName()); + + ClassAnnotation classAnnotation = AnnotationUtil.findAnnotationOrThrow(classAnnotationClass, component); + + Set annotatedMethods = getAnnotatedMethods(component); + if (annotatedMethods.isEmpty()) { + return Stream.empty(); + } + + // FIXME + String channelName = bindingFactory.getChannelName(classAnnotation); + String operationId = channelName + "_publish_" + component.getSimpleName(); + + Operation operation = buildOperation(classAnnotation, annotatedMethods); + + return Stream.of(Map.entry(operationId, operation)); + } + + private ChannelObject buildChannelItem(ClassAnnotation classAnnotation, Set methods) { + var messages = buildMessages(classAnnotation, methods); + return buildChannelItem(classAnnotation, messages); } - private Object buildMessageObject(ClassAnnotation classAnnotation, Set methods) { + private Operation buildOperation(ClassAnnotation classAnnotation, Set methods) { + var messages = buildMessages(classAnnotation, methods); + return buildOperation(classAnnotation, messages); + } + + private Map buildMessages(ClassAnnotation classAnnotation, Set methods) { Set messages = methods.stream() .map((Method method) -> { Class payloadType = payloadClassExtractor.extractFrom(method); @@ -96,7 +132,7 @@ private Object buildMessageObject(ClassAnnotation classAnnotation, Set m }) .collect(toSet()); - return toMessageObjectOrComposition(messages); + return toMessagesMap(messages); } private MessageObject buildMessage(ClassAnnotation classAnnotation, Class payloadType) { @@ -104,33 +140,31 @@ private MessageObject buildMessage(ClassAnnotation classAnnotation, Class pay String modelName = schemasService.register(payloadType); String headerModelName = schemasService.register(asyncHeadersBuilder.buildHeaders(payloadType)); + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(modelName)) + .build()); + return MessageObject.builder() + .messageId(payloadType.getName()) .name(payloadType.getName()) .title(payloadType.getSimpleName()) .description(null) - // .payload(PayloadReference.fromModelName(modelName)) FIXME - // .headers(HeaderReference.fromModelName(headerModelName)) FIXME + .payload(payload) + .headers(MessageHeaders.of(MessageReference.fromSchema(headerModelName))) .bindings(messageBinding) .build(); } - private Operation buildOperation(ClassAnnotation classAnnotation, String operationTitle, Object message) { - Map operationBinding = bindingFactory.buildOperationBinding(classAnnotation); - Map opBinding = operationBinding != null ? new HashMap<>(operationBinding) : null; - - return Operation.builder() - .description("Auto-generated description") - .title(operationTitle) - // .message(message) - .bindings(opBinding) - .build(); - } - - private ChannelObject buildChannelItem(ClassAnnotation classAnnotation, Operation operation) { + private ChannelObject buildChannelItem(ClassAnnotation classAnnotation, Map messages) { Map channelBinding = bindingFactory.buildChannelBinding(classAnnotation); Map chBinding = channelBinding != null ? new HashMap<>(channelBinding) : null; - return ChannelObject.builder() - .bindings(chBinding) /*.publish(operation) FIXME*/ - .build(); + return ChannelObject.builder().bindings(chBinding).messages(messages).build(); + } + + private Operation buildOperation(ClassAnnotation classAnnotation, Map messages) { + Map operationBinding = bindingFactory.buildOperationBinding(classAnnotation); + Map opBinding = operationBinding != null ? new HashMap<>(operationBinding) : null; + // FIXME + return Operation.builder().bindings(opBinding) /*.messages(messages)*/.build(); } } 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 6e00c8299..5e2df5aa1 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 @@ -9,8 +9,13 @@ import io.github.stavshamir.springwolf.asyncapi.v3.bindings.MessageBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.OperationBinding; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; +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.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.schemas.SchemasService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,6 +24,7 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -33,7 +39,7 @@ public class MethodLevelAnnotationChannelsScanner> process(Class clazz) { + public Stream> processChannels(Class clazz) { log.debug( "Scanning class \"{}\" for @\"{}\" annotated methods", clazz.getName(), @@ -45,58 +51,91 @@ public Stream> process(Class clazz) { .map(this::mapMethodToChannel); } + @Override + public Stream> processOperations(Class clazz) { + log.debug( + "Scanning class \"{}\" for @\"{}\" annotated methods", + clazz.getName(), + methodAnnotationClass.getName()); + + return Arrays.stream(clazz.getDeclaredMethods()) + .filter(method -> !method.isBridge()) + .filter(method -> AnnotationUtil.findAnnotation(methodAnnotationClass, method) != null) + .map(this::mapMethodToOperation); + } + private Map.Entry mapMethodToChannel(Method method) { log.debug("Mapping method \"{}\" to channels", method.getName()); MethodAnnotation annotation = AnnotationUtil.findAnnotationOrThrow(methodAnnotationClass, method); String channelName = bindingFactory.getChannelName(annotation); - String operationId = channelName + "_publish_" + method.getName(); Class payload = payloadClassExtractor.extractFrom(method); - ChannelObject channelItem = buildChannelItem(annotation, operationId, payload); + ChannelObject channelItem = buildChannelItem(annotation, payload); return Map.entry(channelName, channelItem); } - private ChannelObject buildChannelItem(MethodAnnotation annotation, String operationId, Class payloadType) { + private Map.Entry mapMethodToOperation(Method method) { + log.debug("Mapping method \"{}\" to operations", method.getName()); + + MethodAnnotation annotation = AnnotationUtil.findAnnotationOrThrow(methodAnnotationClass, method); + + String channelName = bindingFactory.getChannelName(annotation); + String operationId = channelName + "_publish_" + method.getName(); + Class payload = payloadClassExtractor.extractFrom(method); + + Operation operation = buildOperation(annotation, payload); + return Map.entry(operationId, operation); + } + + private ChannelObject buildChannelItem(MethodAnnotation annotation, Class payloadType) { MessageObject message = buildMessage(annotation, payloadType); - Operation operation = buildOperation(annotation, operationId, message); - return buildChannelItem(annotation, operation); + return buildChannelItem(annotation, message); + } + + private Operation buildOperation(MethodAnnotation annotation, Class payloadType) { + MessageObject message = buildMessage(annotation, payloadType); + return buildOperation(annotation, message); } private MessageObject buildMessage(MethodAnnotation annotation, Class payloadType) { Map messageBinding = bindingFactory.buildMessageBinding(annotation); String modelName = schemasService.register(payloadType); String headerModelName = schemasService.register(AsyncHeaders.NOT_DOCUMENTED); + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(modelName)) + .build()); return MessageObject.builder() + .messageId(payloadType.getName()) .name(payloadType.getName()) .title(payloadType.getSimpleName()) .description(null) - // .payload(PayloadReference.fromModelName(modelName)) FIXME - // .headers(HeaderReference.fromModelName(headerModelName)) FIXME + .payload(payload) + .headers(MessageHeaders.of(MessageReference.fromSchema(headerModelName))) .bindings(messageBinding) .build(); } - private Operation buildOperation(MethodAnnotation annotation, String operationTitle, MessageObject message) { + private ChannelObject buildChannelItem(MethodAnnotation annotation, MessageObject message) { + Map channelBinding = bindingFactory.buildChannelBinding(annotation); + Map chBinding = channelBinding != null ? new HashMap<>(channelBinding) : null; + return ChannelObject.builder() + // FIXME: We can use the message reference once everything else works + .messages(Map.of(message.getMessageId(), message)) + .bindings(chBinding) + .build(); + } + + private Operation buildOperation(MethodAnnotation annotation, MessageObject message) { Map operationBinding = bindingFactory.buildOperationBinding(annotation); Map opBinding = operationBinding != null ? new HashMap<>(operationBinding) : null; return Operation.builder() - .description("Auto-generated description") - .title(operationTitle) - // .message(message) + .messages(List.of(MessageReference.fromMessage(message))) .bindings(opBinding) .build(); } - - private ChannelObject buildChannelItem(MethodAnnotation annotation, Operation operation) { - Map channelBinding = bindingFactory.buildChannelBinding(annotation); - Map chBinding = channelBinding != null ? new HashMap<>(channelBinding) : null; - return ChannelObject.builder() - .bindings(chBinding) /*.publish(operation) FIXME*/ - .build(); - } } diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/OperationData.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/OperationData.java index f2827b988..536214a3e 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/OperationData.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/OperationData.java @@ -60,6 +60,7 @@ public interface OperationData { MessageObject getMessage(); + // FIXME: With AsyncAPI v3 this should be Action: SEND / RECEIVER enum OperationType { PUBLISH("publish"), SUBSCRIBE("subscribe"); diff --git a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/channel/operation/message/header/AsyncHeadersNotDocumented.java b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/channel/operation/message/header/AsyncHeadersNotDocumented.java index e2b25b227..1c7020034 100644 --- a/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/channel/operation/message/header/AsyncHeadersNotDocumented.java +++ b/springwolf-core/src/main/java/io/github/stavshamir/springwolf/asyncapi/types/channel/operation/message/header/AsyncHeadersNotDocumented.java @@ -10,6 +10,6 @@ public class AsyncHeadersNotDocumented implements AsyncHeadersBuilder { @Override public AsyncHeaders buildHeaders(Class payloadType) { - return AsyncHeaders.NOT_DOCUMENTED; + return NOT_DOCUMENTED; } } diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsServiceIntegrationTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsServiceIntegrationTest.java index ef2e35fbf..5af926bd1 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsServiceIntegrationTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/DefaultChannelsServiceIntegrationTest.java @@ -40,25 +40,37 @@ void getChannels() { Map actualChannels = defaultChannelsService.findChannels(); assertThat(actualChannels) - .containsAllEntriesOf(fooChannelScanner.scan()) - .containsAllEntriesOf(barChannelScanner.scan()) + .containsAllEntriesOf(fooChannelScanner.scanChannels()) + .containsAllEntriesOf(barChannelScanner.scanChannels()) .containsEntry(SameTopic.topicName, SameTopic.expectedMergedChannel); } @Component static class FooChannelScanner implements ChannelsScanner { @Override - public Map scan() { + public Map scanChannels() { return Map.of("foo", new ChannelObject()); } + + @Override + public Map scanOperations() { + // FIXME + return Map.of(); + } } @Component static class BarChannelScanner implements ChannelsScanner { @Override - public Map scan() { + public Map scanChannels() { return Map.of("bar", new ChannelObject()); } + + @Override + public Map scanOperations() { + // FIXME + return Map.of(); + } } static class SameTopic { @@ -74,12 +86,18 @@ static class ProduceChannelScanner implements ChannelsScanner { Operation.builder() /*.message("publish")FIXME*/.build(); @Override - public Map scan() { + public Map scanChannels() { return Map.of( topicName, ChannelObject.builder() /*.publish(publishOperation) FIXME*/ .build()); } + + @Override + public Map scanOperations() { + // FIXME + return Map.of(); + } } @Component @@ -88,12 +106,18 @@ static class SubscribeChannelScanner implements ChannelsScanner { Operation.builder() /*.message("consumer")FIXME*/.build(); @Override - public Map scan() { + public Map scanChannels() { return Map.of( topicName, ChannelObject.builder() /*.subscribe(subscribeOperation)FIXME*/ .build()); } + + @Override + public Map scanOperations() { + // FIXME + return Map.of(); + } } } } diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/MessageHelperTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/MessageHelperTest.java index 2810e3dca..ad9ceea9a 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/MessageHelperTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/MessageHelperTest.java @@ -6,12 +6,12 @@ import org.junit.jupiter.api.Test; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Set; import static io.github.stavshamir.springwolf.asyncapi.MessageHelper.messageObjectToSet; -import static io.github.stavshamir.springwolf.asyncapi.MessageHelper.toMessageObjectOrComposition; +import static io.github.stavshamir.springwolf.asyncapi.MessageHelper.toMessagesMap; +import static java.util.Map.entry; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -19,32 +19,31 @@ class MessageHelperTest { @Test void toMessageObjectOrComposition_emptySet() { - assertThatThrownBy(() -> toMessageObjectOrComposition(Collections.emptySet())) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> toMessagesMap(Collections.emptySet())).isInstanceOf(IllegalArgumentException.class); } @Test - void toMessageObjectOrComposition_oneMessage() { + void toMessagesMap_oneMessage() { MessageObject message = MessageObject.builder().name("foo").build(); - Object asObject = toMessageObjectOrComposition(Set.of(message)); + var messagesMap = toMessagesMap(Set.of(message)); - assertThat(asObject).isInstanceOf(Message.class).isEqualTo(message); + assertThat(messagesMap).containsExactlyInAnyOrderEntriesOf(Map.of("foo", message)); } @Test - void toMessageObjectOrComposition_multipleMessages() { + void toMessagesMap_multipleMessages() { MessageObject message1 = MessageObject.builder().name("foo").build(); MessageObject message2 = MessageObject.builder().name("bar").build(); - Object asObject = toMessageObjectOrComposition(Set.of(message1, message2)); + var messages = toMessagesMap(Set.of(message1, message2)); - assertThat(asObject).isInstanceOf(Map.class).isEqualTo(Map.of("oneOf", List.of(message2, message1))); + assertThat(messages).containsExactlyInAnyOrderEntriesOf(Map.of("bar", message2, "foo", message1)); } @Test - void toMessageObjectOrComposition_multipleMessages_remove_duplicates() { + void toMessagesMap_multipleMessages_remove_duplicates() { MessageObject message1 = MessageObject.builder() .name("foo") .description("This is message 1") @@ -60,17 +59,17 @@ void toMessageObjectOrComposition_multipleMessages_remove_duplicates() { .description("This is message 3, but in essence the same payload type as message 2") .build(); - Object asObject = toMessageObjectOrComposition(Set.of(message1, message2, message3)); + var messages = toMessagesMap(Set.of(message1, message2, message3)); - Map> oneOfMap = (Map>) asObject; - assertThat(oneOfMap).hasSize(1); - List deduplicatedMessageList = oneOfMap.get("oneOf"); - // we do not have any guarantee wether message2 or message3 won the deduplication. - assertThat(deduplicatedMessageList).hasSize(2).contains(message1).containsAnyOf(message2, message3); + // we do not have any guarantee whether message2 or message3 won the deduplication. + assertThat(messages) + .hasSize(2) + .containsValue(message1) + .containsAnyOf(entry("bar", message2), entry("bar", message3)); } @Test - void toMessageObjectOrComposition_multipleMessages_should_not_break_deep_equals() { + void toMessagesMap_multipleMessages_should_not_break_deep_equals() { MessageObject actualMessage1 = MessageObject.builder() .name("foo") .description("This is actual message 1") @@ -81,7 +80,7 @@ void toMessageObjectOrComposition_multipleMessages_should_not_break_deep_equals( .description("This is actual message 2") .build(); - Object actualObject = toMessageObjectOrComposition(Set.of(actualMessage1, actualMessage2)); + Object actualObject = toMessagesMap(Set.of(actualMessage1, actualMessage2)); MessageObject expectedMessage1 = MessageObject.builder() .name("foo") @@ -93,26 +92,17 @@ void toMessageObjectOrComposition_multipleMessages_should_not_break_deep_equals( .description("This is expected message 2") .build(); - Object expectedObject = toMessageObjectOrComposition(Set.of(expectedMessage1, expectedMessage2)); + Object expectedObject = toMessagesMap(Set.of(expectedMessage1, expectedMessage2)); assertThat(actualObject).isNotEqualTo(expectedObject); } - @Test - void messageObjectToSet_notAMessageOrAMap() { - Object string = "foo"; - - Set messages = messageObjectToSet(string); - - assertThat(messages).isEmpty(); - } - @Test void messageObjectToSet_Message() { MessageObject message = MessageObject.builder().name("foo").build(); - Object asObject = toMessageObjectOrComposition(Set.of(message)); + var asMap = toMessagesMap(Set.of(message)); - Set messages = messageObjectToSet(asObject); + Set messages = messageObjectToSet(asMap); assertThat(messages).containsExactly(message); } @@ -123,9 +113,9 @@ void messageObjectToSet_SetOfMessage() { MessageObject message2 = MessageObject.builder().name("bar").build(); - Object asObject = toMessageObjectOrComposition(Set.of(message1, message2)); + var asMap = toMessagesMap(Set.of(message1, message2)); - Set messages = messageObjectToSet(asObject); + Set messages = messageObjectToSet(asMap); assertThat(messages).containsExactlyInAnyOrder(message1, message2); } 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 3a96d5ae1..7a613f922 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 @@ -4,11 +4,13 @@ import io.github.stavshamir.springwolf.asyncapi.MessageHelper; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +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 org.junit.jupiter.api.Test; import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.Set; @@ -21,33 +23,52 @@ void shouldNotMergeDifferentChannelNames() { // given String channelName1 = "channel1"; String channelName2 = "channel2"; - // Operation publishOperation = - // Operation.builder().action(OperationAction.SEND).build(); - // Operation subscribeOperation = - // Operation.builder().action(OperationAction.RECEIVE).build(); ChannelObject publisherChannel = ChannelObject.builder().build(); ChannelObject subscriberChannel = ChannelObject.builder().build(); // when - Map mergedChannels = ChannelMerger.merge( + Map mergedChannels = ChannelMerger.mergeChannels( Arrays.asList(Map.entry(channelName1, publisherChannel), Map.entry(channelName2, subscriberChannel))); // then assertThat(mergedChannels).hasSize(2); - // .hasEntrySatisfying(channelName1, it -> { - // assertThat(it.getPublish()).isEqualTo(publishOperation); - // assertThat(it.getSubscribe()).isNull(); - // }) - // .hasEntrySatisfying(channelName2, it -> { - // assertThat(it.getPublish()).isNull(); - // assertThat(it.getSubscribe()).isEqualTo(subscribeOperation); - // }); } @Test - void shouldMergePublisherAndSubscriberIntoOneChannel() { + void shouldNotMergeDifferentOperationNames() { + // given + String operationName1 = "operation1"; + String operationName2 = "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))); + + // then + assertThat(mergedOperations).hasSize(2); + } + + @Test + void shouldMergeEqualChannelNamesIntoOneChannel() { // given String channelName = "channel"; + ChannelObject publisherChannel = ChannelObject.builder().build(); + ChannelObject subscriberChannel = ChannelObject.builder().build(); + + // when + Map mergedChannels = ChannelMerger.mergeChannels( + Arrays.asList(Map.entry(channelName, publisherChannel), Map.entry(channelName, subscriberChannel))); + + // then + assertThat(mergedChannels).hasSize(1); + } + + @Test + void shouldMergeEqualOperationNamesIntoOneOperation() { + // given + String operationName = "operation"; Operation publishOperation = Operation.builder() .action(OperationAction.SEND) .title("publisher") @@ -56,100 +77,146 @@ void shouldMergePublisherAndSubscriberIntoOneChannel() { .action(OperationAction.RECEIVE) .title("subscribe") .build(); - ChannelObject publisherChannel = ChannelObject.builder().build(); - ChannelObject subscriberChannel = ChannelObject.builder().build(); // when - Map mergedChannels = ChannelMerger.merge( - Arrays.asList(Map.entry(channelName, publisherChannel), Map.entry(channelName, subscriberChannel))); + Map mergedOperations = ChannelMerger.mergeOperations(Arrays.asList( + Map.entry(operationName, publishOperation), Map.entry(operationName, subscribeOperation))); // then - assertThat(mergedChannels).hasSize(1); - // FIXME - // .hasEntrySatisfying(channelName, it -> { - // assertThat(it.getPublish()).isEqualTo(publishOperation); - // assertThat(it.getSubscribe()).isEqualTo(subscribeOperation); - // }); + assertThat(mergedOperations).hasSize(1); + } + + @Test + void shouldUseFirstChannelFound() { + // given + String channelName = "channel"; + ChannelObject publisherChannel1 = + ChannelObject.builder().channelId("channel1").build(); + ChannelObject publisherChannel2 = + ChannelObject.builder().channelId("channel2").build(); + + // when + Map mergedChannels = ChannelMerger.mergeChannels( + Arrays.asList(Map.entry(channelName, publisherChannel1), Map.entry(channelName, publisherChannel2))); + + // then + assertThat(mergedChannels).hasSize(1).hasEntrySatisfying(channelName, it -> { + assertThat(it.getChannelId()).isEqualTo("channel1"); + }); } @Test void shouldUseFirstOperationFound() { + // given + String operationName = "operation"; + Operation senderOperation = + Operation.builder().action(OperationAction.SEND).build(); + Operation receiverOperation = + Operation.builder().action(OperationAction.RECEIVE).build(); + + // when + Map mergedOperations = ChannelMerger.mergeOperations( + Arrays.asList(Map.entry(operationName, senderOperation), Map.entry(operationName, receiverOperation))); + + // then + assertThat(mergedOperations).hasSize(1).hasEntrySatisfying(operationName, it -> { + assertThat(it.getAction()).isEqualTo(OperationAction.SEND); + }); + } + + @Test + void shouldMergeDifferentMessagesForSameChannel() { // given String channelName = "channel"; - Operation publishOperation1 = Operation.builder() - .action(OperationAction.SEND) - .title("publisher1") + MessageObject message1 = MessageObject.builder() + .messageId("message1") + .name(String.class.getCanonicalName()) + .description("This is a string") .build(); - Operation publishOperation2 = Operation.builder() - .action(OperationAction.RECEIVE) - .title("publisher2") + MessageObject message2 = MessageObject.builder() + .messageId("message2") + .name(Integer.class.getCanonicalName()) + .description("This is an integer") + .build(); + MessageObject message3 = MessageObject.builder() + .messageId("message3") + .name(Integer.class.getCanonicalName()) + .description("This is also an integer, but in essence the same payload type") + .build(); + ChannelObject publisherChannel1 = ChannelObject.builder() + .messages(Map.of(message1.getMessageId(), message1)) + .build(); + ChannelObject publisherChannel2 = ChannelObject.builder() + .messages(Map.of(message2.getMessageId(), message2)) + .build(); + ChannelObject publisherChannel3 = ChannelObject.builder() + .messages(Map.of(message3.getMessageId(), message3)) .build(); - ChannelObject publisherChannel1 = ChannelObject.builder().build(); - ChannelObject publisherChannel2 = ChannelObject.builder().build(); // when - Map mergedChannels = ChannelMerger.merge( - Arrays.asList(Map.entry(channelName, publisherChannel1), Map.entry(channelName, publisherChannel2))); + Map mergedChannels = ChannelMerger.mergeChannels(Arrays.asList( + Map.entry(channelName, publisherChannel1), + Map.entry(channelName, publisherChannel2), + Map.entry(channelName, publisherChannel3))); - // then - assertThat(mergedChannels).hasSize(1); - // FIXME - // .hasEntrySatisfying(channelName, it -> { - // assertThat(it.getPublish()).isEqualTo(publishOperation1); - // assertThat(it.getSubscribe()).isNull(); - // }); + // 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 + var expectedMessages = MessageHelper.toMessagesMap(Set.of(message1, message2)); + assertThat(mergedChannels).hasSize(1).hasEntrySatisfying(channelName, it -> { + assertThat(it.getMessages()).containsExactlyEntriesOf(expectedMessages); + }); } @Test void shouldMergeDifferentMessageForSameOperation() { // given - String channelName = "channel"; + String operationName = "operation"; MessageObject message1 = MessageObject.builder() + .messageId("message1") .name(String.class.getCanonicalName()) .description("This is a string") .build(); MessageObject message2 = MessageObject.builder() + .messageId("message2") .name(Integer.class.getCanonicalName()) .description("This is an integer") .build(); MessageObject message3 = MessageObject.builder() + .messageId("message3") .name(Integer.class.getCanonicalName()) .description("This is also an integer, but in essence the same payload type") .build(); - Operation publishOperation1 = Operation.builder() + MessageReference messageRef1 = MessageReference.fromMessage(message1); + MessageReference messageRef2 = MessageReference.fromMessage(message2); + MessageReference messageRef3 = MessageReference.fromMessage(message3); + + Operation senderOperation1 = Operation.builder() .action(OperationAction.SEND) - .title("publisher1") /*.message(message1)FIXME*/ + .title("sender1") + .messages(List.of(messageRef1)) .build(); - Operation publishOperation2 = Operation.builder() + Operation senderOperation2 = Operation.builder() .action(OperationAction.SEND) - .title("publisher2") /*.message(message2)FIXME*/ + .title("sender2") + .messages(List.of(messageRef2)) .build(); - Operation publishOperation3 = Operation.builder() + Operation senderOperation3 = Operation.builder() .action(OperationAction.SEND) - .title("publisher3") /*.message(message3)FIXME*/ + .title("sender3") + .messages(List.of(messageRef3)) .build(); - ChannelObject publisherChannel1 = ChannelObject.builder().build(); - ChannelObject publisherChannel2 = ChannelObject.builder().build(); - ChannelObject publisherChannel3 = ChannelObject.builder().build(); // when - Map mergedChannels = ChannelMerger.merge(Arrays.asList( - Map.entry(channelName, publisherChannel1), - Map.entry(channelName, publisherChannel2), - Map.entry(channelName, publisherChannel3))); + Map mergedOperations = ChannelMerger.mergeOperations(List.of( + Map.entry(operationName, senderOperation1), + Map.entry(operationName, senderOperation2), + Map.entry(operationName, 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 - Object expectedMessages = MessageHelper.toMessageObjectOrComposition(Set.of(message1, message2)); - assertThat(mergedChannels).hasSize(1); - // .hasEntrySatisfying(channelName, it -> { - // assertThat(it.getPublish()) - // .isEqualTo(Operation.builder() - // .operationId("publisher1") - // .message(expectedMessages) - // .build()); - // assertThat(it.getSubscribe()).isNull(); - // }); + assertThat(mergedOperations).hasSize(1).hasEntrySatisfying(operationName, it -> { + assertThat(it.getMessages()).containsExactlyInAnyOrder(messageRef1, messageRef2); + }); } @Test @@ -157,6 +224,7 @@ void shouldUseOtherMessageIfFirstMessageIsMissing() { // given String channelName = "channel"; MessageObject message2 = MessageObject.builder() + .messageId("message2") .name(String.class.getCanonicalName()) .description("This is a string") .build(); @@ -166,7 +234,8 @@ void shouldUseOtherMessageIfFirstMessageIsMissing() { .build(); Operation publishOperation2 = Operation.builder() .action(OperationAction.SEND) - .title("publisher2") /*.message(message2)FIXME*/ + .title("publisher2") + .messages(List.of(MessageReference.fromMessage(message2))) .build(); ChannelObject publisherChannel1 = ChannelObject.builder() /*.publish(publishOperation1)FIXME*/.build(); @@ -174,11 +243,11 @@ void shouldUseOtherMessageIfFirstMessageIsMissing() { ChannelObject.builder() /*.publish(publishOperation2)FIXME*/.build(); // when - Map mergedChannels = ChannelMerger.merge( + Map mergedChannels = ChannelMerger.mergeChannels( Arrays.asList(Map.entry(channelName, publisherChannel1), Map.entry(channelName, publisherChannel2))); // then expectedMessage message2 - Object expectedMessages = MessageHelper.toMessageObjectOrComposition(Set.of(message2)); + var expectedMessages = MessageHelper.toMessagesMap(Set.of(message2)); assertThat(mergedChannels).hasSize(1).hasEntrySatisfying(channelName, it -> { // assertThat(it.getPublish()) FIXME // .isEqualTo(Operation.builder() diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScannerTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScannerTest.java index aa18c83db..f00ed12ef 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScannerTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/SimpleChannelsScannerTest.java @@ -3,6 +3,7 @@ import io.github.stavshamir.springwolf.asyncapi.scanners.classes.ClassScanner; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; import org.junit.jupiter.api.Test; import java.util.Map; @@ -25,28 +26,26 @@ class SimpleChannelsScannerTest { @Test void noClassFoundTest() { // when - Map channels = simpleChannelsScanner.scan(); + Map channels = simpleChannelsScanner.scanChannels(); + Map operations = simpleChannelsScanner.scanOperations(); // then assertThat(channels).isEmpty(); + assertThat(operations).isEmpty(); } @Test void processClassTest() { // given when(classScanner.scan()).thenReturn(Set.of(String.class)); - Map.Entry channel1 = Map.entry( - "channel1", - ChannelObject.builder() /*.publish(Operation.builder().build())FIXME*/ - .build()); - Map.Entry channel2 = Map.entry( - "channel2", - ChannelObject.builder() /*.subscribe(Operation.builder().build())FIXME*/ - .build()); - when(classProcessor.process(any())).thenReturn(Stream.of(channel1, channel2)); + Map.Entry channel1 = + Map.entry("channel1", ChannelObject.builder().build()); + Map.Entry channel2 = + Map.entry("channel2", ChannelObject.builder().build()); + when(classProcessor.processChannels(any())).thenReturn(Stream.of(channel1, channel2)); // when - Map channels = simpleChannelsScanner.scan(); + Map channels = simpleChannelsScanner.scanChannels(); // then assertThat(channels).containsExactly(channel1, channel2); @@ -56,41 +55,28 @@ void processClassTest() { void sameChannelsAreMergedTest() { // given when(classScanner.scan()).thenReturn(Set.of(String.class)); - Map.Entry channel1 = Map.entry( - "channel1", - ChannelObject.builder() - // .publish(Operation.builder().operationId("pub").build()) FIXME - .build()); - Map.Entry channel2 = Map.entry( - "channel1", - ChannelObject.builder() - // .subscribe(Operation.builder().operationId("sub").build()) FIXME - .build()); - when(classProcessor.process(any())).thenReturn(Stream.of(channel1, channel2)); + Map.Entry channel1 = + Map.entry("channel1", ChannelObject.builder().build()); + Map.Entry channel2 = + Map.entry("channel1", ChannelObject.builder().build()); + when(classProcessor.processChannels(any())).thenReturn(Stream.of(channel1, channel2)); // when - Map channels = simpleChannelsScanner.scan(); + Map channels = simpleChannelsScanner.scanChannels(); // then assertThat(channels) - .containsExactly(Map.entry( - "channel1", - ChannelObject.builder() - // - // .publish(Operation.builder().operationId("pub").build()) FIXME - // - // .subscribe(Operation.builder().operationId("sub").build()) FIXME - .build())); + .containsExactly(Map.entry("channel1", ChannelObject.builder().build())); } @Test void processEmptyClassTest() { // given when(classScanner.scan()).thenReturn(Set.of(String.class)); - when(classProcessor.process(any())).thenReturn(Stream.of()); + when(classProcessor.processChannels(any())).thenReturn(Stream.of()); // when - Map channels = simpleChannelsScanner.scan(); + Map channels = simpleChannelsScanner.scanChannels(); // then assertThat(channels).isEmpty(); 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 0416d0451..11a8a4a0e 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 @@ -15,9 +15,12 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ServerReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.info.Info; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; +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; @@ -121,7 +124,7 @@ private void setClassToScan(Class classToScan) { void scan_componentHasNoListenerMethods() { setClassToScan(ClassWithoutListenerAnnotation.class); - Map channels = channelScanner.scan(); + Map channels = channelScanner.scanChannels(); assertThat(channels).isEmpty(); } @@ -132,29 +135,35 @@ void scan_componentHasListenerMethod() { setClassToScan(ClassWithListenerAnnotation.class); // When scan is called - Map actualChannels = channelScanner.scan(); + Map actualChannels = channelScanner.scanChannels(); // Then the returned collection contains the channel + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) .description("SimpleFoo Message Description") - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) FIXME - // .schemaFormat(Message.DEFAULT_SCHEMA_FORMAT) - .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) + .payload(payload) // FIXME + // .schemaFormat(Message.DEFAULT_SCHEMA_FORMAT) + .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(EMPTY_MAP) .build(); Operation operation = Operation.builder() .description("Auto-generated description") - // .operationId("test-channel_publish") FIXME - // .bindings(EMPTY_MAP) - // .message(message) + // .operationId("test-channel_publish") FIXME + // .bindings(EMPTY_MAP) + // .message(message) .build(); ChannelObject expectedChannel = ChannelObject.builder() - .bindings(null) /*.publish(operation) FIXME*/ + .bindings(null) + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); @@ -165,7 +174,7 @@ void scan_componentHasListenerMethodWithUnknownServer() { // Given a class with method annotated with AsyncListener, with an unknown servername setClassToScan(ClassWithListenerAnnotationWithInvalidServer.class); - assertThatThrownBy(channelScanner::scan) + assertThatThrownBy(channelScanner::scanChannels) .isInstanceOf(IllegalArgumentException.class) .hasMessage( "Operation 'test-channel_publish' defines unknown server ref 'server3'. This AsyncApi defines these server(s): [server1, server2]"); @@ -177,15 +186,21 @@ void scan_componentHasListenerMethodWithAllAttributes() { setClassToScan(ClassWithListenerAnnotationWithAllAttributes.class); // When scan is called - Map actualChannels = channelScanner.scan(); + Map actualChannels = channelScanner.scanChannels(); // Then the returned collection contains the channel + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(String.class.getName()) .name(String.class.getName()) .title(String.class.getSimpleName()) .description(null) - // .schemaFormat(Message.DEFAULT_SCHEMA_FORMAT) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME + // FIXME + // .schemaFormat(Message.DEFAULT_SCHEMA_FORMAT) + .payload(payload) .headers(MessageHeaders.of(MessageReference.fromSchema("TestSchema"))) .bindings(EMPTY_MAP) .build(); @@ -194,15 +209,15 @@ void scan_componentHasListenerMethodWithAllAttributes() { .description("description") .title("test-channel_publish") .bindings(Map.of(TestOperationBindingProcessor.TYPE, TestOperationBindingProcessor.BINDING)) - // .message(message) FIXME + // .message(message) FIXME .build(); ChannelObject expectedChannel = ChannelObject.builder() .bindings(null) + .messages(Map.of(message.getMessageId(), message)) .servers(List.of( ServerReference.builder().ref("server1").build(), ServerReference.builder().ref("server2").build())) - // .publish(operation) FIXME .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); @@ -214,37 +229,47 @@ void scan_componentHasMultipleListenerAnnotations() { setClassToScan(ClassWithMultipleListenerAnnotations.class); // When scan is called - Map actualChannels = channelScanner.scan(); + Map actualChannels = channelScanner.scanChannels(); // Then the returned collection contains the channel - MessageObject.MessageObjectBuilder builder = MessageObject.builder() + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + + MessageObject message = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) FIXME - // .schemaFormat(Message.DEFAULT_SCHEMA_FORMAT) + .payload(payload) + // .schemaFormat(Message.DEFAULT_SCHEMA_FORMAT) // FIXME .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) - // FIXME - .bindings(EMPTY_MAP); + .bindings(EMPTY_MAP) + .description("SimpleFoo Message Description") + .build(); Operation operation1 = Operation.builder() .description("test-channel-1-description") .title("test-channel-1_publish") .bindings(EMPTY_MAP) - // .message(builder.description("SimpleFoo Message Description").build()) FIXME + // .message(builder.description("SimpleFoo Message Description").build()) FIXME .build(); - ChannelObject expectedChannel1 = - ChannelObject.builder().bindings(null) /*.publish(operation1)*/.build(); + ChannelObject expectedChannel1 = ChannelObject.builder() + .messages(Map.of(message.getMessageId(), message)) + .bindings(null) /*.publish(operation1)*/ + .build(); Operation operation2 = Operation.builder() .description("test-channel-2-description") .title("test-channel-2_publish") .bindings(EMPTY_MAP) - // .message(builder.description("SimpleFoo Message Description").build()) FIXME + // .message(builder.description("SimpleFoo Message Description").build()) FIXME .build(); - ChannelObject expectedChannel2 = - ChannelObject.builder().bindings(null) /*.publish(operation2)*/.build(); + ChannelObject expectedChannel2 = ChannelObject.builder() + .messages(Map.of(message.getMessageId(), message)) + .bindings(null) /*.publish(operation2)*/ + .build(); assertThat(actualChannels) .containsExactlyInAnyOrderEntriesOf(Map.of( @@ -258,18 +283,22 @@ void scan_componentHasAsyncMethodAnnotation() { setClassToScan(ClassWithMessageAnnotation.class); // When scan is called - Map actualChannels = channelScanner.scan(); + Map actualChannels = channelScanner.scanChannels(); // Then the returned collection contains the channel + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() .messageId("simpleFoo") .name("SimpleFooPayLoad") .title("Message Title") .description("Message description") - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) FIXME - // .schemaFormat("application/schema+json;version=draft-07") - .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) + .payload(payload) // FIXME + // .schemaFormat("application/schema+json;version=draft-07") + .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(EMPTY_MAP) .build(); @@ -277,11 +306,12 @@ void scan_componentHasAsyncMethodAnnotation() { .description("test channel operation description") .title("test-channel_publish") .bindings(EMPTY_MAP) - // .message(message) FIXME + // .message(message) FIXME .build(); ChannelObject expectedChannel = ChannelObject.builder() .bindings(null) /*.publish(operation) FIXME*/ + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); @@ -369,16 +399,16 @@ void scan_componentHasOnlyDeclaredMethods(Class clazz) { setClassToScan(clazz); // When scan is called - Map actualChannels = channelScanner.scan(); + Map actualChannels = channelScanner.scanChannels(); // Then the returned collection contains the channel with the actual method, excluding type erased methods MessageObject message = MessageObject.builder() + .messageId(String.class.getName()) .name(String.class.getName()) .title(String.class.getSimpleName()) .description(null) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME - // .schemaFormat("application/vnd.oai.openapi+json;version=3.0.0") - // + // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME + // .schemaFormat("application/vnd.oai.openapi+json;version=3.0.0") FIXME .headers( MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(EMPTY_MAP) @@ -388,11 +418,12 @@ void scan_componentHasOnlyDeclaredMethods(Class clazz) { .description("test channel operation description") .title("test-channel_publish") .bindings(EMPTY_MAP) - // .message(message) FIXME + // .message(message) FIXME .build(); ChannelObject expectedChannel = ChannelObject.builder() .bindings(null) /*.publish(operation) FIXME*/ + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); @@ -437,16 +468,21 @@ void scan_componentHasListenerMethodWithMetaAnnotation() { setClassToScan(ClassWithMetaAnnotation.class); // When scan is called - Map actualChannels = channelScanner.scan(); + Map actualChannels = channelScanner.scanChannels(); // Then the returned collection contains the channel + var messagePayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(String.class.getName()) .name(String.class.getName()) .title(String.class.getSimpleName()) .description(null) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME - // .schemaFormat("application/vnd.oai.openapi+json;version=3.0.0") - // + .payload(messagePayload) + // FIXME + // .schemaFormat("application/vnd.oai.openapi+json;version=3.0.0") .headers( MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(EMPTY_MAP) @@ -456,11 +492,12 @@ void scan_componentHasListenerMethodWithMetaAnnotation() { .description("test channel operation description") .title("test-channel_publish") .bindings(EMPTY_MAP) - // .message(message) FIXME + // .message(message) FIXME .build(); ChannelObject expectedChannel = ChannelObject.builder() .bindings(null) /*.publish(operation) FIXME*/ + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry("test-channel", expectedChannel)); diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerIntegrationTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerIntegrationTest.java index 1f118ded6..fcfcfb177 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerIntegrationTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerIntegrationTest.java @@ -3,7 +3,6 @@ import io.github.stavshamir.springwolf.asyncapi.scanners.bindings.BindingFactory; import io.github.stavshamir.springwolf.asyncapi.scanners.channels.payload.PayloadClassExtractor; -import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeaders; import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeadersNotDocumented; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.ChannelBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.MessageBinding; @@ -11,8 +10,10 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; 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.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties; import io.github.stavshamir.springwolf.schemas.DefaultSchemasService; import io.github.stavshamir.springwolf.schemas.SchemasService; @@ -77,7 +78,7 @@ class NoClassListener { void scan_componentHasNoClassLevelRabbitListenerAnnotation() { // when List> channels = - scanner.process(ClassWithoutClassListener.class).toList(); + scanner.processChannels(ClassWithoutClassListener.class).toList(); // then assertThat(channels).isEmpty(); @@ -96,7 +97,7 @@ class NoMethodListener { void scan_componentHasNoClassLevelRabbitListenerAnnotation() { // when List> channels = - scanner.process(ClassWithoutMethodListener.class).toList(); + scanner.processChannels(ClassWithoutMethodListener.class).toList(); // then assertThat(channels).isEmpty(); @@ -114,32 +115,28 @@ class OneMethodLevelAnnotation { @Test void scan_componentWithOneMethodLevelAnnotation() { // when - List> actualChannels = - scanner.process(ClassWithOneMethodLevelHandler.class).toList(); + List> actualChannels = scanner.processChannels( + ClassWithOneMethodLevelHandler.class) + .toList(); // then + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) - // FIXME - // - .headers( - MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) - // FIXME + .payload(payload) + .headers(MessageHeaders.of( + MessageReference.fromSchema(AsyncHeadersNotDocumented.NOT_DOCUMENTED.getSchemaName()))) .bindings(TestBindingFactory.defaultMessageBinding) .build(); - Operation operation = Operation.builder() - .description("Auto-generated description") - .title("test-channel_publish_ClassWithOneMethodLevelHandler") - .bindings(TestBindingFactory.defaultOperationBinding) - // .message(message) FIXME - .build(); - ChannelObject expectedChannel = ChannelObject.builder() .bindings(TestBindingFactory.defaultChannelBinding) - // .publish(operation) FIXME + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry(TestBindingFactory.CHANNEL, expectedChannel)); @@ -161,43 +158,40 @@ class MultipleMethodLevelAnnotations { @Test void scan_componentWithMultipleRabbitHandlerMethods() { // when - List> actualChannels = - scanner.process(ClassWithMultipleMethodLevelHandlers.class).toList(); + List> actualChannels = scanner.processChannels( + ClassWithMultipleMethodLevelHandlers.class) + .toList(); // Then the returned collection contains the channel with message set to oneOf + MessagePayload simpleFooPayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessageObject fooMessage = MessageObject.builder() .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) - // FIXME - // - .headers( - MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) - // FIXME + .payload(simpleFooPayload) + .headers(MessageHeaders.of( + MessageReference.fromSchema(AsyncHeadersNotDocumented.NOT_DOCUMENTED.getSchemaName()))) .bindings(TestBindingFactory.defaultMessageBinding) .build(); + MessagePayload stringPayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + MessageObject barMessage = MessageObject.builder() .name(String.class.getName()) .title(String.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME - // - .headers( - MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) + .payload(stringPayload) + .headers(MessageHeaders.of( + MessageReference.fromSchema(AsyncHeadersNotDocumented.NOT_DOCUMENTED.getSchemaName()))) .bindings(TestBindingFactory.defaultMessageBinding) .build(); - Operation operation = Operation.builder() - .description("Auto-generated description") - // .operationId("test-channel_publish_ClassWithMultipleMethodLevelHandlers") - // FIXME - .bindings(TestBindingFactory.defaultOperationBinding) - // .message(toMessageObjectOrComposition(Set.of(fooMessage, barMessage))) FIXME - .build(); - ChannelObject expectedChannel = ChannelObject.builder() .bindings(TestBindingFactory.defaultChannelBinding) - // .publish(operation) FIXME + .messages(Map.of(fooMessage.getMessageId(), fooMessage, barMessage.getMessageId(), barMessage)) .build(); assertThat(actualChannels).containsExactly(Map.entry(TestBindingFactory.CHANNEL, expectedChannel)); @@ -248,12 +242,12 @@ public String getChannelName(TestClassListener annotation) { @Override public Map buildChannelBinding(TestClassListener annotation) { - return (Map) defaultChannelBinding; + return defaultChannelBinding; } @Override public Map buildOperationBinding(TestClassListener annotation) { - return (Map) defaultOperationBinding; + return defaultOperationBinding; } @Override diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerTest.java index eb72fb4b0..445500d7b 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/ClassLevelAnnotationChannelsScannerTest.java @@ -12,10 +12,10 @@ import io.github.stavshamir.springwolf.asyncapi.v3.bindings.amqp.AMQPMessageBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.amqp.AMQPOperationBinding; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; -import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; -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.channel.message.MessagePayload; +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.schemas.SchemasService; import lombok.Data; import lombok.NoArgsConstructor; @@ -79,27 +79,26 @@ void setUp() { void scan_componentHasTestListenerMethods() { // when List> channels = - scanner.process(ClassWithTestListenerAnnotation.class).collect(Collectors.toList()); + scanner.processChannels(ClassWithTestListenerAnnotation.class).collect(Collectors.toList()); // then + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(String.class.getName()) .name(String.class.getName()) .title(String.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME - .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) + .payload(payload) + // FIXME + // .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(defaultMessageBinding) .build(); - Operation operation = Operation.builder() - .description("Auto-generated description") - .title(CHANNEL + "_publish_ClassWithTestListenerAnnotation") - .bindings(defaultOperationBinding) - // .message(message) FIXME - .build(); - ChannelObject expectedChannelItem = ChannelObject.builder() .bindings(defaultChannelBinding) - // .publish(operation) FIXME + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(channels).containsExactly(Map.entry(CHANNEL, expectedChannelItem)); diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerIntegrationTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerIntegrationTest.java index 48696efa6..2758225a6 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerIntegrationTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerIntegrationTest.java @@ -10,8 +10,10 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; 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.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.configuration.properties.SpringwolfConfigProperties; import io.github.stavshamir.springwolf.schemas.DefaultSchemasService; import io.github.stavshamir.springwolf.schemas.SchemasService; @@ -37,7 +39,6 @@ import static io.github.stavshamir.springwolf.asyncapi.scanners.channels.annotation.MethodLevelAnnotationChannelsScannerIntegrationTest.TestBindingFactory.defaultChannelBinding; import static io.github.stavshamir.springwolf.asyncapi.scanners.channels.annotation.MethodLevelAnnotationChannelsScannerIntegrationTest.TestBindingFactory.defaultMessageBinding; -import static io.github.stavshamir.springwolf.asyncapi.scanners.channels.annotation.MethodLevelAnnotationChannelsScannerIntegrationTest.TestBindingFactory.defaultOperationBinding; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(SpringExtension.class) @@ -72,8 +73,9 @@ class NoListener { @Test void scan_componentHasNoListenerMethods() { // when - List> channels = - scanner.process(ClassWithoutListenerAnnotation.class).toList(); + List> channels = scanner.processChannels( + ClassWithoutListenerAnnotation.class) + .toList(); // then assertThat(channels).isEmpty(); @@ -90,30 +92,26 @@ class WithListener { void scan_componentHasListenerMethod() { // when List> actualChannels = - scanner.process(ClassWithListenerAnnotation.class).toList(); + scanner.processChannels(ClassWithListenerAnnotation.class).toList(); // then + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) - // FIXME - // + .payload(payload) .headers( MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(TestBindingFactory.defaultMessageBinding) .build(); - Operation operation = Operation.builder() - .description("Auto-generated description") - .title("test-channel_publish_methodWithAnnotation") - .bindings(TestBindingFactory.defaultOperationBinding) - // .message(message) FIXME - .build(); - ChannelObject expectedChannel = ChannelObject.builder() .bindings(defaultChannelBinding) - // .publish(operation) FIXME + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry(TestBindingFactory.CHANNEL, expectedChannel)); @@ -133,51 +131,45 @@ class OneChannelTwoPayloads { @Test void scan_componentHasTestListenerMethods_multiplePayloads() { // when - List> channels = scanner.process( + List> channels = scanner.processChannels( ClassWithTestListenerAnnotationMultiplePayloads.class) .toList(); // then + MessagePayload simpleFooPayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessagePayload stringPayload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + MessageObject messageSimpleFoo = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) - // FIXME - // + .payload(simpleFooPayload) .headers( MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(TestBindingFactory.defaultMessageBinding) .build(); MessageObject messageString = MessageObject.builder() + .messageId(String.class.getName()) .name(String.class.getName()) .title(String.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME - // + .payload(stringPayload) .headers( MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(TestBindingFactory.defaultMessageBinding) .build(); ChannelObject expectedChannelItem = ChannelObject.builder() + .messages(Map.of(messageSimpleFoo.getMessageId(), messageSimpleFoo)) .bindings(defaultChannelBinding) - // .publish(Operation.builder() FIXME - // .description("Auto-generated description") - // .operationId(TestBindingFactory.CHANNEL + - // "_publish_methodWithAnnotation") - // .bindings(TestBindingFactory.defaultOperationBinding) - // .message(messageSimpleFoo) - // .build()) .build(); ChannelObject expectedChannelItem2 = ChannelObject.builder() .bindings(defaultChannelBinding) - // .publish(Operation.builder() FIXME - // .description("Auto-generated description") - // .operationId(TestBindingFactory.CHANNEL + - // "_publish_methodWithAnnotation") - // .bindings(TestBindingFactory.defaultOperationBinding) - // .message(messageString) - // .build()) + .messages(Map.of(messageString.getMessageId(), messageSimpleFoo)) .build(); assertThat(channels) @@ -201,31 +193,28 @@ class MetaAnnotation { @Test void scan_componentHasListenerMetaMethod() { // when - List> actualChannels = - scanner.process(ClassWithListenerMetaAnnotation.class).toList(); + List> actualChannels = scanner.processChannels( + ClassWithListenerMetaAnnotation.class) + .toList(); // then + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(SimpleFoo.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) .name(SimpleFoo.class.getName()) .title(SimpleFoo.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(SimpleFoo.class.getSimpleName())) - // FIXME - // + .payload(payload) .headers( MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) .bindings(defaultMessageBinding) .build(); - Operation operation = Operation.builder() - .description("Auto-generated description") - .title("test-channel_publish_methodWithAnnotation") - .bindings(defaultOperationBinding) - // .message(message) FIXME - .build(); - ChannelObject expectedChannel = ChannelObject.builder() .bindings(defaultChannelBinding) - // .publish(operation) FIXME + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(actualChannels).containsExactly(Map.entry(TestBindingFactory.CHANNEL, expectedChannel)); @@ -275,12 +264,12 @@ public String getChannelName(TestChannelListener annotation) { @Override public Map buildChannelBinding(TestChannelListener annotation) { - return (Map) defaultChannelBinding; + return defaultChannelBinding; } @Override public Map buildOperationBinding(TestChannelListener annotation) { - return (Map) defaultOperationBinding; + return defaultOperationBinding; } @Override diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerTest.java index ee8e19437..5d2af5b30 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/MethodLevelAnnotationChannelsScannerTest.java @@ -4,6 +4,7 @@ import io.github.stavshamir.springwolf.asyncapi.scanners.bindings.BindingFactory; import io.github.stavshamir.springwolf.asyncapi.scanners.channels.payload.PayloadClassExtractor; import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeaders; +import io.github.stavshamir.springwolf.asyncapi.types.channel.operation.message.header.AsyncHeadersNotDocumented; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.ChannelBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.MessageBinding; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.OperationBinding; @@ -13,8 +14,10 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageHeaders; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; 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.schema.MultiFormatSchema; +import io.github.stavshamir.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.stavshamir.springwolf.schemas.SchemasService; import lombok.Data; import lombok.NoArgsConstructor; @@ -51,7 +54,7 @@ class MethodLevelAnnotationChannelsScannerTest { Map.of("protocol", new AMQPChannelBinding()); @BeforeEach - void setUp() { + void setUp() throws NoSuchMethodException { // when when(bindingFactory.getChannelName(any())).thenReturn(CHANNEL); @@ -66,33 +69,39 @@ void setUp() { doAnswer(invocation -> AsyncHeaders.NOT_DOCUMENTED.getSchemaName()) .when(schemasService) .register(any(AsyncHeaders.class)); + + var stringMethod = + ClassWithMultipleTestListenerAnnotation.class.getDeclaredMethod("methodWithAnnotation", String.class); + doReturn(String.class).when(payloadClassExtractor).extractFrom(stringMethod); + var simpleFooMethod = ClassWithMultipleTestListenerAnnotation.class.getDeclaredMethod( + "anotherMethodWithAnnotation", SimpleFoo.class); + doReturn(SimpleFoo.class).when(payloadClassExtractor).extractFrom(simpleFooMethod); } @Test void scan_componentHasTestListenerMethods() { // when List> channels = - scanner.process(ClassWithTestListenerAnnotation.class).collect(Collectors.toList()); + scanner.processChannels(ClassWithTestListenerAnnotation.class).collect(Collectors.toList()); // then + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + MessageObject message = MessageObject.builder() + .messageId(String.class.getName()) .name(String.class.getName()) .title(String.class.getSimpleName()) - // .payload(PayloadReference.fromModelName(String.class.getSimpleName())) FIXME - .headers(MessageHeaders.of(MessageReference.fromSchema(AsyncHeaders.NOT_DOCUMENTED.getSchemaName()))) + .payload(payload) + .headers(MessageHeaders.of( + MessageReference.fromSchema(AsyncHeadersNotDocumented.NOT_DOCUMENTED.getSchemaName()))) .bindings(defaultMessageBinding) .build(); - Operation operation = Operation.builder() - .description("Auto-generated description") - .title(CHANNEL + "_publish_methodWithAnnotation") - .bindings(defaultOperationBinding) - // .message(message) FIXME - .build(); - ChannelObject expectedChannelItem = ChannelObject.builder() .bindings(defaultChannelBinding) - // .publish(operation) FIXME + .messages(Map.of(message.getMessageId(), message)) .build(); assertThat(channels).containsExactly(Map.entry(CHANNEL, expectedChannelItem)); @@ -106,6 +115,56 @@ private void methodWithAnnotation(String payload) {} private void methodWithoutAnnotation() {} } + @Test + void scan_componentHasMultipleTestListenerMethods() { + // when + List> channels = scanner.processChannels( + ClassWithMultipleTestListenerAnnotation.class) + .toList(); + + // then + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() + .schema(SchemaReference.fromSchema(String.class.getSimpleName())) + .build()); + + MessageObject stringMessage = MessageObject.builder() + .messageId(String.class.getName()) + .name(String.class.getName()) + .title(String.class.getSimpleName()) + .payload(payload) + .headers(MessageHeaders.of( + MessageReference.fromSchema(AsyncHeadersNotDocumented.NOT_DOCUMENTED.getSchemaName()))) + .bindings(defaultMessageBinding) + .build(); + + MessageObject simpleFooMessage = MessageObject.builder() + .messageId(SimpleFoo.class.getName()) + .name(SimpleFoo.class.getName()) + .title(SimpleFoo.class.getSimpleName()) + .payload(payload) + .headers(MessageHeaders.of( + MessageReference.fromSchema(AsyncHeadersNotDocumented.NOT_DOCUMENTED.getSchemaName()))) + .bindings(defaultMessageBinding) + .build(); + + ChannelObject expectedChannelItem = ChannelObject.builder() + .bindings(defaultChannelBinding) + .messages(Map.of( + stringMessage.getMessageId(), stringMessage, simpleFooMessage.getMessageId(), simpleFooMessage)) + .build(); + + assertThat(channels).containsExactly(Map.entry(CHANNEL, expectedChannelItem)); + } + + private static class ClassWithMultipleTestListenerAnnotation { + + @TestListener + private void methodWithAnnotation(String payload) {} + + @TestListener + private void anotherMethodWithAnnotation(SimpleFoo payload) {} + } + @Data @NoArgsConstructor private static class SimpleFoo { diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfConfigPropertiesIntegrationTest.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfConfigPropertiesIntegrationTest.java index 09fe9bf2d..864ef570a 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfConfigPropertiesIntegrationTest.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfConfigPropertiesIntegrationTest.java @@ -77,7 +77,7 @@ void docketServersTest() { "springwolf.docket.info.extension-fields.x-api-name=api-name", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", }) static class PayloadWithoutCustomizingIntegrationTest { @@ -109,7 +109,7 @@ void payloadTest() { "springwolf.docket.info.extension-fields.x-api-name=api-name", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.payload.extractable-classes.my.custom.class=1" }) static class PayloadWithCustomizingIntegrationTest { @@ -145,7 +145,7 @@ void payloadCustomizedTest() { "springwolf.docket.info.extension-fields.x-api-name=api-name", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.payload.extractable-classes.java.util.List=-1" }) static class PayloadDisabledIntegrationTest { diff --git a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/fixtures/MinimalIntegrationTestContextConfiguration.java b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/fixtures/MinimalIntegrationTestContextConfiguration.java index 644707e72..8233f2534 100644 --- a/springwolf-core/src/test/java/io/github/stavshamir/springwolf/fixtures/MinimalIntegrationTestContextConfiguration.java +++ b/springwolf-core/src/test/java/io/github/stavshamir/springwolf/fixtures/MinimalIntegrationTestContextConfiguration.java @@ -22,6 +22,6 @@ "springwolf.docket.default-content-type=application/yaml", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", }) public @interface MinimalIntegrationTestContextConfiguration {} diff --git a/springwolf-examples/springwolf-amqp-example/src/main/resources/application.properties b/springwolf-examples/springwolf-amqp-example/src/main/resources/application.properties index 3ec9d7ed0..adf64fc4f 100644 --- a/springwolf-examples/springwolf-amqp-example/src/main/resources/application.properties +++ b/springwolf-examples/springwolf-amqp-example/src/main/resources/application.properties @@ -28,7 +28,7 @@ springwolf.docket.info.contact.extension-fields.x-phone=+49 123 456789 springwolf.docket.info.license.name=Apache License 2.0 springwolf.docket.info.license.extension-fields.x-desc=some description springwolf.docket.servers.amqp.protocol=amqp -springwolf.docket.servers.amqp.url=${spring.rabbitmq.host}:${spring.rabbitmq.port} +springwolf.docket.servers.amqp.host=${spring.rabbitmq.host}:${spring.rabbitmq.port} springwolf.use-fqn=true springwolf.plugin.amqp.publishing.enabled=true diff --git a/springwolf-examples/springwolf-amqp-example/src/test/java/io/github/stavshamir/springwolf/example/amqp/SpringContextIntegrationTest.java b/springwolf-examples/springwolf-amqp-example/src/test/java/io/github/stavshamir/springwolf/example/amqp/SpringContextIntegrationTest.java index 7eb8e0ddd..a76b53f04 100644 --- a/springwolf-examples/springwolf-amqp-example/src/test/java/io/github/stavshamir/springwolf/example/amqp/SpringContextIntegrationTest.java +++ b/springwolf-examples/springwolf-amqp-example/src/test/java/io/github/stavshamir/springwolf/example/amqp/SpringContextIntegrationTest.java @@ -23,7 +23,7 @@ public class SpringContextIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=amqp", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", }) class ApplicationPropertiesConfigurationTest { 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 c81a36f84..0642b0534 100644 --- a/springwolf-examples/springwolf-amqp-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-amqp-example/src/test/resources/asyncapi.json @@ -26,20 +26,19 @@ }, "channels": { "another-queue": { - "address": "another-queue", "messages": { "another-queue_publish_receiveAnotherPayload.message": { - "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, "payload": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", "schema": { "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto" } }, - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, + "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", "bindings": { "amqp": { "bindingVersion": "0.3.0" @@ -69,21 +68,20 @@ } }, "example-producer-channel-publisher": { - "address": "example-producer-channel-publisher", "messages": { "example-producer-channel-publisher_subscribe.message": { - "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", - "description": "Another payload model", + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, "payload": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", "schema": { "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto" } }, - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, + "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", + "description": "Another payload model", "bindings": { "amqp": { "bindingVersion": "0.3.0" @@ -93,20 +91,19 @@ } }, "example-queue": { - "address": "example-queue", "messages": { "example-queue_publish_receiveExamplePayload.message": { - "name": "io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto", - "title": "ExamplePayloadDto", + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, "payload": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", "schema": { "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto" } }, - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, + "name": "io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto", + "title": "ExamplePayloadDto", "bindings": { "amqp": { "bindingVersion": "0.3.0" @@ -136,20 +133,19 @@ } }, "example-topic-routing-key": { - "address": "example-topic-routing-key", "messages": { "example-topic-routing-key_publish_bindingsExample.message": { - "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, "payload": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", "schema": { "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto" } }, - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, + "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", "bindings": { "amqp": { "bindingVersion": "0.3.0" @@ -179,20 +175,19 @@ } }, "multi-payload-queue": { - "address": "multi-payload-queue", "messages": { "multi-payload-queue_publish_bindingsBeanExample.message.0": { - "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, "payload": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", "schema": { "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto" } }, - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, + "name": "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", "bindings": { "amqp": { "bindingVersion": "0.3.0" @@ -200,17 +195,17 @@ } }, "multi-payload-queue_publish_bindingsBeanExample.message.1": { - "name": "io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto", - "title": "ExamplePayloadDto", + "headers": { + "$ref": "#/components/schemas/HeadersNotDocumented" + }, "payload": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", "schema": { "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto" } }, - "headers": { - "$ref": "#/components/schemas/HeadersNotDocumented" - }, + "name": "io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto", + "title": "ExamplePayloadDto", "bindings": { "amqp": { "bindingVersion": "0.3.0" @@ -240,6 +235,76 @@ } } }, + "components": { + "schemas": { + "HeadersNotDocumented": { + "type": "object", + "properties": { }, + "example": { } + }, + "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto": { + "required": [ + "example" + ], + "type": "object", + "properties": { + "example": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto" + }, + "foo": { + "type": "string", + "description": "Foo field", + "example": "bar" + } + }, + "description": "Another payload model", + "example": { + "example": { + "someEnum": "FOO2", + "someLong": 5, + "someString": "some string value" + }, + "foo": "bar" + } + }, + "io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto": { + "required": [ + "someEnum", + "someString" + ], + "type": "object", + "properties": { + "someEnum": { + "type": "string", + "description": "Some enum field", + "example": "FOO2", + "enum": [ + "FOO1", + "FOO2", + "FOO3" + ] + }, + "someLong": { + "type": "integer", + "description": "Some long field", + "format": "int64", + "example": 5 + }, + "someString": { + "type": "string", + "description": "Some string field", + "example": "some string value" + } + }, + "description": "Example payload model", + "example": { + "someEnum": "FOO2", + "someLong": 5, + "someString": "some string value" + } + } + } + }, "operations": { "another-queue_publish_receiveAnotherPayload": { "action": "receive", @@ -272,7 +337,7 @@ "expiration": 0, "cc": [], "priority": 0, - "deliveryMode": 0, + "deliveryMode": 1, "mandatory": false, "timestamp": false, "ack": false, @@ -348,75 +413,5 @@ } ] } - }, - "components": { - "schemas": { - "HeadersNotDocumented": { - "type": "object", - "properties": {}, - "example": {} - }, - "io.github.stavshamir.springwolf.example.amqp.dtos.AnotherPayloadDto": { - "required": [ - "example" - ], - "type": "object", - "properties": { - "example": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto" - }, - "foo": { - "type": "string", - "description": "Foo field", - "example": "bar" - } - }, - "description": "Another payload model", - "example": { - "example": { - "someEnum": "FOO2", - "someLong": 5, - "someString": "some string value" - }, - "foo": "bar" - } - }, - "io.github.stavshamir.springwolf.example.amqp.dtos.ExamplePayloadDto": { - "required": [ - "someEnum", - "someString" - ], - "type": "object", - "properties": { - "someEnum": { - "type": "string", - "description": "Some enum field", - "example": "FOO2", - "enum": [ - "FOO1", - "FOO2", - "FOO3" - ] - }, - "someLong": { - "type": "integer", - "description": "Some long field", - "format": "int64", - "example": 5 - }, - "someString": { - "type": "string", - "description": "Some string field", - "example": "some string value" - } - }, - "description": "Example payload model", - "example": { - "someEnum": "FOO2", - "someLong": 5, - "someString": "some string value" - } - } - } } } \ No newline at end of file diff --git a/springwolf-examples/springwolf-cloud-stream-example/src/main/resources/application.properties b/springwolf-examples/springwolf-cloud-stream-example/src/main/resources/application.properties index eeb1f621c..539256f3e 100644 --- a/springwolf-examples/springwolf-cloud-stream-example/src/main/resources/application.properties +++ b/springwolf-examples/springwolf-cloud-stream-example/src/main/resources/application.properties @@ -25,7 +25,7 @@ springwolf.docket.info.contact.email=example@example.com springwolf.docket.info.contact.url=https://github.com/springwolf/springwolf-core springwolf.docket.info.license.name=Apache License 2.0 springwolf.docket.servers.kafka.protocol=kafka -springwolf.docket.servers.kafka.url=${spring.kafka.bootstrap-servers} +springwolf.docket.servers.kafka.host=${spring.kafka.bootstrap-servers} # For debugging purposes diff --git a/springwolf-examples/springwolf-cloud-stream-example/src/test/java/io/github/stavshamir/springwolf/example/cloudstream/SpringContextIntegrationTest.java b/springwolf-examples/springwolf-cloud-stream-example/src/test/java/io/github/stavshamir/springwolf/example/cloudstream/SpringContextIntegrationTest.java index c15dd9716..1d505eddb 100644 --- a/springwolf-examples/springwolf-cloud-stream-example/src/test/java/io/github/stavshamir/springwolf/example/cloudstream/SpringContextIntegrationTest.java +++ b/springwolf-examples/springwolf-cloud-stream-example/src/test/java/io/github/stavshamir/springwolf/example/cloudstream/SpringContextIntegrationTest.java @@ -29,7 +29,7 @@ public class SpringContextIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=kafka", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", }) class ApplicationPropertiesConfigurationTest { 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 f498ea243..d53ebacf5 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 @@ -1,5 +1,5 @@ { - "asyncapi": "2.6.0", + "asyncapi": "3.0.0", "info": { "title": "Springwolf example project - Cloud Stream", "version": "1.0.0", @@ -12,90 +12,129 @@ "license": { "name": "Apache License 2.0" }, + "tags": [], "x-generator": "springwolf" }, "defaultContentType": "application/json", "servers": { "kafka": { - "url": "kafka:29092", + "host": "kafka:29092", "protocol": "kafka" } }, "channels": { "another-topic": { - "subscribe": { - "operationId": "another-topic_subscribe_process", - "description": "Auto-generated description", - "bindings": { - "kafka": { } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "another-topic", + "messages": { + "another-topic_publish_consumerMethod.message": { "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", "payload": { - "$ref": "#/components/schemas/AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "kafka": { } + "kafka": {} } - } - }, - "publish": { - "operationId": "another-topic_publish_consumerMethod", - "description": "Auto-generated description", - "bindings": { - "kafka": { } }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "another-topic_subscribe_process.message": { "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", "payload": { - "$ref": "#/components/schemas/AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "kafka": { } + "kafka": {} } } }, "bindings": { - "kafka": { } + "kafka": {} } }, "example-topic": { - "publish": { - "operationId": "example-topic_publish_process", - "description": "Auto-generated description", - "bindings": { - "kafka": { } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "example-topic", + "messages": { + "example-topic_publish_process.message": { "name": "io.github.stavshamir.springwolf.example.cloudstream.dtos.ExamplePayloadDto", "title": "ExamplePayloadDto", "payload": { - "$ref": "#/components/schemas/ExamplePayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/ExamplePayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "kafka": { } + "kafka": {} } } }, "bindings": { - "kafka": { } + "kafka": {} } } }, + "operations": { + "another-topic_publish_consumerMethod": { + "action": "receive", + "channel": { + "$ref": "#/channels/another-topic" + }, + "description": "Auto-generated description", + "bindings": { + "kafka": {} + }, + "messages": [ + { + "$ref": "#/channels/another-topic/messages/another-topic_publish_consumerMethod.message" + } + ] + }, + "another-topic_subscribe_process": { + "action": "send", + "channel": { + "$ref": "#/channels/another-topic" + }, + "description": "Auto-generated description", + "bindings": { + "kafka": {} + }, + "messages": [ + { + "$ref": "#/channels/another-topic/messages/another-topic_subscribe_process.message" + } + ] + }, + "example-topic_publish_process": { + "action": "receive", + "channel": { + "$ref": "#/channels/example-topic" + }, + "description": "Auto-generated description", + "bindings": { + "kafka": {} + }, + "messages": [ + { + "$ref": "#/channels/example-topic/messages/example-topic_publish_process.message" + } + ] + } + }, "components": { "schemas": { "AnotherPayloadDto": { @@ -161,10 +200,9 @@ }, "HeadersNotDocumented": { "type": "object", - "properties": { }, - "example": { } + "properties": {}, + "example": {} } } - }, - "tags": [ ] + } } \ No newline at end of file diff --git a/springwolf-examples/springwolf-jms-example/src/main/resources/application.properties b/springwolf-examples/springwolf-jms-example/src/main/resources/application.properties index e4675a685..ee4fe48b8 100644 --- a/springwolf-examples/springwolf-jms-example/src/main/resources/application.properties +++ b/springwolf-examples/springwolf-jms-example/src/main/resources/application.properties @@ -23,7 +23,7 @@ springwolf.docket.info.contact.email=example@example.com springwolf.docket.info.contact.url=https://github.com/springwolf/springwolf-core springwolf.docket.info.license.name=Apache License 2.0 springwolf.docket.servers.jms.protocol=jms -springwolf.docket.servers.jms.url=${spring.artemis.broker-url} +springwolf.docket.servers.jms.host=${spring.artemis.broker-url} springwolf.use-fqn=true springwolf.plugin.jms.publishing.enabled=true 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 f1368e997..78cbb5266 100644 --- a/springwolf-examples/springwolf-jms-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-jms-example/src/test/resources/asyncapi.json @@ -1,5 +1,5 @@ { - "asyncapi": "2.6.0", + "asyncapi": "3.0.0", "info": { "title": "Springwolf example project - JMS", "version": "1.0.0", @@ -12,99 +12,138 @@ "license": { "name": "Apache License 2.0" }, + "tags": [], "x-generator": "springwolf" }, "defaultContentType": "application/json", "servers": { "jms": { - "url": "tcp://activemq:61616", + "host": "activemq:61616", "protocol": "jms" } }, "channels": { "another-queue": { - "subscribe": { - "operationId": "another-queue_subscribe", - "description": "Custom, optional description defined in the AsyncPublisher annotation", - "bindings": { - "jms": { - "internal-field": "customValue", - "nested": { - "key": "nestedValue" - } - } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "another-queue", + "messages": { + "another-queue_publish_receiveAnotherPayload.message": { "name": "io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", - "description": "Another payload model", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "jms": { } + "jms": {} } - } - }, - "publish": { - "operationId": "another-queue_publish_receiveAnotherPayload", - "description": "Auto-generated description", - "bindings": { - "jms": { } }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "another-queue_subscribe.message": { "name": "io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", + "description": "Another payload model", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "jms": { } + "jms": {} } } } }, "example-queue": { - "publish": { - "operationId": "example-queue_publish_receiveExamplePayload", - "description": "Auto-generated description", - "bindings": { - "jms": { } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "example-queue", + "messages": { + "example-queue_publish_receiveExamplePayload.message": { "name": "io.github.stavshamir.springwolf.example.jms.dtos.ExamplePayloadDto", "title": "ExamplePayloadDto", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.jms.dtos.ExamplePayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.jms.dtos.ExamplePayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "jms": { } + "jms": {} } } }, "bindings": { - "jms": { } + "jms": {} } } }, + "operations": { + "another-queue_publish_receiveAnotherPayload": { + "action": "receive", + "channel": { + "$ref": "#/channels/another-queue" + }, + "description": "Auto-generated description", + "bindings": { + "jms": {} + }, + "messages": [ + { + "$ref": "#/channels/another-queue/messages/another-queue_publish_receiveAnotherPayload.message" + } + ] + }, + "another-queue_subscribe": { + "action": "send", + "channel": { + "$ref": "#/channels/another-queue" + }, + "description": "Custom, optional description defined in the AsyncPublisher annotation", + "bindings": { + "jms": { + "internal-field": "customValue", + "nested": { + "key": "nestedValue" + } + } + }, + "messages": [ + { + "$ref": "#/channels/another-queue/messages/another-queue_subscribe.message" + } + ] + }, + "example-queue_publish_receiveExamplePayload": { + "action": "receive", + "channel": { + "$ref": "#/channels/example-queue" + }, + "description": "Auto-generated description", + "bindings": { + "jms": {} + }, + "messages": [ + { + "$ref": "#/channels/example-queue/messages/example-queue_publish_receiveExamplePayload.message" + } + ] + } + }, "components": { "schemas": { "HeadersNotDocumented": { "type": "object", - "properties": { }, - "example": { } + "properties": {}, + "example": {} }, "io.github.stavshamir.springwolf.example.jms.dtos.AnotherPayloadDto": { "required": [ @@ -168,6 +207,5 @@ } } } - }, - "tags": [ ] + } } \ No newline at end of file diff --git a/springwolf-examples/springwolf-kafka-example/src/main/resources/application.properties b/springwolf-examples/springwolf-kafka-example/src/main/resources/application.properties index d69e67c8d..f22d024d8 100644 --- a/springwolf-examples/springwolf-kafka-example/src/main/resources/application.properties +++ b/springwolf-examples/springwolf-kafka-example/src/main/resources/application.properties @@ -41,7 +41,7 @@ springwolf.use-fqn=true # Springwolf kafka configuration springwolf.docket.servers.kafka.protocol=kafka -springwolf.docket.servers.kafka.url=${spring.kafka.bootstrap-servers} +springwolf.docket.servers.kafka.host=${spring.kafka.bootstrap-servers} springwolf.plugin.kafka.publishing.enabled=true springwolf.plugin.kafka.publishing.producer.bootstrap-servers=${BOOTSTRAP_SERVER_SASL:localhost:9093} springwolf.plugin.kafka.publishing.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer diff --git a/springwolf-examples/springwolf-kafka-example/src/test/java/io/github/stavshamir/springwolf/example/kafka/SpringContextIntegrationTest.java b/springwolf-examples/springwolf-kafka-example/src/test/java/io/github/stavshamir/springwolf/example/kafka/SpringContextIntegrationTest.java index 795b2f6e0..4d1cbbef8 100644 --- a/springwolf-examples/springwolf-kafka-example/src/test/java/io/github/stavshamir/springwolf/example/kafka/SpringContextIntegrationTest.java +++ b/springwolf-examples/springwolf-kafka-example/src/test/java/io/github/stavshamir/springwolf/example/kafka/SpringContextIntegrationTest.java @@ -29,7 +29,7 @@ public class SpringContextIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=kafka", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", }) class ApplicationPropertiesConfigurationTest { 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 0a11de879..ba5f55984 100644 --- a/springwolf-examples/springwolf-kafka-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-kafka-example/src/test/resources/asyncapi.json @@ -1,5 +1,5 @@ { - "asyncapi": "2.6.0", + "asyncapi": "3.0.0", "info": { "title": "Springwolf example project - Kafka", "version": "1.0.0", @@ -12,37 +12,28 @@ "license": { "name": "Apache License 2.0" }, + "tags": [], "x-generator": "springwolf" }, "defaultContentType": "application/json", "servers": { "kafka": { - "url": "kafka:29092", + "host": "kafka:29092", "protocol": "kafka" } }, "channels": { "another-topic": { - "publish": { - "operationId": "another-topic_publish_receiveAnotherPayloadBatched", - "description": "Auto-generated description", - "bindings": { - "kafka": { - "groupId": { - "type": "string", - "enum": [ - "example-group-id" - ] - }, - "bindingVersion": "0.4.0" - } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "another-topic", + "messages": { + "another-topic_publish_receiveAnotherPayloadBatched.message": { "name": "io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" @@ -88,20 +79,16 @@ } }, "example-topic": { - "publish": { - "operationId": "example-topic_publish_receiveExamplePayload", - "description": "Auto-generated description", - "bindings": { - "kafka": { - "bindingVersion": "0.4.0" - } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "example-topic", + "messages": { + "example-topic_publish_receiveExamplePayload.message": { "name": "io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto", "title": "ExamplePayloadDto", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" @@ -120,82 +107,66 @@ } }, "multi-payload-topic": { - "publish": { - "operationId": "multi-payload-topic_publish", - "description": "Override description in the AsyncListener annotation with servers at kafka:29092", - "bindings": { - "kafka": { - "groupId": { - "type": "string", - "enum": [ - "foo-groupId" - ] - }, - "clientId": { - "type": "string", - "enum": [ - "foo-clientId" - ] - }, - "bindingVersion": "0.4.0" + "address": "multi-payload-topic", + "messages": { + "multi-payload-topic_publish.message.0": { + "name": "io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", + "payload": { + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto" + } + }, + "headers": { + "$ref": "#/components/schemas/SpringKafkaDefaultHeaders-AnotherPayloadDto" + }, + "bindings": { + "kafka": { + "bindingVersion": "0.4.0" + } } }, - "message": { - "oneOf": [ - { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", - "name": "io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", - "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.AnotherPayloadDto" - }, - "headers": { - "$ref": "#/components/schemas/SpringKafkaDefaultHeaders-AnotherPayloadDto" - }, - "bindings": { - "kafka": { - "bindingVersion": "0.4.0" - } - } - }, - { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", - "name": "io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto", - "title": "ExamplePayloadDto", - "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" - }, - "headers": { - "$ref": "#/components/schemas/SpringKafkaDefaultHeaders-ExamplePayloadDto" - }, - "bindings": { - "kafka": { - "bindingVersion": "0.4.0" - } - } - }, - { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", - "name": "javax.money.MonetaryAmount", - "title": "MonetaryAmount", - "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.addons.common_model_converters.converters.monetaryamount.MonetaryAmount" - }, - "headers": { - "$ref": "#/components/schemas/SpringKafkaDefaultHeaders-MonetaryAmount" + "multi-payload-topic_publish.message.1": { + "name": "io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto", + "title": "ExamplePayloadDto", + "payload": { + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.ExamplePayloadDto" + } + }, + "headers": { + "$ref": "#/components/schemas/SpringKafkaDefaultHeaders-ExamplePayloadDto" + }, + "bindings": { + "kafka": { + "bindingVersion": "0.4.0" + } + } + }, + "multi-payload-topic_publish.message.2": { + "name": "javax.money.MonetaryAmount", + "title": "MonetaryAmount", + "payload": { + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.addons.common_model_converters.converters.monetaryamount.MonetaryAmount" + } + }, + "headers": { + "$ref": "#/components/schemas/SpringKafkaDefaultHeaders-MonetaryAmount" + }, + "bindings": { + "kafka": { + "key": { + "type": "string", + "description": "Kafka Consumer Message Key", + "example": "example-key" }, - "bindings": { - "kafka": { - "key": { - "type": "string", - "description": "Kafka Consumer Message Key", - "example": "example-key" - }, - "bindingVersion": "0.4.0" - } - } + "bindingVersion": "0.4.0" } - ] + } } } }, @@ -279,20 +250,16 @@ } }, "primitive-topic": { - "publish": { - "operationId": "primitive-topic_publish_receivePrimitivePayload", - "description": "Auto-generated description", - "bindings": { - "kafka": { - "bindingVersion": "0.4.0" - } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "primitive-topic", + "messages": { + "primitive-topic_publish_receivePrimitivePayload.message": { "name": "java.lang.String", "title": "String", "payload": { - "$ref": "#/components/schemas/String" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/String" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" @@ -311,27 +278,17 @@ } }, "topic-defined-via-asyncPublisher-annotation": { - "subscribe": { - "operationId": "topic-defined-via-asyncPublisher-annotation_subscribe", - "description": "Custom, optional description defined in the AsyncPublisher annotation", - "bindings": { - "kafka": { - "clientId": { - "type": "string", - "enum": [ - "foo-clientId" - ] - }, - "bindingVersion": "0.4.0" - } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "topic-defined-via-asyncPublisher-annotation", + "messages": { + "topic-defined-via-asyncPublisher-annotation_subscribe.message": { "name": "io.github.stavshamir.springwolf.example.kafka.dtos.NestedPayloadDto", "title": "NestedPayloadDto", "description": "Payload model with nested complex types", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.NestedPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.kafka.dtos.NestedPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/SpringDefaultHeaderAndCloudEvent" @@ -350,12 +307,129 @@ } } }, + "operations": { + "another-topic_publish_receiveAnotherPayloadBatched": { + "action": "receive", + "channel": { + "$ref": "#/channels/another-topic" + }, + "description": "Auto-generated description", + "bindings": { + "kafka": { + "groupId": { + "type": "string", + "enum": [ + "example-group-id" + ] + }, + "bindingVersion": "0.4.0" + } + }, + "messages": [ + { + "$ref": "#/channels/another-topic/messages/another-topic_publish_receiveAnotherPayloadBatched.message" + } + ] + }, + "example-topic_publish_receiveExamplePayload": { + "action": "receive", + "channel": { + "$ref": "#/channels/example-topic" + }, + "description": "Auto-generated description", + "bindings": { + "kafka": { + "bindingVersion": "0.4.0" + } + }, + "messages": [ + { + "$ref": "#/channels/example-topic/messages/example-topic_publish_receiveExamplePayload.message" + } + ] + }, + "multi-payload-topic_publish": { + "action": "receive", + "channel": { + "$ref": "#/channels/multi-payload-topic" + }, + "description": "Override description in the AsyncListener annotation with servers at kafka:29092", + "bindings": { + "kafka": { + "groupId": { + "type": "string", + "enum": [ + "foo-groupId" + ] + }, + "clientId": { + "type": "string", + "enum": [ + "foo-clientId" + ] + }, + "bindingVersion": "0.4.0" + } + }, + "messages": [ + { + "$ref": "#/channels/multi-payload-topic/messages/multi-payload-topic_publish.message.0" + }, + { + "$ref": "#/channels/multi-payload-topic/messages/multi-payload-topic_publish.message.1" + }, + { + "$ref": "#/channels/multi-payload-topic/messages/multi-payload-topic_publish.message.2" + } + ] + }, + "primitive-topic_publish_receivePrimitivePayload": { + "action": "receive", + "channel": { + "$ref": "#/channels/primitive-topic" + }, + "description": "Auto-generated description", + "bindings": { + "kafka": { + "bindingVersion": "0.4.0" + } + }, + "messages": [ + { + "$ref": "#/channels/primitive-topic/messages/primitive-topic_publish_receivePrimitivePayload.message" + } + ] + }, + "topic-defined-via-asyncPublisher-annotation_subscribe": { + "action": "send", + "channel": { + "$ref": "#/channels/topic-defined-via-asyncPublisher-annotation" + }, + "description": "Custom, optional description defined in the AsyncPublisher annotation", + "bindings": { + "kafka": { + "clientId": { + "type": "string", + "enum": [ + "foo-clientId" + ] + }, + "bindingVersion": "0.4.0" + } + }, + "messages": [ + { + "$ref": "#/channels/topic-defined-via-asyncPublisher-annotation/messages/topic-defined-via-asyncPublisher-annotation_subscribe.message" + } + ] + } + }, "components": { "schemas": { "HeadersNotDocumented": { "type": "object", - "properties": { }, - "example": { }, + "properties": {}, + "example": {}, "x-json-schema": { "$schema": "https://json-schema.org/draft-04/schema#", "name": "HeadersNotDocumented", @@ -931,7 +1005,7 @@ "name": "io.github.stavshamir.springwolf.example.kafka.dtos.NestedPayloadDto", "properties": { "examplePayloads": { - "items": { }, + "items": {}, "name": "examplePayloads", "type": "array" }, @@ -949,6 +1023,5 @@ } } } - }, - "tags": [ ] + } } diff --git a/springwolf-examples/springwolf-sns-example/src/main/resources/application.properties b/springwolf-examples/springwolf-sns-example/src/main/resources/application.properties index bd191de07..123cee570 100644 --- a/springwolf-examples/springwolf-sns-example/src/main/resources/application.properties +++ b/springwolf-examples/springwolf-sns-example/src/main/resources/application.properties @@ -26,7 +26,7 @@ springwolf.docket.info.contact.email=example@example.com springwolf.docket.info.contact.url=https://github.com/springwolf/springwolf-core springwolf.docket.info.license.name=Apache License 2.0 springwolf.docket.servers.sns.protocol=sns -springwolf.docket.servers.sns.url=http://localhost:4566 +springwolf.docket.servers.sns.host=http://localhost:4566 springwolf.use-fqn=true springwolf.plugin.sns.publishing.enabled=true 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 f5008280e..0541a6823 100644 --- a/springwolf-examples/springwolf-sns-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-sns-example/src/test/resources/asyncapi.json @@ -1,5 +1,5 @@ { - "asyncapi": "2.6.0", + "asyncapi": "3.0.0", "info": { "title": "Springwolf example project - SNS", "version": "1.0.0", @@ -17,77 +17,68 @@ "defaultContentType": "application/json", "servers": { "sns": { - "url": "http://localhost:4566", + "host": "localhost:4566", "protocol": "sns" } }, "channels": { "another-topic": { - "subscribe": { - "operationId": "another-topic_subscribe", - "description": "Custom, optional description defined in the AsyncPublisher annotation", - "bindings": { - "sns": { } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "another-topic", + "messages": { + "another-topic_publish.message": { "name": "io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", "description": "Another payload model", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "sns": { } + "sns": {} } - } - }, - "publish": { - "operationId": "another-topic_publish", - "description": "Auto-generated description", - "bindings": { - "sns": { } }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "another-topic_subscribe.message": { "name": "io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto", "title": "AnotherPayloadDto", "description": "Another payload model", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sns.dtos.AnotherPayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "sns": { } + "sns": {} } } } }, "example-topic": { - "publish": { - "operationId": "example-topic_publish", - "description": "Auto-generated description", - "bindings": { - "sns": { } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "address": "example-topic", + "messages": { + "example-topic_publish.message": { "name": "io.github.stavshamir.springwolf.example.sns.dtos.ExamplePayloadDto", "title": "ExamplePayloadDto", "description": "Example payload model", "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sns.dtos.ExamplePayloadDto" + "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sns.dtos.ExamplePayloadDto" + } }, "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, "bindings": { - "sns": { } + "sns": {} } } } @@ -97,8 +88,8 @@ "schemas": { "HeadersNotDocumented": { "type": "object", - "properties": { }, - "example": { }, + "properties": {}, + "example": {}, "x-json-schema": { "$schema": "https://json-schema.org/draft-04/schema#", "name": "HeadersNotDocumented", @@ -249,5 +240,81 @@ } } }, - "tags": [ ] + "operations": { + "another-topic_publish": { + "action": "receive", + "channel": { + "$ref": "#/channels/another-topic" + }, + "description": "Auto-generated description", + "bindings": { + "sns": { + "consumers": [ + { + "protocol": "sqs", + "endpoint": { + "name": "myQueue" + }, + "rawMessageDelivery": false + } + ] + } + }, + "messages": [ + { + "$ref": "#/channels/another-topic/messages/another-topic_publish.message" + } + ] + }, + "another-topic_subscribe": { + "action": "send", + "channel": { + "$ref": "#/channels/another-topic" + }, + "description": "Custom, optional description defined in the AsyncPublisher annotation", + "bindings": { + "sns": { + "consumers": [ + { + "protocol": "sqs", + "endpoint": { + "name": "myQueue" + }, + "rawMessageDelivery": false + } + ] + } + }, + "messages": [ + { + "$ref": "#/channels/another-topic/messages/another-topic_subscribe.message" + } + ] + }, + "example-topic_publish": { + "action": "receive", + "channel": { + "$ref": "#/channels/example-topic" + }, + "description": "Auto-generated description", + "bindings": { + "sns": { + "consumers": [ + { + "protocol": "sqs", + "endpoint": { + "name": "myQueue" + }, + "rawMessageDelivery": false + } + ] + } + }, + "messages": [ + { + "$ref": "#/channels/example-topic/messages/example-topic_publish.message" + } + ] + } + } } \ No newline at end of file diff --git a/springwolf-examples/springwolf-sqs-example/src/main/resources/application.properties b/springwolf-examples/springwolf-sqs-example/src/main/resources/application.properties index bda7b6ee5..9db619460 100644 --- a/springwolf-examples/springwolf-sqs-example/src/main/resources/application.properties +++ b/springwolf-examples/springwolf-sqs-example/src/main/resources/application.properties @@ -26,7 +26,7 @@ springwolf.docket.info.contact.email=example@example.com springwolf.docket.info.contact.url=https://github.com/springwolf/springwolf-core springwolf.docket.info.license.name=Apache License 2.0 springwolf.docket.servers.sqs.protocol=sqs -springwolf.docket.servers.sqs.url=http://localhost:4566 +springwolf.docket.servers.sqs.host=http://localhost:4566 springwolf.use-fqn=true springwolf.plugin.sqs.publishing.enabled=true 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 6fdd4bf9e..8633462ba 100644 --- a/springwolf-examples/springwolf-sqs-example/src/test/resources/asyncapi.json +++ b/springwolf-examples/springwolf-sqs-example/src/test/resources/asyncapi.json @@ -1,5 +1,5 @@ { - "asyncapi": "2.6.0", + "asyncapi": "3.0.0", "info": { "title": "Springwolf example project - SQS", "version": "1.0.0", @@ -17,85 +17,74 @@ "defaultContentType": "application/json", "servers": { "sqs": { - "url": "http://localhost:4566", + "host": "http://localhost:4566", "protocol": "sqs" } }, "channels": { "another-queue": { - "subscribe": { - "operationId": "another-queue_subscribe", - "description": "Custom, optional description defined in the AsyncPublisher annotation", - "bindings": { - "sqs": { - "internal-field": "customValue", - "nested": { - "key": "nestedValue" - } - } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", - "name": "io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", - "description": "Another payload model", - "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto" - }, + "messages": { + "another-queue_publish_receiveAnotherPayload.message": { "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, + "payload": { + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto" + } + }, + "name": "io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", "bindings": { - "sqs": { } + "sqs": {} } - } - }, - "publish": { - "operationId": "another-queue_publish_receiveAnotherPayload", - "description": "Auto-generated description", - "bindings": { - "sqs": { } }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", - "name": "io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto", - "title": "AnotherPayloadDto", - "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto" - }, + "another-queue_subscribe.message": { + "description": "Another payload model", "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, + "payload": { + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto" + } + }, + "name": "io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto", + "title": "AnotherPayloadDto", "bindings": { - "sqs": { } + "sqs": {} } } } }, "example-queue": { - "publish": { - "operationId": "example-queue_publish_receiveExamplePayload", - "description": "Auto-generated description", - "bindings": { - "sqs": { } - }, - "message": { - "schemaFormat": "application/vnd.oai.openapi+json;version=3.0.0", - "name": "io.github.stavshamir.springwolf.example.sqs.dtos.ExamplePayloadDto", - "title": "ExamplePayloadDto", - "payload": { - "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sqs.dtos.ExamplePayloadDto" - }, + "messages": { + "example-queue_publish_receiveExamplePayload.message": { "headers": { "$ref": "#/components/schemas/HeadersNotDocumented" }, + "payload": { + "schemaFormat": "application/vnd.aai.asyncapi+json;version=3.0.0", + "schema": { + "$ref": "#/components/schemas/io.github.stavshamir.springwolf.example.sqs.dtos.ExamplePayloadDto" + } + }, + "name": "io.github.stavshamir.springwolf.example.sqs.dtos.ExamplePayloadDto", + "title": "ExamplePayloadDto", "bindings": { - "sqs": { } + "sqs": {} } } }, "bindings": { - "sqs": { } + "sqs": { + "queue": { + "name": "example-queue", + "fifoQueue": true, + } + } } } }, @@ -103,8 +92,8 @@ "schemas": { "HeadersNotDocumented": { "type": "object", - "properties": { }, - "example": { } + "properties": {}, + "example": {} }, "io.github.stavshamir.springwolf.example.sqs.dtos.AnotherPayloadDto": { "required": [ @@ -169,5 +158,66 @@ } } }, - "tags": [ ] + "operations": { + "another-queue_publish_receiveAnotherPayload": { + "action": "receive", + "channel": { + "$ref": "#/channels/another-queue" + }, + "description": "Auto-generated description", + "bindings": { + "sqs": { + "queues": [{ + "name": "another-queue", + "fifoQueue": true, + }] + } + }, + "messages": [ + { + "$ref": "#/channels/another-queue/messages/another-queue_publish_receiveAnotherPayload.message" + } + ] + }, + "another-queue_subscribe": { + "action": "send", + "channel": { + "$ref": "#/channels/another-queue" + }, + "description": "Custom, optional description defined in the AsyncPublisher annotation", + "bindings": { + "sqs": { + "queues": [{ + "name": "another-queue", + "fifoQueue": true, + }] + } + }, + "messages": [ + { + "$ref": "#/channels/another-queue/messages/another-queue_subscribe.message" + } + ] + }, + "example-queue_publish_receiveExamplePayload": { + "action": "receive", + "channel": { + "$ref": "#/channels/example-queue" + }, + "description": "Auto-generated description", + "bindings": { + "sqs": { + "queues": [{ + "name": "another-queue", + "fifoQueue": true, + }] + } + }, + "messages": [ + { + "$ref": "#/channels/example-queue/messages/example-queue_publish_receiveExamplePayload.message" + } + ] + } + } } \ No newline at end of file diff --git a/springwolf-plugins/springwolf-amqp-plugin/README.md b/springwolf-plugins/springwolf-amqp-plugin/README.md index 6d53340bf..eb56d1438 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/README.md +++ b/springwolf-plugins/springwolf-amqp-plugin/README.md @@ -42,7 +42,7 @@ springwolf.docket.info.title=${spring.application.name} springwolf.docket.info.version=1.0.0 springwolf.docket.servers.amqp.protocol=amqp -springwolf.docket.servers.amqp.url=amqp:5672 +springwolf.docket.servers.amqp.host=amqp:5672 ``` The basePackage field must be set with the name of the package containing the classes to be scanned for `@RabbitListener` 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 846bdeff7..e0e2bebac 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 @@ -117,7 +117,6 @@ private static AMQPChannelExchangeProperties buildExchangeProperties( .build(); } - // FIXME: Should be converted to the proper enum var type = Stream.of(annotation.bindings()) .map(it -> it.exchange().type()) .findFirst() diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducer.java b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducer.java index 7db13e01b..0cc6dafe3 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducer.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/main/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducer.java @@ -33,8 +33,13 @@ public void send(String channelName, Object payload) { AsyncAPI asyncAPI = asyncApiService.getAsyncAPI(); ChannelObject channelItem = asyncAPI.getChannels().get(channelName); + Operation operation = null; + if (asyncAPI.getOperations() != null) { + operation = asyncAPI.getOperations().get("amqp"); + } + String exchange = getExchangeName(channelItem); - String routingKey = getRoutingKey(channelItem); + String routingKey = getRoutingKey(operation); if (routingKey.isEmpty() && exchange.isEmpty()) { routingKey = channelName; } @@ -60,12 +65,8 @@ private String getExchangeName(ChannelObject channelItem) { return exchange; } - private String getRoutingKey(ChannelObject channelItem) { + private String getRoutingKey(Operation operation) { String routingKey = ""; - // FIXME - // Operation operation = - // channelItem.getSubscribe() != null ? channelItem.getSubscribe() : channelItem.getPublish(); - Operation operation = Operation.builder().build(); if (operation != null && operation.getBindings() != null && operation.getBindings().containsKey("amqp")) { diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/AmqpOperationBindingProcessorTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/AmqpOperationBindingProcessorTest.java index 1c1fb304b..3cc7fbae6 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/AmqpOperationBindingProcessorTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/bindings/processor/AmqpOperationBindingProcessorTest.java @@ -6,6 +6,8 @@ import io.github.stavshamir.springwolf.asyncapi.v3.bindings.amqp.AMQPOperationBinding; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; class AmqpOperationBindingProcessorTest { @@ -21,9 +23,14 @@ void mapToOperationBindingTest() throws NoSuchMethodException { assertThat(binding.getType()).isEqualTo("amqp"); assertThat(binding.getBinding()) - .isEqualTo(AMQPOperationBinding.builder().build()); - // new AMQPOperationBinding(0, null, List.of(), 0, 0, false, null, null, false, false, - // "0.2.0") + .isEqualTo(AMQPOperationBinding.builder() + .cc(List.of()) + .priority(0) + .deliveryMode(0) + .mandatory(false) + .timestamp(false) + .ack(false) + .build()); } @AmqpAsyncOperationBinding diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtilTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtilTest.java index 6ca067572..23c79d83c 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtilTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/scanners/channels/annotation/RabbitListenerUtilTest.java @@ -40,7 +40,7 @@ class RabbitListenerUtilTest { new RabbitListenerUtil.RabbitListenerUtilContext(emptyMap(), emptyMap(), emptyMap()); @Nested - public class QueuesConfiguration { + class QueuesConfiguration { @ParameterizedTest @ValueSource(classes = {ClassWithQueuesConfiguration.class, ClassWithQueuesToDeclare.class}) @@ -429,7 +429,7 @@ private void methodWithAnnotation(String payload) {} } @Nested - public class RabbitListenerUtilContextTest { + class RabbitListenerUtilContextTest { @Test void testEmptyContext() { // when diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfAmqpProducerConfigurationIntegrationTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfAmqpProducerConfigurationIntegrationTest.java index a514af5ef..3652e1472 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfAmqpProducerConfigurationIntegrationTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfAmqpProducerConfigurationIntegrationTest.java @@ -40,7 +40,7 @@ public class SpringwolfAmqpProducerConfigurationIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.amqp.publishing.enabled=true" }) @MockBeans( @@ -81,7 +81,7 @@ void springwolfAmqpProducerShouldBePresentInSpringContext() { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.amqp.publishing.enabled=false" }) @MockBeans( diff --git a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducerTest.java b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducerTest.java index 14e117557..d834bfc29 100644 --- a/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducerTest.java +++ b/springwolf-plugins/springwolf-amqp-plugin/src/test/java/io/github/stavshamir/springwolf/producer/SpringwolfAmqpProducerTest.java @@ -7,13 +7,14 @@ import io.github.stavshamir.springwolf.asyncapi.v3.bindings.amqp.AMQPChannelExchangeProperties; import io.github.stavshamir.springwolf.asyncapi.v3.bindings.amqp.AMQPOperationBinding; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelObject; +import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.ChannelReference; import io.github.stavshamir.springwolf.asyncapi.v3.model.info.Info; import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.Operation; +import io.github.stavshamir.springwolf.asyncapi.v3.model.operation.OperationAction; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.amqp.rabbit.core.RabbitTemplate; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,7 +36,7 @@ void setUp() { asyncApiService = mock(AsyncApiService.class); rabbitTemplate = mock(RabbitTemplate.class); - springwolfAmqpProducer = new SpringwolfAmqpProducer(asyncApiService, Collections.singletonList(rabbitTemplate)); + springwolfAmqpProducer = new SpringwolfAmqpProducer(asyncApiService, List.of(rabbitTemplate)); } @Test @@ -57,17 +58,16 @@ void send_exchangeAndNoRoutingKey() { AMQPChannelExchangeProperties properties = new AMQPChannelExchangeProperties(); properties.setName("exchange-name"); ChannelObject channelItem = ChannelObject.builder() + .channelId("channel-name") .bindings(Map.of( "amqp", AMQPChannelBinding.builder().exchange(properties).build())) - // FIXME - // .publish(Operation.builder() - // .bindings(Map.of("amqp", new AMQPOperationBinding())) - // .build()) .build(); - Map channels = Map.of("channel-name", channelItem); + Map channels = Map.of(channelItem.getChannelId(), channelItem); Operation operation = Operation.builder() + .action(OperationAction.SEND) .bindings(Map.of("amqp", AMQPOperationBinding.builder().build())) + .channel(ChannelReference.fromChannel(channelItem)) .build(); Map operations = Map.of("amqp", operation); @@ -89,6 +89,7 @@ void send_exchangeAndRoutingKeyFromBindings() { AMQPChannelExchangeProperties properties = new AMQPChannelExchangeProperties(); properties.setName("exchange-name"); ChannelObject channelItem = ChannelObject.builder() + .channelId("channel-name") .bindings(Map.of( "amqp", AMQPChannelBinding.builder().exchange(properties).build())) @@ -101,7 +102,7 @@ void send_exchangeAndRoutingKeyFromBindings() { // .build())) // .build()) .build(); - Map channels = Map.of("channel-name", channelItem); + Map channels = Map.of(channelItem.getChannelId(), channelItem); Operation operation = Operation.builder() .bindings(Map.of( "amqp", 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 8bf751f15..af6a3294d 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 @@ -16,6 +16,7 @@ import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessageObject; import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message.MessagePayload; 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.server.Server; import io.github.stavshamir.springwolf.configuration.AsyncApiDocket; import io.github.stavshamir.springwolf.configuration.AsyncApiDocketService; @@ -40,9 +41,9 @@ public class CloudStreamFunctionChannelsScanner implements ChannelsScanner { private final FunctionalChannelBeanBuilder functionalChannelBeanBuilder; @Override - public Map scan() { + public Map scanChannels() { Set beanMethods = beanMethodsScanner.getBeanMethods(); - return ChannelMerger.merge(beanMethods.stream() + return ChannelMerger.mergeChannels(beanMethods.stream() .map(functionalChannelBeanBuilder::fromMethodBean) .flatMap(Set::stream) .filter(this::isChannelBean) @@ -50,6 +51,12 @@ public Map scan() { .collect(Collectors.toList())); } + @Override + public Map scanOperations() { + // FIXME + return Map.of(); + } + private boolean isChannelBean(FunctionalChannelBeanData beanData) { return cloudStreamBindingsProperties.getBindings().containsKey(beanData.cloudStreamBinding()); } 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 8f830a7d5..422d12909 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 @@ -66,7 +66,7 @@ "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.asyncapi.scanners.channels.cloudstream", "springwolf.docket.servers.kafka.protocol=kafka", - "springwolf.docket.servers.kafka.url=kafka:9092", + "springwolf.docket.servers.kafka.host=kafka:9092", }) @EnableConfigurationProperties @Import(CloudStreamFunctionChannelsScannerIntegrationTest.Configuration.class) @@ -85,7 +85,7 @@ class CloudStreamFunctionChannelsScannerIntegrationTest { @Test void testNoBindings() { when(bindingServiceProperties.getBindings()).thenReturn(Collections.emptyMap()); - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); assertThat(channels).isEmpty(); } @@ -98,7 +98,7 @@ void testConsumerBinding() { when(bindingServiceProperties.getBindings()).thenReturn(Map.of("testConsumer-in-0", testConsumerInBinding)); // When scan is called - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); // Then the returned channels contain a ChannelItem with the correct data MessageObject message = MessageObject.builder() @@ -133,7 +133,7 @@ void testSupplierBinding() { when(bindingServiceProperties.getBindings()).thenReturn(Map.of("testSupplier-out-0", testSupplierOutBinding)); // When scan is called - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); // Then the returned channels contain a ChannelItem with the correct data @@ -177,7 +177,7 @@ void testFunctionBinding() { "testFunction-out-0", testFunctionOutBinding)); // When scan is called - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); // Then the returned channels contain a publish ChannelItem and a subscribe ChannelItem MessageObject subscribeMessage = MessageObject.builder() @@ -241,7 +241,7 @@ void testKStreamFunctionBinding() { "kStreamTestFunction-out-0", testFunctionOutBinding)); // When scan is called - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); // Then the returned channels contain a publish ChannelItem and a subscribe ChannelItem MessageObject subscribeMessage = MessageObject.builder() @@ -304,7 +304,7 @@ void testFunctionBindingWithSameTopicName() { "testFunction-out-0", testFunctionOutBinding)); // When scan is called - Map channels = scanner.scan(); + Map channels = scanner.scanChannels(); // Then the returned merged channels contain a publish operation and a subscribe operation MessageObject subscribeMessage = MessageObject.builder() diff --git a/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfJmsControllerIntegrationTest.java b/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfJmsControllerIntegrationTest.java index d57e4bffb..fa84d00cd 100644 --- a/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfJmsControllerIntegrationTest.java +++ b/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfJmsControllerIntegrationTest.java @@ -53,7 +53,7 @@ "springwolf.docket.info.title=Title", "springwolf.docket.info.version=1.0", "springwolf.docket.servers.jms.protocol=jms", - "springwolf.docket.servers.jms.url=127.0.0.1", + "springwolf.docket.servers.jms.host=127.0.0.1", "springwolf.plugin.jms.publishing.enabled=true", "springwolf.use-fqn=true" }) diff --git a/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfJmsProducerConfigurationIntegrationTest.java b/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfJmsProducerConfigurationIntegrationTest.java index 60917ba72..7ae8be750 100644 --- a/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfJmsProducerConfigurationIntegrationTest.java +++ b/springwolf-plugins/springwolf-jms-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfJmsProducerConfigurationIntegrationTest.java @@ -41,7 +41,7 @@ public class SpringwolfJmsProducerConfigurationIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.jms.publishing.enabled=true" }) @MockBeans( @@ -82,7 +82,7 @@ void springwolfJmsProducerShouldBePresentInSpringContext() { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.jms.publishing.enabled=false" }) @MockBeans( diff --git a/springwolf-plugins/springwolf-kafka-plugin/README.md b/springwolf-plugins/springwolf-kafka-plugin/README.md index d7a783a4d..d3e3d984f 100644 --- a/springwolf-plugins/springwolf-kafka-plugin/README.md +++ b/springwolf-plugins/springwolf-kafka-plugin/README.md @@ -44,7 +44,7 @@ springwolf.docket.info.title=${spring.application.name} springwolf.docket.info.version=1.0.0 springwolf.docket.servers.kafka.protocol=kafka -springwolf.docket.servers.kafka.url=${kafka.bootstrap.servers:localhost:29092} +springwolf.docket.servers.kafka.host=${kafka.bootstrap.servers:localhost:29092} ``` The basePackage field must be set with the name of the package containing the classes to be scanned for `@KafkaListener` diff --git a/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfKafkaControllerIntegrationTest.java b/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfKafkaControllerIntegrationTest.java index 8081e70c8..ae75c63c9 100644 --- a/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfKafkaControllerIntegrationTest.java +++ b/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/asyncapi/controller/SpringwolfKafkaControllerIntegrationTest.java @@ -53,7 +53,7 @@ "springwolf.docket.info.title=Title", "springwolf.docket.info.version=1.0", "springwolf.docket.servers.kafka.protocol=kafka", - "springwolf.docket.servers.kafka.url=127.0.0.1", + "springwolf.docket.servers.kafka.host=127.0.0.1", "springwolf.plugin.kafka.publishing.enabled=true", "springwolf.use-fqn=true" }) diff --git a/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfKafkaProducerConfigurationIntegrationTest.java b/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfKafkaProducerConfigurationIntegrationTest.java index b024317cc..65a6bb898 100644 --- a/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfKafkaProducerConfigurationIntegrationTest.java +++ b/springwolf-plugins/springwolf-kafka-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfKafkaProducerConfigurationIntegrationTest.java @@ -39,7 +39,7 @@ public class SpringwolfKafkaProducerConfigurationIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.kafka.publishing.enabled=true" }) @MockBeans( @@ -78,7 +78,7 @@ void springwolfKafkaTemplateShouldBePresentInSpringContext() { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.kafka.publishing.enabled=false" }) @MockBeans( diff --git a/springwolf-plugins/springwolf-sns-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSnsProducerConfigurationIntegrationTest.java b/springwolf-plugins/springwolf-sns-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSnsProducerConfigurationIntegrationTest.java index a59ccdf8e..98374c386 100644 --- a/springwolf-plugins/springwolf-sns-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSnsProducerConfigurationIntegrationTest.java +++ b/springwolf-plugins/springwolf-sns-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSnsProducerConfigurationIntegrationTest.java @@ -41,7 +41,7 @@ public class SpringwolfSnsProducerConfigurationIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.sns.publishing.enabled=true" }) @MockBeans( @@ -82,7 +82,7 @@ void springwolfSqsProducerShouldBePresentInSpringContext() { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.sns.publishing.enabled=false" }) @MockBeans( diff --git a/springwolf-plugins/springwolf-sqs-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSqsProducerConfigurationIntegrationTest.java b/springwolf-plugins/springwolf-sqs-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSqsProducerConfigurationIntegrationTest.java index 8abf87714..683934882 100644 --- a/springwolf-plugins/springwolf-sqs-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSqsProducerConfigurationIntegrationTest.java +++ b/springwolf-plugins/springwolf-sqs-plugin/src/test/java/io/github/stavshamir/springwolf/configuration/SpringwolfSqsProducerConfigurationIntegrationTest.java @@ -41,7 +41,7 @@ public class SpringwolfSqsProducerConfigurationIntegrationTest { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.sqs.publishing.enabled=true" }) @MockBeans( @@ -82,7 +82,7 @@ void springwolfSqsProducerShouldBePresentInSpringContext() { "springwolf.docket.info.version=1.0.0", "springwolf.docket.base-package=io.github.stavshamir.springwolf.example", "springwolf.docket.servers.test-protocol.protocol=test", - "springwolf.docket.servers.test-protocol.url=some-server:1234", + "springwolf.docket.servers.test-protocol.host=some-server:1234", "springwolf.plugin.sqs.publishing.enabled=false" }) @MockBeans(