Skip to content
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

docs: adding document for Messages and Operations reusability with Traits #2411

Merged
merged 5 commits into from
Dec 16, 2023
Merged
Changes from 3 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
100 changes: 100 additions & 0 deletions pages/docs/concepts/asyncapi-document/reusability-with-traits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: Reusability with Traits
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved
weight: 200
---

Traits work only with `operations` and `messages` fields. Traits allows to define properties that can be reused across multiple message and operations within the specification. Reusing traits promotes code maintainability, reduces duplication, and makes your AsyncAPI documents cleaner and easier to manage.
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved

## Defining traits

You can inline traits definitions as part of an `operation` or a `message` but because goal of traits is reusability, you should do it under the `components` section of your AsyncAPI document, within `operationTraits` or `messageTraits`, depending on whether you want to apply them to operations or messages, respectively. Each trait is given a unique name and contains the properties that will be applied. Since you point to trait using `$ref` keyword, it means that you also can store your reusable traits outside AsyncAPI document. Read [Reusable parts document](/docs/concepts/asyncapi-document/reusable-parts) to learn more about different ways of using `$ref`.
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved

```mermaid
graph LR
A[channels] --> F[messages]
F -->|$ref| D
B[components] --> C[operationTraits]
B --> D[messageTraits]
E[operations] -->|$ref| C


style A fill:#47BCEE,stroke:#47BCEE;
style F fill:#47BCEE,stroke:#47BCEE;
style E fill:#47BCEE,stroke:#47BCEE;
```

[Message Trait](/docs/reference/specification/latest#messageTraitObject) do not fully cover all fields that normal message has, like for example `payload`. The same is with [Operation Trait](/docs/reference/specification/latest#operationTraitObject) that represents only selected fields you usually use in an operation.
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved

Here is a part of a message that has a trait defined inline in a message:

```yaml
description: Example description.
traits:
- name: UserSignup
description: Trait description.
- tags:
- name: user
```

Traits are merged into the message object and later message look like in the example below:
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved

```yaml
name: UserSignup
description: Example description.
tags:
- name: user
```

Notice that description from trait did not override the description that was already there defined in a message outside the trait.
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved

## Applying traits from components

Once a trait is defined, you can apply it to an operation or a message using the `$ref` keyword in the `traits` section. The `$ref` value should point to the path of the trait within the `components` section.

For example, let's say we have a trait named `commonHeaders` defined in `messageTraits`:

```yml
components:
messageTraits:
commonHeaders:
headers:
type: object
properties:
content-type:
type: integer
```

To apply the above trait to a message object, you can do:

```yml
name: lightMeasured
title: Light measured
summary: Inform about environmental lighting conditions of a particular streetlight.
headers:
type: object
properties:
custom-header:
type: string
traits:
- $ref: '#/components/messageTraits/commonHeaders'
```

In such document, the `commonHeaders` trait, which includes a `content-type` header, is merged into `headers` object in a message and will look like in the following example:
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved

```yaml
name: lightMeasured
title: Light measured
summary: Inform about environmental lighting conditions of a particular streetlight.
headers:
type: object
properties:
content-type:
type: integer
custom-header:
type: string
```

## Trait merging mechanism

Traits in AsyncAPI document are merged into the message object in the same order they are defined and traits are merged into the operation or message object. There is no override of properties possible. For more info on [the merge mechanism check further specification reference documentation](/docs/reference/specification/#traitsMergeMechanism).
quetzalliwrites marked this conversation as resolved.
Show resolved Hide resolved