Skip to content

Commit

Permalink
feat(core): autogenerate name for header schema if not set already GH…
Browse files Browse the repository at this point in the history
…-893 (#940)

Co-authored-by: Timon Back <[email protected]>
  • Loading branch information
sam0r040 and timonback authored Aug 23, 2024
1 parent 8607feb commit 60414e0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,15 @@ public static SchemaObject getAsyncHeaders(AsyncOperation op, StringValueResolve
}
return AsyncHeadersNotDocumented.NOT_DOCUMENTED;
}
if (!StringUtils.hasText(headers.schemaName())) {
throw new IllegalArgumentException("The schemaName in @AsyncOperation.Headers must be set for values: "
+ Arrays.toString(headers.values()));
}

String headerSchemaTitle =
StringUtils.hasText(headers.schemaName()) ? headers.schemaName() : generateHeadersSchemaName(headers);
String headerDescription =
StringUtils.hasText(headers.description()) ? resolver.resolveStringValue(headers.description()) : null;

SchemaObject headerSchema = new SchemaObject();
headerSchema.setType(SchemaType.OBJECT);
headerSchema.setTitle(headers.schemaName());
headerSchema.setTitle(headerSchemaTitle);
headerSchema.setDescription(headerDescription);
headerSchema.setProperties(new HashMap<>());

Expand Down Expand Up @@ -95,6 +93,10 @@ private static String getDescription(List<AsyncOperation.Headers.Header> value,
.orElse(null);
}

private static String generateHeadersSchemaName(AsyncOperation.Headers headers) {
return "Headers-" + Math.abs(headers.hashCode());
}

public static Map<String, OperationBinding> processOperationBindingFromAnnotation(
Method method, List<OperationBindingProcessor> operationBindingProcessors) {
return operationBindingProcessors.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.github.springwolf.asyncapi.v3.bindings.OperationBinding;
import io.github.springwolf.asyncapi.v3.model.channel.message.MessageObject;
import io.github.springwolf.asyncapi.v3.model.schema.SchemaObject;
import io.github.springwolf.asyncapi.v3.model.schema.SchemaType;
import io.github.springwolf.core.asyncapi.annotations.AsyncListener;
import io.github.springwolf.core.asyncapi.annotations.AsyncMessage;
import io.github.springwolf.core.asyncapi.annotations.AsyncOperation;
Expand All @@ -25,7 +26,6 @@
import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
Expand Down Expand Up @@ -99,10 +99,45 @@ void getAsyncHeadersWithoutSchemaName() throws NoSuchMethodException {
when(resolver.resolveStringValue(any()))
.thenAnswer(invocation -> invocation.getArgument(0).toString() + "Resolved");

// when + then
assertThatIllegalArgumentException()
.isThrownBy(() -> AsyncAnnotationUtil.getAsyncHeaders(operation, resolver))
.withMessageContaining("The schemaName in @AsyncOperation.Headers must be set for values");
// when
SchemaObject headers = AsyncAnnotationUtil.getAsyncHeaders(operation, resolver);

// then
assertThat(headers)
.isEqualTo(SchemaObject.builder()
.type(SchemaType.OBJECT)
.title("Headers-501004016")
.properties(Map.of(
"headerResolved",
SchemaObject.builder()
.type(SchemaType.STRING)
.title("headerResolved")
.description("descriptionResolved")
.enumValues(List.of("valueResolved"))
.examples(List.of("valueResolved"))
.build()))
.build());
}

@Test
void generatedHeaderSchemaNameShouldBeUnique() throws NoSuchMethodException {
// given
Method m1 = ClassWithHeaders.class.getDeclaredMethod("withoutSchemaName", String.class);
AsyncOperation operation1 = m1.getAnnotation(AsyncListener.class).operation();

Method m2 = ClassWithHeaders.class.getDeclaredMethod("differentHeadersWithoutSchemaName", String.class);
AsyncOperation operation2 = m2.getAnnotation(AsyncListener.class).operation();

StringValueResolver resolver = mock(StringValueResolver.class);
when(resolver.resolveStringValue(any()))
.thenAnswer(invocation -> invocation.getArgument(0).toString() + "Resolved");

// when
SchemaObject headers1 = AsyncAnnotationUtil.getAsyncHeaders(operation1, resolver);
SchemaObject headers2 = AsyncAnnotationUtil.getAsyncHeaders(operation2, resolver);

// then
assertThat(headers1.getTitle()).isNotEqualTo(headers2.getTitle());
}

@Test
Expand Down Expand Up @@ -362,6 +397,18 @@ private void emptyHeaders(String payload) {}
})))
@TestOperationBindingProcessor.TestOperationBinding()
private void withoutSchemaName(String payload) {}

@AsyncListener(
operation =
@AsyncOperation(
channelName = "${test.property.test-channel}",
headers =
@AsyncOperation.Headers(
values = {
@AsyncOperation.Headers.Header(name = "header", value = "value")
})))
@TestOperationBindingProcessor.TestOperationBinding()
private void differentHeadersWithoutSchemaName(String payload) {}
}

private static class ClassWithMultipleOperationBindingProcessors {
Expand Down

0 comments on commit 60414e0

Please sign in to comment.