Skip to content

Commit

Permalink
Refactor/resolve header service todos (#725)
Browse files Browse the repository at this point in the history
* refactor: resolve header schema in PayloadService

* refactor: move headers package to scanners

* refactor: fix usage in cloud-stream
  • Loading branch information
timonback committed May 3, 2024
1 parent b4b293b commit 9e7a4be
Show file tree
Hide file tree
Showing 37 changed files with 156 additions and 94 deletions.
Expand Up @@ -16,8 +16,6 @@ public interface ComponentsService {

String registerSchema(SchemaObject headers);

String registerSchema(Class<?> type);

String registerSchema(Class<?> type, String contentType);

Map<String, Message> getMessages();
Expand Down
Expand Up @@ -89,12 +89,6 @@ public String registerSchema(SchemaObject headers) {
return headers.getTitle();
}

@Override
public String registerSchema(Class<?> type) {
// FIXME: Move this to the new HeadersService
return this.registerSchema(type, properties.getDocket().getDefaultContentType());
}

@Override
public String registerSchema(Class<?> type, String contentType) {
log.debug("Registering schema for {}", type.getSimpleName());
Expand Down
Expand Up @@ -5,9 +5,9 @@
import io.github.springwolf.asyncapi.v3.model.channel.ChannelObject;
import io.github.springwolf.asyncapi.v3.model.channel.message.MessageReference;
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.headers.AsyncHeadersBuilder;
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;
Expand Down
Expand Up @@ -6,9 +6,9 @@
import io.github.springwolf.asyncapi.v3.model.channel.message.MessageObject;
import io.github.springwolf.asyncapi.v3.model.channel.message.MessageReference;
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.headers.AsyncHeadersBuilder;
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;
Expand Down
Expand Up @@ -94,10 +94,8 @@ protected Operation buildOperation(AsyncOperation asyncOperation, Method method,
protected MessageObject buildMessage(AsyncOperation operationData, Method method) {
NamedSchemaObject payloadSchema = payloadService.extractSchema(operationData, method);

// 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);
Expand All @@ -121,7 +119,7 @@ protected MessageObject buildMessage(AsyncOperation operationData, Method method
.title(payloadSchema.schema().getTitle())
.description(description)
.payload(messagePayload)
.headers(headers)
.headers(MessageHeaders.of(MessageReference.toSchema(headerSchemaName)))
.bindings(messageBinding);

// Retrieve the Message information obtained from the @AsyncMessage annotation. These values have higher
Expand Down
Expand Up @@ -7,10 +7,11 @@
import io.github.springwolf.asyncapi.v3.model.channel.message.MessagePayload;
import io.github.springwolf.asyncapi.v3.model.channel.message.MessageReference;
import io.github.springwolf.asyncapi.v3.model.schema.MultiFormatSchema;
import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject;
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.headers.AsyncHeadersBuilder;
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;
Expand Down Expand Up @@ -83,7 +84,8 @@ protected Map<String, MessageReference> buildMessages(
protected MessageObject buildMessage(ClassAnnotation classAnnotation, NamedSchemaObject payloadSchema) {
Map<String, MessageBinding> messageBinding = bindingFactory.buildMessageBinding(classAnnotation);

String headerModelName = componentsService.registerSchema(asyncHeadersBuilder.buildHeaders(payloadSchema));
SchemaObject headerSchema = asyncHeadersBuilder.buildHeaders(payloadSchema);
String headerSchemaName = componentsService.registerSchema(headerSchema);

MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder()
.schema(SchemaReference.fromSchema(payloadSchema.name()))
Expand All @@ -95,7 +97,7 @@ protected MessageObject buildMessage(ClassAnnotation classAnnotation, NamedSchem
.title(payloadSchema.schema().getTitle())
.description(null)
.payload(payload)
.headers(MessageHeaders.of(MessageReference.toSchema(headerModelName)))
.headers(MessageHeaders.of(MessageReference.toSchema(headerSchemaName)))
.bindings(messageBinding)
.build();

Expand Down
Expand Up @@ -7,10 +7,11 @@
import io.github.springwolf.asyncapi.v3.model.channel.message.MessagePayload;
import io.github.springwolf.asyncapi.v3.model.channel.message.MessageReference;
import io.github.springwolf.asyncapi.v3.model.schema.MultiFormatSchema;
import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject;
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.headers.AsyncHeadersBuilder;
import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -29,8 +30,8 @@ public abstract class MethodLevelAnnotationScanner<MethodAnnotation extends Anno
protected MessageObject buildMessage(MethodAnnotation annotation, NamedSchemaObject payloadSchema) {
Map<String, MessageBinding> messageBinding = bindingFactory.buildMessageBinding(annotation);

// TODO: move block to own HeaderService
String headerModelName = componentsService.registerSchema(asyncHeadersBuilder.buildHeaders(payloadSchema));
SchemaObject headerSchema = asyncHeadersBuilder.buildHeaders(payloadSchema);
String headerModelName = componentsService.registerSchema(headerSchema);

MessagePayload payload = MessagePayload.of(MultiFormatSchema.builder()
.schema(SchemaReference.fromSchema(payloadSchema.name()))
Expand Down
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.asyncapi.components.headers;
package io.github.springwolf.core.asyncapi.scanners.common.headers;

import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject;
import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject;
Expand Down
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.asyncapi.components.headers;
package io.github.springwolf.core.asyncapi.scanners.common.headers;

public class AsyncHeadersCloudEventConstants {
public static final String CONTENT_TYPE = "content-type";
Expand Down
@@ -1,26 +1,22 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.asyncapi.components.headers;
package io.github.springwolf.core.asyncapi.scanners.common.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;

public class AsyncHeadersNotDocumented implements AsyncHeadersBuilder {
/**
* Per default, if no headers are explicitly defined, {@link AsyncHeadersNotUsed#NOT_USED} is used.
* There can be headers, but don't have to be.
*/
public static final SchemaObject NOT_DOCUMENTED = new SchemaObject();

static {
NOT_DOCUMENTED.setType("object");
NOT_DOCUMENTED.setTitle("HeadersNotDocumented");
NOT_DOCUMENTED.setDescription("There can be headers, but they are not explicitly documented.");
NOT_DOCUMENTED.setProperties(Map.of());
NOT_DOCUMENTED.setExamples(List.of(new Object()));
}
public static final SchemaObject NOT_DOCUMENTED = SchemaObject.builder()
.type("object")
.title("HeadersNotDocumented")
.description("There can be headers, but they are not explicitly documented.")
.properties(Map.of())
.build();

@Override
public SchemaObject buildHeaders(NamedSchemaObject payloadSchema) {
Expand Down
@@ -1,25 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.springwolf.core.asyncapi.components.headers;
package io.github.springwolf.core.asyncapi.scanners.common.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;

public class AsyncHeadersNotUsed implements AsyncHeadersBuilder {
/**
* Explicitly document that no headers are used.
*/
public static final SchemaObject NOT_USED = new SchemaObject();

static {
NOT_USED.setType("object");
NOT_USED.setTitle("HeadersNotUsed");
NOT_USED.setDescription("No headers are present.");
NOT_USED.setProperties(Map.of());
NOT_USED.setExamples(List.of(new Object()));
}
public static final SchemaObject NOT_USED = SchemaObject.builder()
.type("object")
.title("HeadersNotUsed")
.description("No headers are present.")
.properties(Map.of())
.build();

@Override
public SchemaObject buildHeaders(NamedSchemaObject payloadSchema) {
Expand Down
Expand Up @@ -31,8 +31,7 @@ public class PayloadService {
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);
return payloadType.map(this::buildSchema).orElseGet(this::useUnusedPayload);
}

public NamedSchemaObject extractSchema(AsyncOperation operationData, Method method) {
Expand All @@ -41,9 +40,16 @@ public NamedSchemaObject extractSchema(AsyncOperation operationData, Method meth
: payloadClassExtractor.extractFrom(method);

String contentType = operationData.message().contentType();

return payloadType.map((type) -> buildSchema(contentType, type)).orElseGet(this::useUnusedPayload);
}

private NamedSchemaObject buildSchema(Class<?> payloadType) {
String contentType = properties.getDocket().getDefaultContentType();

return buildSchema(contentType, payloadType);
}

private NamedSchemaObject buildSchema(String contentType, Class<?> payloadType) {
String componentsSchemaName = this.componentsService.registerSchema(payloadType, contentType);

Expand All @@ -53,6 +59,12 @@ private NamedSchemaObject buildSchema(String contentType, Class<?> payloadType)
return new NamedSchemaObject(componentsSchemaName, schema);
}

public String extractSchemaForName(Class<?> payloadType) {
String contentType = properties.getDocket().getDefaultContentType();

return this.componentsService.registerSchema(payloadType, contentType);
}

private NamedSchemaObject useUnusedPayload() {
this.componentsService.registerSchema(PAYLOAD_NOT_USED.schema());
return PAYLOAD_NOT_USED;
Expand Down
Expand Up @@ -8,14 +8,14 @@
import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject;
import io.github.springwolf.core.asyncapi.annotations.AsyncMessage;
import io.github.springwolf.core.asyncapi.annotations.AsyncOperation;
import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersNotDocumented;
import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersNotUsed;
import io.github.springwolf.core.asyncapi.scanners.bindings.channels.ChannelBindingProcessor;
import io.github.springwolf.core.asyncapi.scanners.bindings.channels.ProcessedChannelBinding;
import io.github.springwolf.core.asyncapi.scanners.bindings.messages.MessageBindingProcessor;
import io.github.springwolf.core.asyncapi.scanners.bindings.messages.ProcessedMessageBinding;
import io.github.springwolf.core.asyncapi.scanners.bindings.operations.OperationBindingProcessor;
import io.github.springwolf.core.asyncapi.scanners.bindings.operations.ProcessedOperationBinding;
import io.github.springwolf.core.asyncapi.scanners.common.headers.AsyncHeadersNotDocumented;
import io.github.springwolf.core.asyncapi.scanners.common.headers.AsyncHeadersNotUsed;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;

Expand Down
Expand Up @@ -7,9 +7,9 @@
import io.github.springwolf.asyncapi.v3.model.operation.Operation;
import io.github.springwolf.asyncapi.v3.model.operation.OperationAction;
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.headers.AsyncHeadersBuilder;
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;
Expand Down
Expand Up @@ -8,9 +8,9 @@
import io.github.springwolf.asyncapi.v3.model.operation.Operation;
import io.github.springwolf.asyncapi.v3.model.operation.OperationAction;
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.headers.AsyncHeadersBuilder;
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;
Expand Down
Expand Up @@ -20,13 +20,13 @@
import io.github.springwolf.core.asyncapi.components.ComponentsService;
import io.github.springwolf.core.asyncapi.components.DefaultComponentsService;
import io.github.springwolf.core.asyncapi.components.SwaggerSchemaUtil;
import io.github.springwolf.core.asyncapi.components.headers.AsyncHeadersNotDocumented;
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.bindings.processor.TestOperationBindingProcessor;
import io.github.springwolf.core.asyncapi.scanners.channels.AsyncAnnotationChannelsScanner;
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.headers.AsyncHeadersNotDocumented;
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;
Expand Down
Expand Up @@ -17,8 +17,8 @@
import io.github.springwolf.core.asyncapi.components.examples.SchemaWalkerProvider;
import io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker;
import io.github.springwolf.core.asyncapi.components.examples.walkers.json.ExampleJsonValueGenerator;
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.headers.AsyncHeadersNotDocumented;
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;
Expand Down
Expand Up @@ -16,8 +16,8 @@
import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject;
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.headers.AsyncHeadersNotDocumented;
import io.github.springwolf.core.asyncapi.scanners.common.payload.NamedSchemaObject;
import io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadService;
import lombok.Data;
Expand Down Expand Up @@ -70,9 +70,6 @@ void setUp() {

when(payloadService.extractSchema(any()))
.thenReturn(new NamedSchemaObject(String.class.getName(), new SchemaObject()));
doAnswer(invocation -> invocation.<Class<?>>getArgument(0).getSimpleName())
.when(componentsService)
.registerSchema(any(Class.class));
doAnswer(invocation -> AsyncHeadersNotDocumented.NOT_DOCUMENTED.getTitle())
.when(componentsService)
.registerSchema(any(SchemaObject.class));
Expand Down
Expand Up @@ -17,8 +17,8 @@
import io.github.springwolf.core.asyncapi.components.examples.SchemaWalkerProvider;
import io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker;
import io.github.springwolf.core.asyncapi.components.examples.walkers.json.ExampleJsonValueGenerator;
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.headers.AsyncHeadersNotDocumented;
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;
Expand Down

0 comments on commit 9e7a4be

Please sign in to comment.