Skip to content

Update documentation for actuator #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/styles/config/vocabularies/Springwolf/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ Kotlinx
Protobuf
Springfox
Springwolf
STOMP
UI
2 changes: 1 addition & 1 deletion docs/behind-the-scenes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
59 changes: 32 additions & 27 deletions docs/configuration/configuration.mdx

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/configuration/customizing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 10 additions & 2 deletions docs/configuration/documenting-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
39 changes: 10 additions & 29 deletions docs/configuration/documenting-consumers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`, `@RabbitListener`, `@SqsListener`
- 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.
Expand All @@ -30,23 +37,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) {
Expand All @@ -66,17 +57,7 @@ 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.
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.
131 changes: 131 additions & 0 deletions docs/configuration/documenting-headers.mdx
Original file line number Diff line number Diff line change
@@ -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:

<Tabs>
<TabItem value="Groovy" label="Groovy" default>
<CodeBlock language="groovy">{CodeSchemaGroovy}</CodeBlock>
</TabItem>
<TabItem value="Maven" label="Maven">
<CodeBlock language="xml">{CodeSchemaMaven}</CodeBlock>
</TabItem>
</Tabs>

Then, add the `@Schema` annotation to the payload class:

<!-- vale off -->
```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;
}
}
```
<!-- vale on -->

:::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
:::
4 changes: 2 additions & 2 deletions docs/configuration/documenting-messages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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",
Expand Down
22 changes: 1 addition & 21 deletions docs/configuration/documenting-producers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/snippets/_schema_groovy.gradle
Original file line number Diff line number Diff line change
@@ -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'
}
2 changes: 1 addition & 1 deletion docs/configuration/snippets/_schema_maven.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core</artifactId>
<version>2.2.20</version>
<version>2.2.22</version>
</dependency>
</dependencies>
5 changes: 3 additions & 2 deletions docs/introduction/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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)
Expand Down
Loading
Loading