-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/handle no payload #687
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
✅ Deploy Preview for springwolf-ui canceled.
|
timonback
force-pushed
the
feat/handle-no-payload
branch
2 times, most recently
from
April 12, 2024 17:02
18dc5c0
to
3d37f09
Compare
timonback
force-pushed
the
feat/handle-no-payload
branch
from
April 19, 2024 16:58
858c2b1
to
1c406fb
Compare
Co-authored-by: David Müller <[email protected]> fix(core): extract AsyncMessage#description Co-authored-by: David Müller <[email protected]> feat(core): use fqn in for schema name Co-authored-by: David Müller <[email protected]> refactor(core): split test for PayloadClassExtractor and TypeToClassConverter Co-authored-by: Timon Back <[email protected]> test(kafka): remove unused use-fqn setting Co-authored-by: David Müller <[email protected]> test(kafka): update asyncapi.json Co-authored-by: David Müller <[email protected]> refactor(core): extract TypeToClassConverter Co-authored-by: David Müller <[email protected]> refactor(core): replace pair of resolved schema name and schema object with a specific record Co-authored-by: Timon Back <[email protected]> feat(core): add NoPayloadUsedConsumer Co-authored-by: David Müller <[email protected]> refactor(core): update AsyncHeadersBuilder (wip) Co-authored-by: David Müller <[email protected]> feat(core): Use new PayloadService (wip) Co-authored-by: David Müller <[email protected]> refactor(core): Check description in Schema annotation in DefaultComponentsService test(core): Add PayloadServiceTest refactor(core): Give PayloadService a name feat(core): Add PayloadNotUsed Schema Co-authored-by: Timon Back <[email protected]> refactor(core): PayloadClassExtractor returns optional instead of throwing an exception Co-authored-by: Timon Back <[email protected]> diff --git a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessagePayload.java b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessagePayload.java index 9ccf6e1c..e6302005 100644 --- a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessagePayload.java +++ b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessagePayload.java @@ -7,10 +7,12 @@ import io.github.springwolf.asyncapi.v3.model.schema.MultiFormatSchema; import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.ToString; @Getter @JsonSerialize(using = MessagePayloadSerializer.class) @EqualsAndHashCode +@ToString public class MessagePayload { private MultiFormatSchema multiFormatSchema; private SchemaObject schema; diff --git a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessageReference.java b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessageReference.java index b938b4d4..bc6b16b9 100644 --- a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessageReference.java +++ b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/channel/message/MessageReference.java @@ -9,6 +9,7 @@ import lombok.NoArgsConstructor; import lombok.ToString; @EqualsAndHashCode +@ToString @NoArgsConstructor @AllArgsConstructor public class MessageReference implements Message, Reference { diff --git a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaObject.java b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaObject.java index 710a3ed0..497fb78e 100644 --- a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaObject.java +++ b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaObject.java @@ -10,6 +10,7 @@ import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import java.math.BigDecimal; import java.util.List; @@ -31,6 +32,7 @@ import java.util.Map; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) +@ToString public class SchemaObject extends ExtendableObject implements Schema { /** * Adds support for polymorphism. The discriminator is the schema property name that is used to differentiate diff --git a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaReference.java b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaReference.java index 2384a153..848c27fb 100644 --- a/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaReference.java +++ b/springwolf-asyncapi/src/main/java/io/github/springwolf/asyncapi/v3/model/schema/SchemaReference.java @@ -9,6 +9,7 @@ import lombok.NoArgsConstructor; import lombok.ToString; @EqualsAndHashCode +@ToString @NoArgsConstructor @AllArgsConstructor public class SchemaReference implements Schema, Reference { diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/ComponentsService.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/ComponentsService.java index 9c982b3d..f5132257 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/ComponentsService.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/ComponentsService.java @@ -12,6 +12,8 @@ public interface ComponentsService { Map<String, SchemaObject> getSchemas(); + SchemaObject resolveSchema(String schemaName); + String registerSchema(SchemaObject headers); String registerSchema(Class<?> type); diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/DefaultComponentsService.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/DefaultComponentsService.java index 59caf4e5..f2e3104c 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/DefaultComponentsService.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/DefaultComponentsService.java @@ -14,6 +14,7 @@ import io.swagger.v3.core.jackson.TypeNameResolver; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; +import jakarta.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -60,6 +61,15 @@ public class DefaultComponentsService implements ComponentsService { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } + @Override + @Nullable + public SchemaObject resolveSchema(String schemaName) { + if (schemas.containsKey(schemaName)) { + return swaggerSchemaUtil.mapSchema(schemas.get(schemaName)); + } + return null; + } + @Override public String registerSchema(SchemaObject headers) { log.debug("Registering schema for {}", headers.getTitle()); @@ -81,6 +91,7 @@ public class DefaultComponentsService implements ComponentsService { @Override public String registerSchema(Class<?> type) { + // FIXME: Move this to the new HeadersService return this.registerSchema(type, properties.getDocket().getDefaultContentType()); } @@ -90,13 +101,13 @@ public class DefaultComponentsService implements ComponentsService { String actualContentType = StringUtils.isBlank(contentType) ? properties.getDocket().getDefaultContentType() : contentType; - Map<String, Schema> schemas = new LinkedHashMap<>(runWithFqnSetting((unused) -> converter.readAll(type))); + Map<String, Schema> newSchemas = new LinkedHashMap<>(runWithFqnSetting((unused) -> converter.readAll(type))); - String schemaName = getSchemaName(type, schemas); + String schemaName = getSchemaName(type, newSchemas); - preProcessSchemas(schemas, schemaName, type); - schemas.forEach(this.schemas::putIfAbsent); - schemas.values().forEach(schema -> postProcessSchema(schema, actualContentType)); + preProcessSchemas(newSchemas, schemaName, type); + newSchemas.forEach(this.schemas::putIfAbsent); + newSchemas.values().forEach(schema -> postProcessSchema(schema, actualContentType)); return schemaName; } @@ -130,11 +141,22 @@ public class DefaultComponentsService implements ComponentsService { return new ArrayList<>(resolvedPayloadModelName).get(0); } - return type.getSimpleName(); + return getNameFromClass(type); } private void preProcessSchemas(Map<String, Schema> schemas, String schemaName, Class<?> type) { processAsyncApiPayloadAnnotation(schemas, schemaName, type); + processSchemaAnnotation(schemas, schemaName, type); + } + + private void processSchemaAnnotation(Map<String, Schema> schemas, String schemaName, Class<?> type) { + Schema schemaForType = schemas.get(schemaName); + if (schemaForType != null) { + var schemaAnnotation = type.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); + if (schemaAnnotation != null) { + schemaForType.setDescription(schemaAnnotation.description()); + } + } } private void processAsyncApiPayloadAnnotation(Map<String, Schema> schemas, String schemaName, Class<?> type) { @@ -161,9 +183,9 @@ public class DefaultComponentsService implements ComponentsService { } private String registerString() { - String schemaName = "String"; + String schemaName = getNameFromClass(String.class); StringSchema schema = new StringSchema(); - schema.setName(String.class.getName()); + schema.setName(schemaName); this.schemas.put(schemaName, schema); postProcessSchema(schema, DEFAULT_CONTENT_TYPE); @@ -181,6 +203,13 @@ public class DefaultComponentsService implements ComponentsService { return result; } + private String getNameFromClass(Class<?> type) { + if (properties.isUseFqn()) { + return type.getName(); + } + return type.getSimpleName(); + } + private void postProcessSchema(Schema schema, String contentType) { for (SchemasPostProcessor processor : schemaPostProcessors) { processor.process(schema, schemas, contentType); diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersBuilder.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersBuilder.java index 195fcb13..0496125f 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersBuilder.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersBuilder.java @@ -2,7 +2,8 @@ package io.github.springwolf.core.asyncapi.components.headers; import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; public interface AsyncHeadersBuilder { - SchemaObject buildHeaders(Class<?> payloadType); + SchemaObject buildHeaders(NamedSchemaObject payloadSchema); } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotDocumented.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotDocumented.java index b1548c4e..77b177bf 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotDocumented.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotDocumented.java @@ -2,6 +2,7 @@ package io.github.springwolf.core.asyncapi.components.headers; import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; import java.util.List; import java.util.Map; @@ -22,7 +23,7 @@ public class AsyncHeadersNotDocumented implements AsyncHeadersBuilder { } @Override - public SchemaObject buildHeaders(Class<?> payloadType) { + public SchemaObject buildHeaders(NamedSchemaObject payloadSchema) { return NOT_DOCUMENTED; } } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotUsed.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotUsed.java index 19ffed26..8b026f07 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotUsed.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/components/headers/AsyncHeadersNotUsed.java @@ -2,6 +2,7 @@ package io.github.springwolf.core.asyncapi.components.headers; import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; import java.util.List; import java.util.Map; @@ -21,7 +22,7 @@ public class AsyncHeadersNotUsed implements AsyncHeadersBuilder { } @Override - public SchemaObject buildHeaders(Class<?> payloadType) { + public SchemaObject buildHeaders(NamedSchemaObject payloadSchema) { return NOT_USED; } } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/AsyncAnnotationChannelsScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/AsyncAnnotationChannelsScanner.java index 253e1c7c..7c28ddab 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/AsyncAnnotationChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/AsyncAnnotationChannelsScanner.java @@ -15,6 +15,7 @@ import io.github.springwolf.core.asyncapi.scanners.bindings.operations.Operation import io.github.springwolf.core.asyncapi.scanners.classes.ClassScanner; import io.github.springwolf.core.asyncapi.scanners.common.AsyncAnnotationScanner; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AsyncAnnotationUtil; import io.github.springwolf.core.configuration.docket.AsyncApiDocketService; import lombok.extern.slf4j.Slf4j; @@ -36,11 +37,13 @@ public class AsyncAnnotationChannelsScanner<A extends Annotation> extends AsyncA ComponentsService componentsService, AsyncApiDocketService asyncApiDocketService, PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, List<OperationBindingProcessor> operationBindingProcessors, List<MessageBindingProcessor> messageBindingProcessors) { super( asyncAnnotationProvider, payloadClassExtractor, + payloadService, componentsService, operationBindingProcessors, messageBindingProcessors); diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScanner.java index d86fff29..22d88226 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScanner.java @@ -8,7 +8,7 @@ import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersBuilder; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; import io.github.springwolf.core.asyncapi.scanners.common.ClassLevelAnnotationScanner; -import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AnnotationScannerUtil; import lombok.extern.slf4j.Slf4j; @@ -30,14 +30,14 @@ public class SpringAnnotationClassLevelChannelsScanner< Class<MethodAnnotation> methodAnnotationClass, BindingFactory<ClassAnnotation> bindingFactory, AsyncHeadersBuilder asyncHeadersBuilder, - PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, ComponentsService componentsService) { super( classAnnotationClass, methodAnnotationClass, bindingFactory, asyncHeadersBuilder, - payloadClassExtractor, + payloadService, componentsService); } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationMethodLevelChannelsScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationMethodLevelChannelsScanner.java index c2942147..2321fa21 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationMethodLevelChannelsScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationMethodLevelChannelsScanner.java @@ -9,7 +9,8 @@ import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersBuilder; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; import io.github.springwolf.core.asyncapi.scanners.common.MethodLevelAnnotationScanner; -import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AnnotationScannerUtil; import lombok.extern.slf4j.Slf4j; @@ -25,17 +26,17 @@ public class SpringAnnotationMethodLevelChannelsScanner<MethodAnnotation extends extends MethodLevelAnnotationScanner<MethodAnnotation> implements SpringAnnotationChannelsScannerDelegator { private final Class<MethodAnnotation> methodAnnotationClass; - private final PayloadClassExtractor payloadClassExtractor; + private final PayloadService payloadService; public SpringAnnotationMethodLevelChannelsScanner( Class<MethodAnnotation> methodAnnotationClass, BindingFactory<MethodAnnotation> bindingFactory, AsyncHeadersBuilder asyncHeadersBuilder, - PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, ComponentsService componentsService) { super(bindingFactory, asyncHeadersBuilder, componentsService); this.methodAnnotationClass = methodAnnotationClass; - this.payloadClassExtractor = payloadClassExtractor; + this.payloadService = payloadService; } @Override @@ -56,16 +57,15 @@ public class SpringAnnotationMethodLevelChannelsScanner<MethodAnnotation extends MethodAnnotation annotation = AnnotationScannerUtil.findAnnotationOrThrow(methodAnnotationClass, method); + NamedSchemaObject payloadSchema = payloadService.extractSchema(method); + ChannelObject channelItem = buildChannelItem(annotation, payloadSchema); + String channelName = bindingFactory.getChannelName(annotation); - Class<?> payload = payloadClassExtractor.extractFrom(method); - - ChannelObject channelItem = buildChannelItem(annotation, payload); - return Map.entry(channelName, channelItem); } - private ChannelObject buildChannelItem(MethodAnnotation annotation, Class<?> payloadType) { - MessageObject message = buildMessage(annotation, payloadType); + private ChannelObject buildChannelItem(MethodAnnotation annotation, NamedSchemaObject payloadSchema) { + MessageObject message = buildMessage(annotation, payloadSchema); return buildChannelItem(annotation, message); } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/AsyncAnnotationScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/AsyncAnnotationScanner.java index 0dbba50d..48884d26 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/AsyncAnnotationScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/AsyncAnnotationScanner.java @@ -17,7 +17,9 @@ import io.github.springwolf.core.asyncapi.annotations.AsyncOperation; import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.scanners.bindings.messages.MessageBindingProcessor; import io.github.springwolf.core.asyncapi.scanners.bindings.operations.OperationBindingProcessor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AnnotationScannerUtil; import io.github.springwolf.core.asyncapi.scanners.common.utils.AsyncAnnotationUtil; import io.github.springwolf.core.asyncapi.scanners.common.utils.TextUtils; @@ -42,6 +44,7 @@ public abstract class AsyncAnnotationScanner<A extends Annotation> implements Em protected final AsyncAnnotationProvider<A> asyncAnnotationProvider; protected final PayloadClassExtractor payloadClassExtractor; + protected final PayloadService payloadService; protected final ComponentsService componentsService; protected final List<OperationBindingProcessor> operationBindingProcessors; protected final List<MessageBindingProcessor> messageBindingProcessors; @@ -89,30 +92,33 @@ public abstract class AsyncAnnotationScanner<A extends Annotation> implements Em } protected MessageObject buildMessage(AsyncOperation operationData, Method method) { - Class<?> payloadType = operationData.payloadType() != Object.class - ? operationData.payloadType() - : payloadClassExtractor.extractFrom(method); + NamedSchemaObject payloadSchema = payloadService.extractSchema(operationData, method); - String modelName = this.componentsService.registerSchema( - payloadType, operationData.message().contentType()); - SchemaObject asyncHeaders = AsyncAnnotationUtil.getAsyncHeaders(operationData, resolver); - String headerModelName = this.componentsService.registerSchema(asyncHeaders); - var headers = MessageHeaders.of(MessageReference.toSchema(headerModelName)); - - var schema = payloadType.getAnnotation(Schema.class); - String description = schema != null ? schema.description() : null; + // TODO: move block to own HeaderService + SchemaObject headerSchema = AsyncAnnotationUtil.getAsyncHeaders(operationData, resolver); + String headerSchemaName = this.componentsService.registerSchema(headerSchema); + var headers = MessageHeaders.of(MessageReference.toSchema(headerSchemaName)); Map<String, MessageBinding> messageBinding = AsyncAnnotationUtil.processMessageBindingFromAnnotation(method, messageBindingProcessors); var messagePayload = MessagePayload.of(MultiFormatSchema.builder() - .schema(SchemaReference.fromSchema(modelName)) + .schema(SchemaReference.fromSchema(payloadSchema.name())) .build()); + String description = operationData.message().description(); + if (!StringUtils.hasText(description)) { + description = payloadSchema.schema().getDescription(); + } + if (StringUtils.hasText(description)) { + description = this.resolver.resolveStringValue(description); + description = TextUtils.trimIndent(description); + } + var builder = MessageObject.builder() - .messageId(payloadType.getName()) - .name(payloadType.getName()) - .title(payloadType.getSimpleName()) + .messageId(payloadSchema.name()) + .name(payloadSchema.name()) + .title(payloadSchema.schema().getTitle()) .description(description) .payload(messagePayload) .headers(headers) diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/ClassLevelAnnotationScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/ClassLevelAnnotationScanner.java index f814e939..8a7f6507 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/ClassLevelAnnotationScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/ClassLevelAnnotationScanner.java @@ -11,7 +11,8 @@ import io.github.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersBuilder; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; -import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AnnotationScannerUtil; import io.github.springwolf.core.asyncapi.scanners.operations.annotations.SpringAnnotationClassLevelOperationsScanner; import lombok.RequiredArgsConstructor; @@ -37,7 +38,7 @@ public abstract class ClassLevelAnnotationScanner< protected final Class<MethodAnnotation> methodAnnotationClass; protected final BindingFactory<ClassAnnotation> bindingFactory; protected final AsyncHeadersBuilder asyncHeadersBuilder; - protected final PayloadClassExtractor payloadClassExtractor; + protected final PayloadService payloadService; protected final ComponentsService componentsService; protected enum MessageType { @@ -67,8 +68,8 @@ public abstract class ClassLevelAnnotationScanner< SpringAnnotationClassLevelOperationsScanner.MessageType messageType) { Set<MessageObject> messages = methods.stream() .map((Method method) -> { - Class<?> payloadType = payloadClassExtractor.extractFrom(method); - return buildMessage(classAnnotation, payloadType); + NamedSchemaObject payloadSchema = payloadService.extractSchema(method); + return buildMessage(classAnnotation, payloadSchema); }) .collect(toSet()); @@ -79,18 +80,19 @@ public abstract class ClassLevelAnnotationScanner< return toMessagesMap(messages); } - protected MessageObject buildMessage(ClassAnnotation classAnnotation, Class<?> payloadType) { + protected MessageObject buildMessage(ClassAnnotation classAnnotation, NamedSchemaObject payloadSchema) { Map<String, MessageBinding> messageBinding = bindingFactory.buildMessageBinding(classAnnotation); - String modelName = componentsService.registerSchema(payloadType); - String headerModelName = componentsService.registerSchema(asyncHeadersBuilder.buildHeaders(payloadType)); + + String headerModelName = componentsService.registerSchema(asyncHeadersBuilder.buildHeaders(payloadSchema)); + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() - .schema(SchemaReference.fromSchema(modelName)) + .schema(SchemaReference.fromSchema(payloadSchema.name())) .build()); MessageObject message = MessageObject.builder() - .messageId(payloadType.getName()) - .name(payloadType.getName()) - .title(payloadType.getSimpleName()) + .messageId(payloadSchema.name()) + .name(payloadSchema.name()) + .title(payloadSchema.schema().getTitle()) .description(null) .payload(payload) .headers(MessageHeaders.of(MessageReference.toSchema(headerModelName))) diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/MethodLevelAnnotationScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/MethodLevelAnnotationScanner.java index 1d548122..72f5e823 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/MethodLevelAnnotationScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/MethodLevelAnnotationScanner.java @@ -11,6 +11,7 @@ import io.github.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersBuilder; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,18 +26,20 @@ public abstract class MethodLevelAnnotationScanner<MethodAnnotation extends Anno protected final AsyncHeadersBuilder asyncHeadersBuilder; protected final ComponentsService componentsService; - protected MessageObject buildMessage(MethodAnnotation annotation, Class<?> payloadType) { + protected MessageObject buildMessage(MethodAnnotation annotation, NamedSchemaObject payloadSchema) { Map<String, MessageBinding> messageBinding = bindingFactory.buildMessageBinding(annotation); - String modelName = componentsService.registerSchema(payloadType); - String headerModelName = componentsService.registerSchema(asyncHeadersBuilder.buildHeaders(payloadType)); + + // TODO: move block to own HeaderService + String headerModelName = componentsService.registerSchema(asyncHeadersBuilder.buildHeaders(payloadSchema)); + MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder() - .schema(SchemaReference.fromSchema(modelName)) + .schema(SchemaReference.fromSchema(payloadSchema.name())) .build()); MessageObject message = MessageObject.builder() - .messageId(payloadType.getName()) - .name(payloadType.getName()) - .title(payloadType.getSimpleName()) + .messageId(payloadSchema.name()) + .name(payloadSchema.name()) + .title(payloadSchema.schema().getTitle()) .description(null) .payload(payload) .headers(MessageHeaders.of(MessageReference.toSchema(headerModelName))) diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/NamedSchemaObject.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/NamedSchemaObject.java new file mode 100644 index 00000000..9509becf --- /dev/null +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/NamedSchemaObject.java @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 +package io.github.springwolf.core.asyncapi.scanners.common.payload; + +import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject; + +/** + * Encapsulates the resolved name for the contained schema. + * @param name The fully qualified name or the simple name of the schema. + * @param schema The SchemaObject. + */ +public record NamedSchemaObject(String name, SchemaObject schema) {} diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadClassExtractor.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadClassExtractor.java index 0d19c5e6..9e80ef74 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadClassExtractor.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadClassExtractor.java @@ -1,52 +1,34 @@ // SPDX-License-Identifier: Apache-2.0 package io.github.springwolf.core.asyncapi.scanners.common.payload; -import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.messaging.handler.annotation.Payload; import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.Arrays; -import java.util.Map; +import java.util.Optional; +@RequiredArgsConstructor @Slf4j public class PayloadClassExtractor { private final TypeToClassConverter typeToClassConverter; - public PayloadClassExtractor(SpringwolfConfigProperties properties) { - Map<String, Integer> extractableClasses = Map.of(); - if (properties.getPayload() != null) { - extractableClasses = properties.getPayload().getExtractableClasses(); - } - typeToClassConverter = new TypeToClassConverter(extractableClasses); - } - - public Class<?> extractFrom(Method method) { + public Optional<Class<?>> extractFrom(Method method) { String methodName = String.format("%s::%s", method.getDeclaringClass().getSimpleName(), method.getName()); log.debug("Finding payload type for {}", methodName); - int parameterPayloadIndex = - getPayloadParameterIndex(method.getParameterTypes(), method.getParameterAnnotations(), methodName); - - return typeToClassConverter.extractClass(method.getGenericParameterTypes()[parameterPayloadIndex]); + return getPayloadParameterIndex(method.getParameterTypes(), method.getParameterAnnotations(), methodName) + .map((parameterPayloadIndex) -> + typeToClassConverter.extractClass(method.getGenericParameterTypes()[parameterPayloadIndex])); } - public Class<?> typeToClass(Type type) { - return typeToClassConverter.extractClass(type); - } - - private int getPayloadParameterIndex( + private Optional<Integer> getPayloadParameterIndex( Class<?>[] parameterClasses, Annotation[][] parameterAnnotations, String methodName) { - switch (parameterClasses.length) { - case 0 -> throw new IllegalArgumentException( - "Payload cannot be detected. Method must not have 0 parameters: " + methodName); - case 1 -> { - return 0; - } + return switch (parameterClasses.length) { + case 0 -> Optional.empty(); + case 1 -> Optional.of(0); default -> { int payloadAnnotatedParameterIndex = getPayloadAnnotatedParameterIndex(parameterAnnotations); if (payloadAnnotatedParameterIndex == -1) { @@ -57,9 +39,9 @@ public class PayloadClassExtractor { throw new IllegalArgumentException(msg); } - return payloadAnnotatedParameterIndex; + yield Optional.of(payloadAnnotatedParameterIndex); } - } + }; } private int getPayloadAnnotatedParameterIndex(Annotation[][] parameterAnnotations) { @@ -74,58 +56,4 @@ public class PayloadClassExtractor { return -1; } - - @RequiredArgsConstructor - private static class TypeToClassConverter { - - private final Map<String, Integer> extractableClassToArgumentIndex; - - private Class<?> extractClass(Type parameterType) { - try { - if (parameterType instanceof ParameterizedType) { - Type rawParameterType = ((ParameterizedType) parameterType).getRawType(); - String rawParameterTypeName = rawParameterType.getTypeName(); - - Class<?> actualPayloadClass = - extractActualGenericClass((ParameterizedType) parameterType, rawParameterTypeName); - if (actualPayloadClass != Void.class) { - return actualPayloadClass; - } - - // nested generic class - fallback to most outer container - return Class.forName(rawParameterTypeName); - } - - // no generics used - just a normal type - return Class.forName(parameterType.getTypeName()); - } catch (Exception ex) { - log.info("Unable to extract generic data type of {}", parameterType, ex); - } - return Void.class; - } - - private Class<?> extractActualGenericClass(ParameterizedType parameterType, String rawParameterTypeName) { - Type type = parameterType; - String typeName = rawParameterTypeName; - - while (type instanceof ParameterizedType && extractableClassToArgumentIndex.containsKey(typeName)) { - Integer index = extractableClassToArgumentIndex.get(rawParameterTypeName); - - type = ((ParameterizedType) type).getActualTypeArguments()[index]; - - typeName = type.getTypeName(); - if (type instanceof ParameterizedType) { - typeName = ((ParameterizedType) type).getRawType().getTypeName(); - } - } - - try { - return Class.forName(typeName); - } catch (ClassNotFoundException ex) { - log.debug("Unable to find class for type {}", typeName, ex); - } - - return Void.class; - } - } } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadService.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadService.java new file mode 100644 index 00000000..69342a90 --- /dev/null +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/PayloadService.java @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 +package io.github.springwolf.core.asyncapi.scanners.common.payload; + +import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject; +import io.github.springwolf.core.asyncapi.annotations.AsyncOperation; +import io.github.springwolf.core.asyncapi.components.ComponentsService; +import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@RequiredArgsConstructor +public class PayloadService { + private final PayloadClassExtractor payloadClassExtractor; + private final ComponentsService componentsService; + private final SpringwolfConfigProperties properties; + + private static final String PAYLOAD_NOT_USED_KEY = "PayloadNotUsed"; + static final NamedSchemaObject PAYLOAD_NOT_USED = new NamedSchemaObject( + PAYLOAD_NOT_USED_KEY, + SchemaObject.builder() + .title(PAYLOAD_NOT_USED_KEY) + .description("No payload specified") + .properties(Map.of()) + .build()); + + public NamedSchemaObject extractSchema(Method method) { + Optional<Class<?>> payloadType = payloadClassExtractor.extractFrom(method); + + String contentType = properties.getDocket().getDefaultContentType(); + return payloadType.map((type) -> buildSchema(contentType, type)).orElseGet(this::useUnusedPayload); + } + + public NamedSchemaObject extractSchema(AsyncOperation operationData, Method method) { + Optional<Class<?>> payloadType = operationData.payloadType() != Object.class + ? Optional.of(operationData.payloadType()) + : payloadClassExtractor.extractFrom(method); + + String contentType = operationData.message().contentType(); + return payloadType.map((type) -> buildSchema(contentType, type)).orElseGet(this::useUnusedPayload); + } + + private NamedSchemaObject buildSchema(String contentType, Class<?> payloadType) { + String componentsSchemaName = this.componentsService.registerSchema(payloadType, contentType); + + SchemaObject schema = componentsService.resolveSchema(componentsSchemaName); + schema.setTitle(payloadType.getSimpleName()); + + return new NamedSchemaObject(componentsSchemaName, schema); + } + + private NamedSchemaObject useUnusedPayload() { + this.componentsService.registerSchema(PAYLOAD_NOT_USED.schema()); + return PAYLOAD_NOT_USED; + } +} diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/TypeToClassConverter.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/TypeToClassConverter.java new file mode 100644 index 00000000..c55f8254 --- /dev/null +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/payload/TypeToClassConverter.java @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: Apache-2.0 +package io.github.springwolf.core.asyncapi.scanners.common.payload; + +import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Map; + +@Slf4j +public class TypeToClassConverter { + + private final Map<String, Integer> extractableClassToArgumentIndex; + + public TypeToClassConverter(SpringwolfConfigProperties properties) { + if (properties.getPayload() != null) { + extractableClassToArgumentIndex = properties.getPayload().getExtractableClasses(); + } else { + extractableClassToArgumentIndex = Map.of(); + } + } + + public Class<?> extractClass(Type parameterType) { + try { + if (parameterType instanceof ParameterizedType) { + Type rawParameterType = ((ParameterizedType) parameterType).getRawType(); + String rawParameterTypeName = rawParameterType.getTypeName(); + + Class<?> actualPayloadClass = + extractActualGenericClass((ParameterizedType) parameterType, rawParameterTypeName); + if (actualPayloadClass != Void.class) { + return actualPayloadClass; + } + + // nested generic class - fallback to most outer container + return Class.forName(rawParameterTypeName); + } + + // no generics used - just a normal type + return Class.forName(parameterType.getTypeName()); + } catch (Exception ex) { + log.info("Unable to extract generic data type of %s".formatted(parameterType), ex); + } + return Void.class; + } + + private Class<?> extractActualGenericClass(ParameterizedType parameterType, String rawParameterTypeName) { + Type type = parameterType; + String typeName = rawParameterTypeName; + + while (type instanceof ParameterizedType && extractableClassToArgumentIndex.containsKey(typeName)) { + Integer index = extractableClassToArgumentIndex.get(rawParameterTypeName); + + type = ((ParameterizedType) type).getActualTypeArguments()[index]; + + typeName = type.getTypeName(); + if (type instanceof ParameterizedType) { + typeName = ((ParameterizedType) type).getRawType().getTypeName(); + } + } + + try { + return Class.forName(typeName); + } catch (ClassNotFoundException ex) { + log.debug("Unable to find class for type %s".formatted(typeName), ex); + } + + return Void.class; + } +} diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/AsyncAnnotationOperationsScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/AsyncAnnotationOperationsScanner.java index 6cee589b..16ac6204 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/AsyncAnnotationOperationsScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/AsyncAnnotationOperationsScanner.java @@ -10,6 +10,7 @@ import io.github.springwolf.core.asyncapi.scanners.bindings.operations.Operation import io.github.springwolf.core.asyncapi.scanners.classes.ClassScanner; import io.github.springwolf.core.asyncapi.scanners.common.AsyncAnnotationScanner; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.operations.OperationMerger; import lombok.extern.slf4j.Slf4j; @@ -28,11 +29,13 @@ public class AsyncAnnotationOperationsScanner<A extends Annotation> extends Asyn ClassScanner classScanner, ComponentsService componentsService, PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, List<OperationBindingProcessor> operationBindingProcessors, List<MessageBindingProcessor> messageBindingProcessors) { super( asyncAnnotationProvider, payloadClassExtractor, + payloadService, componentsService, operationBindingProcessors, messageBindingProcessors); diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationClassLevelOperationsScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationClassLevelOperationsScanner.java index 74b0db0c..81166950 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationClassLevelOperationsScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationClassLevelOperationsScanner.java @@ -10,7 +10,7 @@ import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersBuilder; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; import io.github.springwolf.core.asyncapi.scanners.common.ClassLevelAnnotationScanner; -import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AnnotationScannerUtil; import lombok.extern.slf4j.Slf4j; @@ -32,14 +32,14 @@ public class SpringAnnotationClassLevelOperationsScanner< Class<MethodAnnotation> methodAnnotationClass, BindingFactory<ClassAnnotation> bindingFactory, AsyncHeadersBuilder asyncHeadersBuilder, - PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, ComponentsService componentsService) { super( classAnnotationClass, methodAnnotationClass, bindingFactory, asyncHeadersBuilder, - payloadClassExtractor, + payloadService, componentsService); } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationMethodLevelOperationsScanner.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationMethodLevelOperationsScanner.java index e222893f..ac5448ac 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationMethodLevelOperationsScanner.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/operations/annotations/SpringAnnotationMethodLevelOperationsScanner.java @@ -11,7 +11,8 @@ import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersBuilder; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; import io.github.springwolf.core.asyncapi.scanners.common.MethodLevelAnnotationScanner; -import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.common.utils.AnnotationScannerUtil; import lombok.extern.slf4j.Slf4j; @@ -28,17 +29,17 @@ public class SpringAnnotationMethodLevelOperationsScanner<MethodAnnotation exten extends MethodLevelAnnotationScanner<MethodAnnotation> implements SpringAnnotationOperationsScannerDelegator { private final Class<MethodAnnotation> methodAnnotationClass; - private final PayloadClassExtractor payloadClassExtractor; + private final PayloadService payloadService; public SpringAnnotationMethodLevelOperationsScanner( Class<MethodAnnotation> methodAnnotationClass, BindingFactory<MethodAnnotation> bindingFactory, AsyncHeadersBuilder asyncHeadersBuilder, - PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, ComponentsService componentsService) { super(bindingFactory, asyncHeadersBuilder, componentsService); this.methodAnnotationClass = methodAnnotationClass; - this.payloadClassExtractor = payloadClassExtractor; + this.payloadService = payloadService; } @Override @@ -61,13 +62,13 @@ public class SpringAnnotationMethodLevelOperationsScanner<MethodAnnotation exten String channelName = bindingFactory.getChannelName(annotation); String operationId = channelName + "_" + OperationAction.RECEIVE + "_" + method.getName(); - Class<?> payload = payloadClassExtractor.extractFrom(method); + NamedSchemaObject payloadSchema = payloadService.extractSchema(method); - Operation operation = buildOperation(annotation, payload); + Operation operation = buildOperation(annotation, payloadSchema); return Map.entry(operationId, operation); } - private Operation buildOperation(MethodAnnotation annotation, Class<?> payloadType) { + private Operation buildOperation(MethodAnnotation annotation, NamedSchemaObject payloadType) { MessageObject message = buildMessage(annotation, payloadType); return buildOperation(annotation, message); } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfAutoConfiguration.java b/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfAutoConfiguration.java index b8284b26..2851142c 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfAutoConfiguration.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfAutoConfiguration.java @@ -28,6 +28,8 @@ import io.github.springwolf.core.asyncapi.operations.OperationsService; import io.github.springwolf.core.asyncapi.scanners.ChannelsScanner; import io.github.springwolf.core.asyncapi.scanners.OperationsScanner; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; +import io.github.springwolf.core.asyncapi.scanners.common.payload.TypeToClassConverter; import io.github.springwolf.core.configuration.docket.AsyncApiDocketService; import io.github.springwolf.core.configuration.docket.DefaultAsyncApiDocketService; import io.github.springwolf.core.configuration.properties.SpringwolfConfigConstants; @@ -161,7 +163,22 @@ public class SpringwolfAutoConfiguration { @Bean @ConditionalOnMissingBean - public PayloadClassExtractor payloadClassExtractor(SpringwolfConfigProperties springwolfConfigProperties) { - return new PayloadClassExtractor(springwolfConfigProperties); + public TypeToClassConverter typeToClassConverter(SpringwolfConfigProperties springwolfConfigProperties) { + return new TypeToClassConverter(springwolfConfigProperties); + } + + @Bean + @ConditionalOnMissingBean + public PayloadClassExtractor payloadClassExtractor(TypeToClassConverter typeToClassConverter) { + return new PayloadClassExtractor(typeToClassConverter); + } + + @Bean + @ConditionalOnMissingBean + public PayloadService payloadService( + PayloadClassExtractor payloadClassExtractor, + ComponentsService componentsService, + SpringwolfConfigProperties properties) { + return new PayloadService(payloadClassExtractor, componentsService, properties); } } diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfScannerConfiguration.java b/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfScannerConfiguration.java index a0c9e7d8..ab416da7 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfScannerConfiguration.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/configuration/SpringwolfScannerConfiguration.java @@ -17,6 +17,7 @@ import io.github.springwolf.core.asyncapi.scanners.classes.spring.ComponentClass import io.github.springwolf.core.asyncapi.scanners.classes.spring.ConfigurationClassScanner; import io.github.springwolf.core.asyncapi.scanners.common.AsyncAnnotationScanner; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import io.github.springwolf.core.asyncapi.scanners.operations.annotations.AsyncAnnotationOperationsScanner; import io.github.springwolf.core.configuration.docket.AsyncApiDocketService; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -74,6 +75,7 @@ public class SpringwolfScannerConfiguration { ComponentsService componentsService, AsyncApiDocketService asyncApiDocketService, PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, List<OperationBindingProcessor> operationBindingProcessors, List<MessageBindingProcessor> messageBindingProcessors) { return new AsyncAnnotationChannelsScanner<>( @@ -82,6 +84,7 @@ public class SpringwolfScannerConfiguration { componentsService, asyncApiDocketService, payloadClassExtractor, + payloadService, operationBindingProcessors, messageBindingProcessors); } @@ -96,6 +99,7 @@ public class SpringwolfScannerConfiguration { SpringwolfClassScanner springwolfClassScanner, ComponentsService componentsService, PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, List<OperationBindingProcessor> operationBindingProcessors, List<MessageBindingProcessor> messageBindingProcessors) { return new AsyncAnnotationOperationsScanner<>( @@ -103,6 +107,7 @@ public class SpringwolfScannerConfiguration { springwolfClassScanner, componentsService, payloadClassExtractor, + payloadService, operationBindingProcessors, messageBindingProcessors); } @@ -118,6 +123,7 @@ public class SpringwolfScannerConfiguration { ComponentsService componentsService, AsyncApiDocketService asyncApiDocketService, PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, List<OperationBindingProcessor> operationBindingProcessors, List<MessageBindingProcessor> messageBindingProcessors) { return new AsyncAnnotationChannelsScanner<>( @@ -126,6 +132,7 @@ public class SpringwolfScannerConfiguration { componentsService, asyncApiDocketService, payloadClassExtractor, + payloadService, operationBindingProcessors, messageBindingProcessors); } @@ -140,6 +147,7 @@ public class SpringwolfScannerConfiguration { SpringwolfClassScanner springwolfClassScanner, ComponentsService componentsService, PayloadClassExtractor payloadClassExtractor, + PayloadService payloadService, List<OperationBindingProcessor> operationBindingProcessors, List<MessageBindingProcessor> messageBindingProcessors) { return new AsyncAnnotationOperationsScanner<>( @@ -147,6 +155,7 @@ public class SpringwolfScannerConfiguration { springwolfClassScanner, componentsService, payloadClassExtractor, + payloadService, operationBindingProcessors, messageBindingProcessors); } diff --git a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/AsyncAnnotationChannelsScannerTest.java b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/AsyncAnnotationChannelsScannerTest.java index 39b2002d..7e4bdb5c 100644 --- a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/AsyncAnnotationChannelsScannerTest.java +++ b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/AsyncAnnotationChannelsScannerTest.java @@ -28,6 +28,8 @@ import io.github.springwolf.core.asyncapi.scanners.channels.AsyncAnnotationChann import io.github.springwolf.core.asyncapi.scanners.classes.ClassScanner; import io.github.springwolf.core.asyncapi.scanners.common.AsyncAnnotationScanner; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; +import io.github.springwolf.core.asyncapi.scanners.common.payload.TypeToClassConverter; import io.github.springwolf.core.configuration.docket.AsyncApiDocket; import io.github.springwolf.core.configuration.docket.AsyncApiDocketService; import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties; @@ -85,7 +87,10 @@ class AsyncAnnotationChannelsScannerTest { new DefaultComponentsService(emptyList(), emptyList(), swaggerSchemaUtil, properties); private final AsyncApiDocketService asyncApiDocketService = mock(AsyncApiDocketService.class); - private final PayloadClassExtractor payloadClassExtractor = new PayloadClassExtractor(properties); + private final TypeToClassConverter typeToClassConverter = new TypeToClassConverter(properties); + private final PayloadClassExtractor payloadClassExtractor = new PayloadClassExtractor(typeToClassConverter); + private final PayloadService payloadService = + new PayloadService(payloadClassExtractor, componentsService, properties); private final List<OperationBindingProcessor> operationBindingProcessors = List.of(new TestOperationBindingProcessor()); @@ -99,6 +104,7 @@ class AsyncAnnotationChannelsScannerTest { componentsService, asyncApiDocketService, payloadClassExtractor, + payloadService, operationBindingProcessors, messageBindingProcessors); diff --git a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerIntegrationTest.java b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerIntegrationTest.java index 11e2dec6..3671c992 100644 --- a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerIntegrationTest.java +++ b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerIntegrationTest.java @@ -20,6 +20,8 @@ import io.github.springwolf.core.asyncapi.components.examples.walkers.json.Examp import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersNotDocumented; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; +import io.github.springwolf.core.asyncapi.scanners.common.payload.TypeToClassConverter; import io.github.springwolf.core.configuration.properties.SpringwolfConfigProperties; import lombok.Data; import lombok.EqualsAndHashCode; @@ -48,7 +50,9 @@ import static org.assertj.core.api.Assertions.assertThat; SpringAnnotationClassLevelChannelsScannerIntegrationTest.TestBindingFactory.class, DefaultComponentsService.class, SwaggerSchemaUtil.class, + PayloadService.class, PayloadClassExtractor.class, + TypeToClassConverter.class, DefaultSchemaWalker.class, SchemaWalkerProvider.class, ExampleJsonValueGenerator.class, @@ -60,7 +64,7 @@ class SpringAnnotationClassLevelChannelsScannerIntegrationTest { BindingFactory<TestClassListener> bindingFactory; @Autowired - PayloadClassExtractor payloadClassExtractor; + PayloadService payloadService; @Autowired ComponentsService componentsService; @@ -74,7 +78,7 @@ class SpringAnnotationClassLevelChannelsScannerIntegrationTest { TestMethodListener.class, this.bindingFactory, new AsyncHeadersNotDocumented(), - payloadClassExtractor, + payloadService, componentsService); } diff --git a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerTest.java b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerTest.java index 9f0ba78b..601cf424 100644 --- a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerTest.java +++ b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/channels/annotations/SpringAnnotationClassLevelChannelsScannerTest.java @@ -18,7 +18,8 @@ import io.github.springwolf.asyncapi.v3.model.schema.SchemaReference; import io.github.springwolf.core.asyncapi.components.ComponentsService; import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersNotDocumented; import io.github.springwolf.core.asyncapi.scanners.bindings.BindingFactory; -import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadClassExtractor; +import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject; +import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService; import lombok.Data; import lombok.NoArgsConstructor; import org.junit.jupiter.api.BeforeEach; @@ -38,7 +39,7 @@ import static org.mockito.Mockito.when; class SpringAnnotationClassLevelChannelsScannerTest { - private final PayloadClassExtractor payloadClassExtractor = mock(PayloadClassExtractor.class); + pri…
Co-authored-by: David Müller <[email protected]>
timonback
force-pushed
the
feat/handle-no-payload
branch
from
April 19, 2024 17:02
1c406fb
to
a281c70
Compare
Co-authored-by: David Müller <[email protected]>
Co-authored-by: Timon Back <[email protected]>
sam0r040
commented
Apr 23, 2024
...ngwolf/addons/common_model_converters/converters/monetaryamount/MonetaryAmountConverter.java
Outdated
Show resolved
Hide resolved
sam0r040
commented
Apr 23, 2024
...re/src/main/java/io/github/springwolf/core/asyncapi/components/DefaultComponentsService.java
Show resolved
Hide resolved
sam0r040
commented
Apr 23, 2024
...re/src/main/java/io/github/springwolf/core/asyncapi/components/DefaultComponentsService.java
Outdated
Show resolved
Hide resolved
…r to make clearer what happens before and after proceeding the chain
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
resolves: GH-665