Headers
Springwolf provides different ways to document headers. The header
is mapped to an AsyncAPI schemaObject
.
Auto-detection
Besides the payload, Springwolf detects the Spring @Header
annotation within the method signature:
@KafkaListener(topics = "example-topic")
public void receiveExamplePayload(
@Payload ExamplePayloadDto payload, // @Payload is required for multiple parameters
@Header(KafkaHeaders.RECEIVED_KEY) String key,
@Header(KafkaHeaders.OFFSET) Integer offset) {
// process
}
Using @AsyncOperation.Headers
Again, the annotation property headers
of @AsyncOperation
allows to overwrite the headers, as shown below:
@AsyncPublisher(operation = @AsyncOperation(
channelName = "example-producer-topic",
headers = @AsyncOperation.Headers( // Optional
schemaName = "SpringKafkaDefaultHeaders",
values = {
@AsyncOperation.Headers.Header(
name = DEFAULT_CLASSID_FIELD_NAME,
description = "Spring Type Id Header",
value = "io.github.springwolf.example.dtos.ExamplePayloadDto"
),
// demonstrating https://cloudevents.io
@AsyncOperation.Headers.Header(
name = AsyncHeadersCloudEventConstants.TYPE,
description = AsyncHeadersCloudEventConstants.TYPE_DESC,
value = "ExamplePayloadDto.v1")
// ...
}
)
))
public void sendMessage(ExamplePayloadDto msg) {
// process
}
Schema
Under the hood Springwolf relies on swagger-core ModelConverters
to define the message schema.
By default, the type and example values for the properties are guessed.
The default Jackson ModelResolver
supports schema definitions via @Schema
to overwrite the property definitions.
Using @Schema
The @Schema
annotation allows to set many properties like description
, example
, requiredMode
, minimum
to document payloads.
All properties are part of the produced AsyncAPI file. However, not all are displayed in springwolf-ui
(see #378)
Usage
Add the following dependency:
- Groovy
- Maven
dependencies {
implementation 'io.swagger.core.v3:swagger-core:2.2.22'
}
<dependencies>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core</artifactId>
<version>2.2.22</version>
</dependency>
</dependencies>
Then, add the @Schema
annotation to the payload class:
import io.swagger.v3.oas.annotations.media.Schema;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Schema(description = "Example payload model")
public class ExamplePayloadDto {
@Schema(description = "Some string field", example = "some string value", requiredMode = REQUIRED)
private String someString;
public String getSomeString() {
return someString;
}
}
The @AsyncMessage.description
field will always override the @Schema
description if provided
For a full example, take a look at ExamplePayloadDto.java in springwolf-amqp-example
Primitive, final and external classes
When the @Schema
annotation can't be attached to the payload class (that's java.lang.String
), the payload can be wrapped in an envelope class. The actual payload is a field within this class (StringEnvelope
), marked using @AsyncApiPayload
and documented using the @Schema
annotation.
@AsyncListener( operation = @AsyncOperation( channelName = TOPIC,
payloadType = StringEnvelope.class) // <- envelope class
)
public void receiveStringPayload(String stringPayload) { // <- The original class is used here
// ...
}
@Data
static class StringEnvelope {
@AsyncApiPayload // <- The annotation marker
@Schema(description = "Payload description using @Schema annotation and @AsyncApiPayload within envelope class")
private final String payload;
}
See Add-Ons for more information on how to document other formats