From 37a24c871c5faea594980e5ad458fe84459f6f6a Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 21 Jun 2024 13:50:46 +0200 Subject: [PATCH 1/9] Update documentation for actuator --- docs/configuration/configuration.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/configuration.mdx b/docs/configuration/configuration.mdx index b209262..0e96499 100644 --- a/docs/configuration/configuration.mdx +++ b/docs/configuration/configuration.mdx @@ -84,7 +84,7 @@ The following table contains additional properties that can be specified in the ## Actuator support Springwolf supports exposing the AsyncAPI document as part of Spring Boot’s actuator endpoint. -The AsyncAPI document will then be moved underneath actuators base path, that's `/actuator/springwolf/docs.json` or `/actuator/springwolf/docs.yaml` respectively. +The AsyncAPI document will then be moved underneath actuators base path, that's `/actuator/springwolf`. To enable it, add the `spring-boot-actuator` dependency first. Second, enable the actuator endpoint in the `application.properties` file: From f16ac2fd8b85aa5f8532d58c887ba54ba939cd8d Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 15:39:10 +0200 Subject: [PATCH 2/9] docs: update to 1.4.0 --- .../_springwolf_common_model_converters_groovy.gradle | 2 +- docs/snippets/_springwolf_common_model_converters_maven.xml | 2 +- docs/snippets/_springwolf_generic_binding_groovy.gradle | 2 +- docs/snippets/_springwolf_generic_binding_maven.xml | 2 +- docs/snippets/_springwolf_groovy.gradle | 4 ++-- docs/snippets/_springwolf_json_schema_groovy.gradle | 2 +- docs/snippets/_springwolf_json_schema_maven.xml | 2 +- ...ngwolf_kotlinx_serialization_model_converter_groovy.gradle | 2 +- ...springwolf_kotlinx_serialization_model_converter_maven.xml | 2 +- docs/snippets/_springwolf_maven.xml | 4 ++-- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/snippets/_springwolf_common_model_converters_groovy.gradle b/docs/snippets/_springwolf_common_model_converters_groovy.gradle index ce68ac2..ef2183e 100644 --- a/docs/snippets/_springwolf_common_model_converters_groovy.gradle +++ b/docs/snippets/_springwolf_common_model_converters_groovy.gradle @@ -1,3 +1,3 @@ dependencies { - implementation 'io.github.springwolf:springwolf-common-model-converters:1.3.0' + implementation 'io.github.springwolf:springwolf-common-model-converters:1.4.0' } diff --git a/docs/snippets/_springwolf_common_model_converters_maven.xml b/docs/snippets/_springwolf_common_model_converters_maven.xml index 863158e..1b53d14 100644 --- a/docs/snippets/_springwolf_common_model_converters_maven.xml +++ b/docs/snippets/_springwolf_common_model_converters_maven.xml @@ -2,6 +2,6 @@ io.github.springwolf springwolf-common-model-converters - 1.3.0 + 1.4.0 diff --git a/docs/snippets/_springwolf_generic_binding_groovy.gradle b/docs/snippets/_springwolf_generic_binding_groovy.gradle index b3da602..b66d625 100644 --- a/docs/snippets/_springwolf_generic_binding_groovy.gradle +++ b/docs/snippets/_springwolf_generic_binding_groovy.gradle @@ -1,3 +1,3 @@ dependencies { - implementation 'io.github.springwolf:springwolf-generic-binding:1.3.0' + implementation 'io.github.springwolf:springwolf-generic-binding:1.4.0' } diff --git a/docs/snippets/_springwolf_generic_binding_maven.xml b/docs/snippets/_springwolf_generic_binding_maven.xml index b260a83..ce95684 100644 --- a/docs/snippets/_springwolf_generic_binding_maven.xml +++ b/docs/snippets/_springwolf_generic_binding_maven.xml @@ -2,6 +2,6 @@ io.github.springwolf springwolf-generic-binding - 1.3.0 + 1.4.0 diff --git a/docs/snippets/_springwolf_groovy.gradle b/docs/snippets/_springwolf_groovy.gradle index fbdd2c1..b58380b 100644 --- a/docs/snippets/_springwolf_groovy.gradle +++ b/docs/snippets/_springwolf_groovy.gradle @@ -1,7 +1,7 @@ dependencies { // Provides the documentation API - implementation 'io.github.springwolf:springwolf-kafka:1.3.0' + implementation 'io.github.springwolf:springwolf-kafka:1.4.0' // Provides the UI - optional (recommended) - runtimeOnly 'io.github.springwolf:springwolf-ui:1.3.0' + runtimeOnly 'io.github.springwolf:springwolf-ui:1.4.0' } diff --git a/docs/snippets/_springwolf_json_schema_groovy.gradle b/docs/snippets/_springwolf_json_schema_groovy.gradle index 904df2c..d286ad9 100644 --- a/docs/snippets/_springwolf_json_schema_groovy.gradle +++ b/docs/snippets/_springwolf_json_schema_groovy.gradle @@ -1,3 +1,3 @@ dependencies { - implementation 'io.github.springwolf:springwolf-json-schema:1.3.0' + implementation 'io.github.springwolf:springwolf-json-schema:1.4.0' } diff --git a/docs/snippets/_springwolf_json_schema_maven.xml b/docs/snippets/_springwolf_json_schema_maven.xml index 05e60f2..1c112ee 100644 --- a/docs/snippets/_springwolf_json_schema_maven.xml +++ b/docs/snippets/_springwolf_json_schema_maven.xml @@ -2,6 +2,6 @@ io.github.springwolf springwolf-json-schema - 1.3.0 + 1.4.0 diff --git a/docs/snippets/_springwolf_kotlinx_serialization_model_converter_groovy.gradle b/docs/snippets/_springwolf_kotlinx_serialization_model_converter_groovy.gradle index dcbd5d7..ee5b45d 100644 --- a/docs/snippets/_springwolf_kotlinx_serialization_model_converter_groovy.gradle +++ b/docs/snippets/_springwolf_kotlinx_serialization_model_converter_groovy.gradle @@ -1,3 +1,3 @@ dependencies { - implementation 'io.github.springwolf:springwolf-kotlinx-serialization-model-converter:1.3.0' + implementation 'io.github.springwolf:springwolf-kotlinx-serialization-model-converter:1.4.0' } diff --git a/docs/snippets/_springwolf_kotlinx_serialization_model_converter_maven.xml b/docs/snippets/_springwolf_kotlinx_serialization_model_converter_maven.xml index 31c3d72..fe76628 100644 --- a/docs/snippets/_springwolf_kotlinx_serialization_model_converter_maven.xml +++ b/docs/snippets/_springwolf_kotlinx_serialization_model_converter_maven.xml @@ -2,6 +2,6 @@ io.github.springwolf springwolf-kotlinx-serialization-model-converter - 1.3.0 + 1.4.0 diff --git a/docs/snippets/_springwolf_maven.xml b/docs/snippets/_springwolf_maven.xml index 94563ce..daea306 100644 --- a/docs/snippets/_springwolf_maven.xml +++ b/docs/snippets/_springwolf_maven.xml @@ -3,12 +3,12 @@ io.github.springwolf springwolf-kafka - 1.3.0 + 1.4.0 io.github.springwolf springwolf-ui - 1.3.0 + 1.4.0 From 9294d05dc3c508b213df5e006b26217d60c129a9 Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 16:14:15 +0200 Subject: [PATCH 3/9] docs: document stomp binding and plugin --- .../config/vocabularies/Springwolf/accept.txt | 1 + docs/behind-the-scenes.md | 2 +- docs/configuration/configuration.mdx | 56 ++++++++++--------- docs/configuration/customizing.md | 6 ++ docs/configuration/documenting-bindings.md | 12 +++- docs/configuration/documenting-consumers.md | 2 +- docs/introduction/introduction.md | 5 +- docs/introduction/supported-protocols.md | 35 ++++++------ 8 files changed, 71 insertions(+), 48 deletions(-) diff --git a/.github/styles/config/vocabularies/Springwolf/accept.txt b/.github/styles/config/vocabularies/Springwolf/accept.txt index d4286bc..cfa0764 100644 --- a/.github/styles/config/vocabularies/Springwolf/accept.txt +++ b/.github/styles/config/vocabularies/Springwolf/accept.txt @@ -12,4 +12,5 @@ Kotlinx Protobuf Springfox Springwolf +STOMP UI \ No newline at end of file diff --git a/docs/behind-the-scenes.md b/docs/behind-the-scenes.md index f310886..9a62843 100644 --- a/docs/behind-the-scenes.md +++ b/docs/behind-the-scenes.md @@ -20,7 +20,7 @@ From there, Springwolf forwards the message to the protocol specific producer. ## Plugins `springwolf-core` provides the base functionality to orchestrate the scanning and building of the AsyncAPI document. -The different protocol (AMQP, Cloud-Stream, JMS, Kafka, SNS, SQS) are supported through plugins. +The different protocol (AMQP, Cloud-Stream, JMS, Kafka, SNS, SQS, STOMP/WebSocket) are supported through plugins. These plugins are found through the Spring dependency injection functionality. When building own scanner plugins, your plugin will need to implement the `ChannelsScanner` interface. diff --git a/docs/configuration/configuration.mdx b/docs/configuration/configuration.mdx index 0e96499..cd11aa7 100644 --- a/docs/configuration/configuration.mdx +++ b/docs/configuration/configuration.mdx @@ -15,7 +15,7 @@ Add the following to the spring `application.properties` file: It's recommended to structure the project such that all consumers and producers (classes containing listener/producer methods) are in the same package - it's not mandatory, and if they're scattered across multiple packages, just provide the highest in hierarchy package that contains all classes. -The `base-package` will be scanned for classes containing `@Component` annotated classes (that includes `@Service` annotated classes) for methods annotated with `@JmsListener`, `@KafkaListener`, `@RabbitListener`, `@SqsListener`, `@AsyncListener`, `@AsyncPublisher`, etc. +The `base-package` will be scanned for classes containing `@Component` annotated classes (that includes `@Service` annotated classes) for methods annotated with `@JmsListener`, `@KafkaListener`, `MessageMapping`, `@RabbitListener`, `@SqsListener`, `@AsyncListener`, `@AsyncPublisher`, etc. `@Configuration` classes are scanned for `@Bean` containing the previously mentioned annotations as well. ### `Info` (required) @@ -55,31 +55,35 @@ Every custom extension field must begin with `x-`, for example `x-internal-id` ( The following table contains additional properties that can be specified in the `application.properties` file: -| Property Name | Default Value | Description | -|----------------------------------------------------------|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `springwolf.enabled` | `true` | Allows to enable/disable Springwolf at one central place. | -| `springwolf.init-mode` | `fail_fast` | Springwolf initializes during start up with `fail_fast` or in the `background` after the application has started. | -| `springwolf.paths.docs` | `/springwolf/docs` | The path of the AsyncAPI document in JSON format. *Note that at the moment the UI will work only with the default value.* | -| `springwolf.endpoint.actuator.enabled` | `false` | Publish the AsyncAPI document as part of Spring Boot’s actuator feature. | -| `springwolf.use-fqn` | `true` | Use fully qualified names for the schema classes. **Required for publishing with `springwolf-ui`** | -| `springwolf.payload.extractable-classes..` | N/A | Extract additional payload types. See [message payloads](documenting-messages.mdx) for more details. | -| `springwolf.scanner.async-listener.enabled` | `true` | Enable scanner to find methods annotated with `@AsyncListener`. | -| `springwolf.scanner.async-publisher.enabled` | `true` | Enable scanner to find methods annotated with `@AsyncPublisher`. | -| **AMQP** | | | -| `springwolf.plugin.amqp.publishing.enabled` | `false` | Allow (anyone) to produce AMQP messages from the UI. *Note that this has security implications* | -| `springwolf.plugin.amqp.scanner.rabbit-listener.enabled` | `true` | Enable scanner to find methods annotated with `@RabbitListener`. | -| **JMS** | | | -| `springwolf.plugin.jms.publishing.enabled` | `false` | Allow (anyone) to produce JMS messages from the UI. *Note that this has security implications* | -| `springwolf.plugin.jms.scanner.jms-listener.enabled` | `true` | Enable scanner to find methods annotated with `@JmsListener`. | -| **Kafka** | | | -| `springwolf.plugin.kafka.publishing.enabled` | `false` | Allow (anyone) to produce Kafka messages from the UI. *Note that this has security implications* | -| `springwolf.plugin.kafka.publishing.producer` | `null` | Configure the Kafka producer used to publish messages from the UI. Uses identical parameters as `spring.kafka.producer`. [SpringwolfKafkaProducer](https://github.com/springwolf/springwolf-core/blob/master/springwolf-examples/springwolf-kafka-example/src/main/java/io/github/springwolf/examples/kafka/configuration/CustomSpringwolfKafkaProducer.java#L20) demonstrates multiple producer configuration to publish to Avro and Protobuf. | -| `springwolf.plugin.kafka.scanner.kafka-listener.enabled` | `true` | Enable scanner to find methods annotated with `@KafkaListener`. | -| **SNS** | | | -| `springwolf.plugin.sns.publishing.enabled` | `false` | Allow (anyone) to produce SNS messages from the UI. *Note that this has security implications* | -| **SQS** | | | -| `springwolf.plugin.sqs.publishing.enabled` | `false` | Allow (anyone) to produce SQS messages from the UI. *Note that this has security implications* | -| `springwolf.plugin.sqs.scanner.sqs-listener.enabled` | `true` | Enable scanner to find methods annotated with `@SqsListener`. | +| Property Name | Default Value | Description | +|-----------------------------------------------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `springwolf.enabled` | `true` | Allows to enable/disable Springwolf at one central place. | +| `springwolf.init-mode` | `fail_fast` | Springwolf initializes during start up with `fail_fast` or in the `background` after the application has started. | +| `springwolf.paths.docs` | `/springwolf/docs` | The path of the AsyncAPI document in JSON format. *Note that at the moment the UI will work only with the default value.* | +| `springwolf.endpoint.actuator.enabled` | `false` | Publish the AsyncAPI document as part of Spring Boot’s actuator feature. | +| `springwolf.use-fqn` | `true` | Use fully qualified names for the schema classes. **Required for publishing with `springwolf-ui`** | +| `springwolf.payload.extractable-classes..` | N/A | Extract additional payload types. See [message payloads](documenting-messages.mdx) for more details. | +| `springwolf.scanner.async-listener.enabled` | `true` | Enable scanner to find methods annotated with `@AsyncListener`. | +| `springwolf.scanner.async-publisher.enabled` | `true` | Enable scanner to find methods annotated with `@AsyncPublisher`. | +| **AMQP** | | | +| `springwolf.plugin.amqp.publishing.enabled` | `false` | Allow (anyone) to produce AMQP messages from the UI. *Note that this has security implications* | +| `springwolf.plugin.amqp.scanner.rabbit-listener.enabled` | `true` | Enable scanner to find methods annotated with `@RabbitListener`. | +| **JMS** | | | +| `springwolf.plugin.jms.publishing.enabled` | `false` | Allow (anyone) to produce JMS messages from the UI. *Note that this has security implications* | +| `springwolf.plugin.jms.scanner.jms-listener.enabled` | `true` | Enable scanner to find methods annotated with `@JmsListener`. | +| **Kafka** | | | +| `springwolf.plugin.kafka.publishing.enabled` | `false` | Allow (anyone) to produce Kafka messages from the UI. *Note that this has security implications* | +| `springwolf.plugin.kafka.publishing.producer` | `null` | Configure the Kafka producer used to publish messages from the UI. Uses identical parameters as `spring.kafka.producer`. [SpringwolfKafkaProducer](https://github.com/springwolf/springwolf-core/blob/master/springwolf-examples/springwolf-kafka-example/src/main/java/io/github/springwolf/examples/kafka/configuration/CustomSpringwolfKafkaProducer.java#L20) demonstrates multiple producer configuration to publish to Avro and Protobuf. | +| `springwolf.plugin.kafka.scanner.kafka-listener.enabled` | `true` | Enable scanner to find methods annotated with `@KafkaListener`. | +| **SNS** | | | +| `springwolf.plugin.sns.publishing.enabled` | `false` | Allow (anyone) to produce SNS messages from the UI. *Note that this has security implications* | +| **SQS** | | | +| `springwolf.plugin.sqs.publishing.enabled` | `false` | Allow (anyone) to produce SQS messages from the UI. *Note that this has security implications* | +| `springwolf.plugin.sqs.scanner.sqs-listener.enabled` | `true` | Enable scanner to find methods annotated with `@SqsListener`. | +| **STOMP (WebSocket)** | | | +| `springwolf.plugin.stomp.scanner.stomp-message-mapping.enabled` | `true` | Enable scanner to find methods annotated with `@MessageMapping`. | +| `springwolf.plugin.stomp.scanner.stomp-send-to.enabled` | `true` | Enable scanner to find methods annotated with `@SendTo`. | +| `springwolf.plugin.stomp.scanner.stomp-send-to-user.enabled` | `true` | Enable scanner to find methods annotated with `@SendToUser`. | ## Actuator support diff --git a/docs/configuration/customizing.md b/docs/configuration/customizing.md index bcc96e4..17ebf30 100644 --- a/docs/configuration/customizing.md +++ b/docs/configuration/customizing.md @@ -38,6 +38,12 @@ public class AsyncApiTitleCustomizer implements AsyncApiCustomizer { } ``` +## ObjectMapper in `DefaultAsyncApiSerializerService` + +The `DefaultAsyncApiSerializerService` is responsible for serializing the AsyncAPI document into a `String` for the Controller. + +Use `DefaultAsyncApiSerializerService#getJsonObjectMapper()` and `DefaultAsyncApiSerializerService#getYamlObjectMapper()` to customize the `ObjectMapper`. + ## `ChannelScanners` - Channel detection All `ChannelScanner` beans are called to scan for channels. diff --git a/docs/configuration/documenting-bindings.md b/docs/configuration/documenting-bindings.md index 6d729f7..4253ef9 100644 --- a/docs/configuration/documenting-bindings.md +++ b/docs/configuration/documenting-bindings.md @@ -53,6 +53,14 @@ Associate this operation with SQS, see [operation-binding] for details. @SqsAsyncOperationBinding ``` +### `@StompAsyncOperationBinding` + +Associate this operation with STOMP (WebSocket), see [operation-binding] for details. + +```java +@StompAsyncOperationBinding +``` + ## Generic annotation This binding is generic, so that any properties can be specified. @@ -123,7 +131,7 @@ The group id that will be used during message consumption The client id to identify the consumer -### Google PubSub binding annotations +### Google PubSub #### Channel Binding Object @@ -148,7 +156,7 @@ The Channel Bindings Object is used to describe the Google Cloud Pub/Sub Topic d - A list of IDs of GCP regions where messages that are published to the topic may be persisted in storage -`Schema Settings`:The Schema Settings Object is used to describe the Google Cloud Pub/Sub SchemaSettings. +`Schema Settings`: The Schema Settings Object is used to describe the Google Cloud Pub/Sub SchemaSettings. - encoding: The encoding of the message - firstRevisionId: The minimum (inclusive) revision allowed for validating messages diff --git a/docs/configuration/documenting-consumers.md b/docs/configuration/documenting-consumers.md index f181d3b..e45a1c8 100644 --- a/docs/configuration/documenting-consumers.md +++ b/docs/configuration/documenting-consumers.md @@ -12,7 +12,7 @@ For these use-cases, Springwolf provides additional ways to explicitly add them To document consumers, either: - add the `@AsyncListener` annotation or -- rely on the auto-detection of `@JmsListener`, `@KafkaListener`, `@RabbitListener`, `@SqsListener` +- rely on the auto-detection of `@JmsListener`, `@KafkaListener`, `@MessageMapping`, `@RabbitListener`, `@SqsListener`, `@SendTo`, `@SendToUser` You are free to use both options together. Channel and operation, documented via `@AsyncListener` have a higher precedence than auto-detected annotations. diff --git a/docs/introduction/introduction.md b/docs/introduction/introduction.md index fc961be..19ca6a7 100644 --- a/docs/introduction/introduction.md +++ b/docs/introduction/introduction.md @@ -13,7 +13,7 @@ Integrate Springwolf in minutes using the [Quickstart](../quickstart.mdx). API Documentation is an important part of every project and product, but can be painful to maintain manually. Spring Boot projects have great solutions for auto-generated documentation for REST APIs to overcome this pain (such as Springfox, or springdoc-openapi). -However, until now there were no solutions for asynchronous APIs (such as AMQP, JMS, Kafka, SNS, SQS, etc.). Springwolf aims to solve this and provides auto-generated documentation for asynchronous APIs built in Spring Boot. +However, until now there were no solutions for asynchronous APIs (such as AMQP, JMS, Kafka, SNS, SQS, STOMP/WebSocket, etc.). Springwolf aims to solve this and provides auto-generated documentation for asynchronous APIs built in Spring Boot. Springwolf is compliant to [AsyncAPI](https://www.asyncapi.com), which brings the [swagger/OpenAPI](https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi) specification you know already from REST APIs into the world of event-driven architectures. @@ -27,7 +27,8 @@ Also, the demos of the [JMS](https://jms.demo.springwolf.dev), [Kafka](https://kafka.demo.springwolf.dev), [SNS](https://sns.demo.springwolf.dev), -[SQS](https://sqs.demo.springwolf.dev) +[SQS](https://sqs.demo.springwolf.dev), +[STOMP (WebSocket)](https://stomp.demo.springwolf.dev) example projects are available. ![Springwolf publishing demo](/img/demo.gif) diff --git a/docs/introduction/supported-protocols.md b/docs/introduction/supported-protocols.md index 4e34c5e..bbeab0b 100644 --- a/docs/introduction/supported-protocols.md +++ b/docs/introduction/supported-protocols.md @@ -11,14 +11,15 @@ any protocol can be defined using Springwolf custom annotations `@AsyncListener` The following protocols are supported natively: -| Protocol | Auto-detected annotations | Example Project | Latest Plugin Version | -|-----------------|-----------------------------------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| -| AMQP (RabbitMQ) | `@RabbitListener` | [`springwolf-amqp-example`][amqp] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-amqp?color=green&label=springwolf-amqp&style=plastic) | -| Cloud Functions | `@Bean` (functional interface) | [`springwolf-cloud-stream`][cloud-stream] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-cloud-stream?color=green&label=springwolf-cloud-stream&style=plastic) | -| JMS | `@JmsListener` | [`springwolf-jms-example`][jms] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-jms?color=green&label=springwolf-jms&style=plastic) | -| Kafka | `@KafkaListener`, `@KafkaHandler` | [`springwolf-kafka-example`][kafka] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-kafka?color=green&label=springwolf-kafka&style=plastic) | -| SNS | | [`springwolf-sns-example`][sns] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sns?color=green&label=springwolf-sns&style=plastic) | -| SQS | `@SqsListener` | [`springwolf-sqs-example`][sqs] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sqs?color=green&label=springwolf-sqs&style=plastic) | +| Protocol | Auto-detected annotations | Example Project | Latest Plugin Version | +|-------------------|---------------------------------------------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| AMQP (RabbitMQ) | `@RabbitListener` | [`springwolf-amqp-example`][amqp] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-amqp?color=green&label=springwolf-amqp&style=plastic) | +| Cloud Functions | `@Bean` (functional interface) | [`springwolf-cloud-stream`][cloud-stream] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-cloud-stream?color=green&label=springwolf-cloud-stream&style=plastic) | +| JMS | `@JmsListener` | [`springwolf-jms-example`][jms] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-jms?color=green&label=springwolf-jms&style=plastic) | +| Kafka | `@KafkaListener`, `@KafkaHandler` | [`springwolf-kafka-example`][kafka] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-kafka?color=green&label=springwolf-kafka&style=plastic) | +| SNS | | [`springwolf-sns-example`][sns] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sns?color=green&label=springwolf-sns&style=plastic) | +| SQS | `@SqsListener` | [`springwolf-sqs-example`][sqs] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sqs?color=green&label=springwolf-sqs&style=plastic) | +| STOMP (WebSocket) | `@MessageMapping`, `@SendTo`, `@SendToUser` | [`springwolf-stomp-example`][stomp] | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-stomp?color=green&label=springwolf-stomp&style=plastic) | Check out the example projects, which include a full `docker-compose` setup. The examples are simple, easy to start with, good for testing and reproducing bugs. @@ -37,14 +38,15 @@ Springwolf also provides some libraries to document bindings. Those libraries pr The supported binding annotations are: -| Protocol | Annotations | Latest Plugin Version | -|--------------|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| AMQP | `@AmqpAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-amqp-binding?color=green&label=springwolf-amqp-binding&style=plastic) | -| GooglePubSub | `@GooglePubSubAsyncChannelBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-googlepubsub-binding?color=green&label=springwolf-googlepubsub-binding&style=plastic) | -| JMS | `@JmsAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-jms-binding?color=green&label=springwolf-jms-binding&style=plastic) | -| Kafka | `@KafkaAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-kafka-binding?color=green&label=springwolf-kafka-binding&style=plastic) | -| SNS | `@SnsAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sns-binding?color=green&label=springwolf-sns-binding&style=plastic) | -| SQS | `@SqsAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sqs-binding?color=green&label=springwolf-sqs-binding&style=plastic) | +| Protocol | Annotations | Latest Plugin Version | +|-------------------|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| AMQP | `@AmqpAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-amqp-binding?color=green&label=springwolf-amqp-binding&style=plastic) | +| GooglePubSub | `@GooglePubSubAsyncChannelBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-googlepubsub-binding?color=green&label=springwolf-googlepubsub-binding&style=plastic) | +| JMS | `@JmsAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-jms-binding?color=green&label=springwolf-jms-binding&style=plastic) | +| Kafka | `@KafkaAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-kafka-binding?color=green&label=springwolf-kafka-binding&style=plastic) | +| SNS | `@SnsAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sns-binding?color=green&label=springwolf-sns-binding&style=plastic) | +| SQS | `@SqsAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-sqs-binding?color=green&label=springwolf-sqs-binding&style=plastic) | +| STOMP (WebSocket) | `@StompAsyncOperationBinding` | ![Maven Central](https://img.shields.io/maven-central/v/io.github.springwolf/springwolf-stomp-binding?color=green&label=springwolf-stomp-binding&style=plastic) | :::info See [Add-Ons / Generic Annotation Binding](../add-ons#generic-binding) @@ -56,3 +58,4 @@ See [Add-Ons / Generic Annotation Binding](../add-ons#generic-binding) [kafka]: https://github.com/springwolf/springwolf-core/tree/master/springwolf-examples/springwolf-kafka-example [sns]: https://github.com/springwolf/springwolf-core/tree/master/springwolf-examples/springwolf-sns-example [sqs]: https://github.com/springwolf/springwolf-core/tree/master/springwolf-examples/springwolf-sqs-example +[stomp]: https://github.com/springwolf/springwolf-core/tree/master/springwolf-examples/springwolf-stomp-example From a2d884bd86fa50a886d73b4b93765b6ab24eedaa Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 16:14:24 +0200 Subject: [PATCH 4/9] chore: add lint command --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e9d2179..5ea1f58 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "deploy": "docusaurus deploy", "clear": "docusaurus clear", "serve": "docusaurus serve", + "lint": "vale docs/ && npm run lint:md && npm run lint:mdx", "lint:md": "markdownlint --config conf/.markdownlint.json --ignore node_modules/ \"./docs/**/*.md\"", "lint:md:fix": "markdownlint --config conf/.markdownlint.json --fix --ignore node_modules/ \"./docs/**/*.md\"", "lint:mdx": "markdownlint --config conf/.mdx.markdownlint.json --ignore node_modules/ \"./docs/**/*.mdx\"", From 4d618a8fd18d5834c7a8e20f568eee8bcaba16ae Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 16:28:37 +0200 Subject: [PATCH 5/9] docs: update swagger version --- docs/configuration/snippets/_schema_groovy.gradle | 2 +- docs/configuration/snippets/_schema_maven.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configuration/snippets/_schema_groovy.gradle b/docs/configuration/snippets/_schema_groovy.gradle index adf4f81..6d5d0d1 100644 --- a/docs/configuration/snippets/_schema_groovy.gradle +++ b/docs/configuration/snippets/_schema_groovy.gradle @@ -1,3 +1,3 @@ dependencies { - implementation 'io.swagger.core.v3:swagger-core:2.2.20' + implementation 'io.swagger.core.v3:swagger-core:2.2.22' } \ No newline at end of file diff --git a/docs/configuration/snippets/_schema_maven.xml b/docs/configuration/snippets/_schema_maven.xml index 58d02d8..6fa10a3 100644 --- a/docs/configuration/snippets/_schema_maven.xml +++ b/docs/configuration/snippets/_schema_maven.xml @@ -2,6 +2,6 @@ io.swagger.core.v3 swagger-core - 2.2.20 + 2.2.22 \ No newline at end of file From 25092fb5bd388510d2aa5ffcc85e708d9c333b31 Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 16:54:04 +0200 Subject: [PATCH 6/9] docs: add headers page --- docs/configuration/documenting-consumers.md | 22 +--- docs/configuration/documenting-headers.mdx | 131 ++++++++++++++++++++ docs/configuration/documenting-messages.mdx | 4 +- docs/configuration/documenting-producers.md | 22 +--- 4 files changed, 135 insertions(+), 44 deletions(-) create mode 100644 docs/configuration/documenting-headers.mdx diff --git a/docs/configuration/documenting-consumers.md b/docs/configuration/documenting-consumers.md index e45a1c8..1f99a00 100644 --- a/docs/configuration/documenting-consumers.md +++ b/docs/configuration/documenting-consumers.md @@ -30,23 +30,7 @@ Below is an example to demonstrate the annotation: @AsyncListener(operation = @AsyncOperation( channelName = "example-consumer-topic", description = "Customer uploaded an example payload", // Optional - servers = {"kafka-server"}, // Optional - 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 = "NestedPayloadDto.v1") - // ... - } - ) + servers = {"kafka-server"} // Optional )) @KafkaAsyncOperationBinding public void receiveMessage(ExamplePayloadDto msg) { @@ -66,10 +50,6 @@ The channel name (or topic name in case of Kafka) - this is the name that will b 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. -### Header - -Optional. The headers describing the metadata of the payload. - ### Servers Optional. Useful when an application is connect to multiple brokers and wants to indicate to which broker the channel belongs to. diff --git a/docs/configuration/documenting-headers.mdx b/docs/configuration/documenting-headers.mdx new file mode 100644 index 0000000..c23df23 --- /dev/null +++ b/docs/configuration/documenting-headers.mdx @@ -0,0 +1,131 @@ +--- +sidebar_position: 69 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import CodeBlock from '@theme/CodeBlock'; +import CodeSchemaGroovy from '!!raw-loader!./snippets/_schema_groovy.gradle'; +import CodeSchemaMaven from '!!raw-loader!./snippets/_schema_maven.xml'; + +# 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: + +```java +@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: + +```java +@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](https://github.com/springwolf/springwolf-core/issues/378)) + +#### Usage + +Add the following dependency: + + + + {CodeSchemaGroovy} + + + {CodeSchemaMaven} + + + +Then, add the `@Schema` annotation to the payload class: + + +```java +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; + } +} +``` + + +:::note +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`](https://github.com/springwolf/springwolf-core/blob/master/springwolf-examples/springwolf-amqp-example/src/main/java/io/github/springwolf/examples/amqp/dtos/ExamplePayloadDto.java) + +#### 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. + +```java +@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; +} +``` + +:::info +See [Add-Ons](../add-ons) for more information on how to document other formats +::: diff --git a/docs/configuration/documenting-messages.mdx b/docs/configuration/documenting-messages.mdx index 8fcc9c1..aa6bfd8 100644 --- a/docs/configuration/documenting-messages.mdx +++ b/docs/configuration/documenting-messages.mdx @@ -10,7 +10,7 @@ import CodeSchemaMaven from '!!raw-loader!./snippets/_schema_maven.xml'; # Messages -Springwolf provides different ways to document the messages. The `message` is part of the AsyncAPI `operationObject` +Springwolf provides different ways to document the messages. The `message` is part of the AsyncAPI `operationObject` and mapped as `messageObject`. > A definition of the message that will be published or received by this operation @@ -22,7 +22,7 @@ For example: @AsyncPublisher(operation = @AsyncOperation( channelName = "example-producer-topic", description = "Customer uploaded an example payload", // Optional - payloadType = ExamplePayloadDto.class, // Optional + payloadType = ExamplePayloadDto.class, // Optional. Overwrites the detected payload message = @AsyncMessage( // Optional messageId = "my-unique-id", name = "ExamplePayloadDto", diff --git a/docs/configuration/documenting-producers.md b/docs/configuration/documenting-producers.md index 3abdd58..e61332e 100644 --- a/docs/configuration/documenting-producers.md +++ b/docs/configuration/documenting-producers.md @@ -24,23 +24,7 @@ Below is an example to demonstrate the annotation: @AsyncPublisher(operation = @AsyncOperation( channelName = "example-producer-topic", description = "Customer uploaded an example payload", // Optional - servers = {"kafka-server"}, // Optional - 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 = "NestedPayloadDto.v1") - // ... - } - ) + servers = {"kafka-server"} // Optional )) @KafkaAsyncOperationBinding public void sendMessage(ExamplePayloadDto msg) { @@ -60,10 +44,6 @@ The channel name (or topic name in case of Kafka) - this is the name that will b 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. -### Header - -Optional. The headers describing the metadata of the payload. - ### Servers Optional. Useful when an application is connect to multiple brokers and wants to indicate to which broker the channel belongs to. From 73065f37f5a1bffec76793cf8765556903d1f8d1 Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 16:56:50 +0200 Subject: [PATCH 7/9] docs: improve consumer docs --- docs/configuration/documenting-consumers.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/configuration/documenting-consumers.md b/docs/configuration/documenting-consumers.md index 1f99a00..e3c1263 100644 --- a/docs/configuration/documenting-consumers.md +++ b/docs/configuration/documenting-consumers.md @@ -11,11 +11,18 @@ For these use-cases, Springwolf provides additional ways to explicitly add them To document consumers, either: -- add the `@AsyncListener` annotation or -- rely on the auto-detection of `@JmsListener`, `@KafkaListener`, `@MessageMapping`, `@RabbitListener`, `@SqsListener`, `@SendTo`, `@SendToUser` +- rely on the auto-detection of `@JmsListener`, `@KafkaListener`, `@MessageMapping`, `@RabbitListener`, `@SendTo`, `@SendToUser`, `@SqsListener` +- and/or use the `@AsyncListener` annotation You are free to use both options together. Channel and operation, documented via `@AsyncListener` have a higher precedence than auto-detected annotations. +## Auto-detection + +The `@JmsListener`, `@KafkaListener`, `@MessageMapping`, `@RabbitListener`, `@SendTo`, `@SendToUser`, `@SqsListener` annotations are detected automatically. +There is nothing more to do. + +Use the other option if the provided documentation is insufficient. + ## `@AsyncListener` The `@AsyncListener` annotation is added to the method of the listeners and extracts the payload from its arguments. @@ -54,9 +61,3 @@ Optional. The description allows for human-friendly text to verbosely explain th Optional. Useful when an application is connect to multiple brokers and wants to indicate to which broker the channel belongs to. The server name needs to exist in [configuration > Servers](configuration.mdx) as well. - -## `@JmsListener`, `@KafkaListener`, `@RabbitListener`, `@SqsListener` - -The `@JmsListener`, `@KafkaListener`, `@RabbitListener`, `@SqsListener` annotations are detected automatically. -There is nothing more to do. -Use the other option if the provided documentation is insufficient. From a8fc855adcff9c85f02d1ea35624b6dedaa750df Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 17:14:11 +0200 Subject: [PATCH 8/9] docs: add springwolf.studio-compatibility configuration --- docs/configuration/configuration.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration/configuration.mdx b/docs/configuration/configuration.mdx index cd11aa7..6285523 100644 --- a/docs/configuration/configuration.mdx +++ b/docs/configuration/configuration.mdx @@ -62,6 +62,7 @@ The following table contains additional properties that can be specified in the | `springwolf.paths.docs` | `/springwolf/docs` | The path of the AsyncAPI document in JSON format. *Note that at the moment the UI will work only with the default value.* | | `springwolf.endpoint.actuator.enabled` | `false` | Publish the AsyncAPI document as part of Spring Boot’s actuator feature. | | `springwolf.use-fqn` | `true` | Use fully qualified names for the schema classes. **Required for publishing with `springwolf-ui`** | +| `springwolf.studio-compatibility` | `true` | Activate tweaks to allow viewing & editing in [AsyncAPI studio](https://studio.asyncapi.com) | | `springwolf.payload.extractable-classes..` | N/A | Extract additional payload types. See [message payloads](documenting-messages.mdx) for more details. | | `springwolf.scanner.async-listener.enabled` | `true` | Enable scanner to find methods annotated with `@AsyncListener`. | | `springwolf.scanner.async-publisher.enabled` | `true` | Enable scanner to find methods annotated with `@AsyncPublisher`. | From b4672bb1902718250ff48e64663c06d6f369f444 Mon Sep 17 00:00:00 2001 From: Timon Back Date: Fri, 28 Jun 2024 17:18:36 +0200 Subject: [PATCH 9/9] docs: add presentation link --- docs/quickstart.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx index 498ffa0..8fbc1c9 100644 --- a/docs/quickstart.mdx +++ b/docs/quickstart.mdx @@ -54,6 +54,7 @@ If you configured a different context path in your application, make sure to pre ## 4. Next steps +- [AsyncAPI and Springwolf presentation](https://www.youtube.com/watch?v=DylvTW_ia4Y) at Spring I/O 2024 - Read an elaborated tutorial on Baeldung at https://www.baeldung.com/java-spring-doc-asyncapi-springwolf - Check out the [supported protocols and example projects](introduction/supported-protocols) - Dive deeper on the next pages