Consumers
Springwolf comes with build-in support to auto-detect listeners of supported protocols.
Sometimes projects are configured in a way that makes Springwolf unable to automatically locate consumers or the generated documentation is insufficient. For these use-cases, Springwolf provides additional ways to explicitly add them to the generated document.
To document consumers, either:
- add the
@AsyncListenerannotation or - declare the
ConsumerDataobject as part of theAsyncApiDocketor - rely on the auto-detection of
@KafkaListener,@RabbitListener
You are free to use all options together. Per channel and operation, first ConsumerData is used, then @AsyncListener and last the auto-detected annotations.
Option 1: @AsyncListener
The @AsyncListener annotation is added to the method of the listeners and extracts the payload from its arguments.
Additional fields can be documented.
The protocol operation binding is configured via @AmqpAsyncOperationBinding or @KafkaAsyncOperationBinding, which has to be on the same method.
Below is an example to demonstrate the annotation:
@KafkaListener
@AsyncListener(operation = @AsyncOperation(
channelName = "example-consumer-topic",
description = "Optional. Customer uploaded an example payload",
headers = @AsyncOperation.Headers(
schemaName = "SpringKafkaDefaultHeaders",
values = {
@AsyncOperation.Headers.Header(
name = DEFAULT_CLASSID_FIELD_NAME,
description = "Spring Type Id Header",
value = "io.github.stavshamir.springwolf.example.dtos.ExamplePayloadDto"
),
}
)
))
@KafkaAsyncOperationBinding
public void receiveMessage(ExamplePayloadDto msg) {
// process
}
Springwolf only finds methods that are within the base-package.
Channel Name
The channel name (or topic name in case of Kafka) - this is the name that will be used to subscribe to messages to by the UI.
Description
Optional. The description allows for human-friendly text to verbosely explain the message, like specific domain, what the topic is used for and which data it contains.
Payload Type
The class object of the payload that will be consumed from this channel. If not specified, it is extracted from the method arguments.
Header
Optional. The headers describing the metadata of the payload.
@AmqpAsyncOperationBinding
Associate this operation with amqp, see operation-binding for details.
@AmqpAsyncOperationBinding(cc = "example-topic-routing-key")
@KafkaAsyncOperationBinding
Associate this operation with kafka, see operation-binding for details.
@KafkaAsyncOperationBinding(
bindingVersion = "1",
clientId = "foo-clientId",
groupId = "#{'foo-groupId'}"
)
Option 2: ConsumerData
Use specific ConsumerData types AmqpConsumerData & KafkaConsumerData for protocol specific attributes
Below is an example of describing a Kafka consumer:
@Bean
public AsyncApiDocket asyncApiDocket() {
ConsumerData exampleConsumerData = ConsumerData.builder()
.channelName("example-consumer-topic")
.description("Optional. Customer uploaded an example payload")
.operationBinding(ImmutableMap.of("kafka", new KafkaOperationBinding()))
.payloadType(ExamplePayloadDto.class)
.headers(AsyncHeaders.NOT_USED)
.build();
return AsyncApiDocket.builder()
.basePackage(...)
.info(...)
.server(...)
.consumer(exampleConsumerData)
.build();
}
Multiple consumers can be configured by calling the consumer() method multiple times.
Channel Name
The channel name (or topic name in case of Kafka) - this is the name that will be used to subscribe to messages to by the UI.
Description
Optional. The description allows for human-friendly text to verbosely explain the message, like specific domain, what the topic is used for and which data it contains.
Binding
This property is used to discriminate the producer's protocol and provide protocol-specific properties (see operation-binding)).
Payload Type
The class object of the payload that will be consumed from this channel.
Header
Optional. The headers describing the metadata of the payload.
By default, AsyncHeaders.NOT_DOCUMENTED is used to indicate that no explicit header documentation exists.
Use AsyncHeaders to add your custom headers, use AsyncHeaders.NOT_USED if you do not use headers and AsyncHeadersForCloudEventsBuilder if your events follow the CloudEvent specification.
AmqpConsumerData
The above Kafka ConsumerData equivalent in AmqpConsumerData:
AmqpConsumerData exampleConsumer = AmqpConsumerData.amqpConsumerDataBuilder()
.queueName("example-consumer-channel")
.description("example-consumer-channel-description")
.exchangeName("example-topic-exchange")
.routingKey("example-topic-routing-key")
.payloadType(AnotherPayloadDto.class)
.build();
KafkaConsumerData
The above Kafka ConsumerData simplifies to the following KafkaConsumerData:
KafkaConsumerData exampleConsumerData = KafkaConsumerData.kafkaConsumerDataBuilder()
.topicName("example-consumer-topic")
.description("Optional. Customer uploaded an example payload")
.payloadType(ExamplePayloadDto.class)
.headers(AsyncHeaders.NOT_USED)
.build();
Option 3: @KafkaListener, @RabbitListener
The @KafkaListener and @RabbitListener annotations are detected automatically.
There is nothing more to do.
Use the other options if the provided documentation is insufficient.
AMQP Parameters
Queue Name (Channel Name)
The queue name that will be used to consume messages from.
Description
Optional. The description allows for human-friendly text to verbosely explain the message, like specific domain, what the topic is used for and which data it contains.
Exchange Name
The exchange name that will be used to bind queues to.
Routing Key
The routing key used when publishing a message.
Payload Type
The class object of the payload that will be consumed from this channel.
Kafka Parameters
Topic Name (Channel Name)
The topic name that will be used to consume messages from.
Description
Optional. The description allows for human-friendly text to verbosely explain the message, like specific domain, what the topic is used for and which data it contains.
Payload Type
The class object of the payload that will be consumed from this channel.
Headers
The Kafka headers describing the metadata of the payload, more details in the generic ConsumerData.
The Springwolf Kafka plugin comes with a special AsyncHeadersForSpringKafkaBuilder to document the __TypeId__ header of the spring-kafka dependency.