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

chore(blog): adding 3 New Articles as Blog Posts #1805

Merged
merged 64 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
bcca026
zenwave contributed blog posts
ivangsa Jun 18, 2023
124feab
Merge branch 'asyncapi:master' into master
ivangsa Jun 19, 2023
1f9773e
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
80ddb67
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
05ccaaf
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
a39ce78
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
e2c77a7
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
c5624ed
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
660c067
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
e3adebb
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
bfb4e18
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
75971b0
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
66624a4
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
cde4d4a
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
eadb08a
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
d4d8620
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
de93816
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
8a711ab
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
80cc3ca
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
8c1c18d
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
6d527e9
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
ea0af72
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
24f6eb9
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
3e4a3a9
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
1cacf26
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
693c39f
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
b0ade68
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
a057d8e
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
f06de6a
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
3fbdf53
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
f341744
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
4841dae
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
062c638
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
0dc9b57
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
a431317
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
ec428c7
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
465fac6
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
47e2322
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
f047707
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
186a0cc
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
9223e4c
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
c4fcd8a
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
64cc9b5
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
7a3b7dc
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
5e5d4d9
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
58d22aa
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
bceb20b
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
ef38d98
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
bed8bba
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
87b409c
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
8ea1618
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
d0c7961
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
5b73ccc
Applying suggestions from code review, thanks a lot...
ivangsa Jun 19, 2023
69a6b7b
Merge branch 'master' into master
quetzalliwrites Jun 21, 2023
09ebb85
Update api-first-with-asyncapi.md
thulieblack Jun 23, 2023
cba9a7f
Update zenwave-asyncapi-code-generator.md
thulieblack Jun 23, 2023
20a1280
Merge branch 'master' into master
thulieblack Jun 23, 2023
6947218
Merge branch 'master' into master
thulieblack Jul 13, 2023
45d0884
Merge branch 'master' into master
ivangsa Aug 2, 2023
4e7a61a
Update pages/blog/api-first-with-asyncapi.md
ivangsa Aug 2, 2023
f4fb7a2
Update pages/blog/jhipster-jdl-to-asyncapi.md
ivangsa Aug 2, 2023
dace2f6
Update pages/blog/zenwave-asyncapi-code-generator.md
ivangsa Aug 2, 2023
f4bddf2
Merge branch 'master' into master
derberg Aug 2, 2023
3dce3fc
Merge branch 'master' into master
thulieblack Aug 11, 2023
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
284 changes: 284 additions & 0 deletions pages/blog/api-first-with-asyncapi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
---
title: API-First with AsyncAPI
date: 2023-06-17T06:00:00+01:00
ivangsa marked this conversation as resolved.
Show resolved Hide resolved
type: Engineering
tags:
- API-First
- EDA
- Specification
cover: /img/posts/zenwave/api-first-with-asyncapi-banner.png
canonical: https://zenwave360.github.io/Event-Driven-Architectures/API-First-with-AsyncAPI
authors:
- name: Ivan Garcia Sainz-Aja
photo: /img/avatars/ivangsa.webp
link: https://www.linkedin.com/in/ivangarciasainzaja/
byline: Software Architect at Sngular. Speaker. Building ZenWave 360º
excerpt: 'If you are familiar with OpenAPI and OpenAPI Generator API-First process, doing API-First with AsyncAPI is similar.'
---

# API-First with AsyncAPI

- [API-First with AsyncAPI](#api-first-with-asyncapi)
- [Broker-based APIs are Symmetric](#broker-based-apis-are-symmetric)
- [Events, Commands, and Messages](#events-commands-and-messages)
- [Understanding AsyncAPI Definition](#understanding-asyncapi-definition)
- [Info](#info)
- [Servers](#servers)
- [Channels: Publish / Subscribe](#channels-publish--subscribe)
- [Messages](#messages)
- [Message Payloads / Schemas](#message-payloads--schemas)
- [Reusing Configurations: Operation Traits, Message Traits...](#reusing-configurations-operation-traits-message-traits)
- [Different Styles of Event Messages](#different-styles-of-event-messages)
- [Notification Messages](#notification-messages)
- [State Transfer Messages](#state-transfer-messages)
- [Domain Event Messages](#domain-event-messages)
- [Next: Java Code Generator for AsyncAPI](#next-java-code-generator-for-asyncapi)

If you are familiar with OpenAPI and OpenAPI Generator API-First workflow:

- First, write the OpenAPI definition, collaborating between API providers and API consumers.
- Then, use OpenAPI Generator, either the maven plugin or a CLI, to generate some DTOs and interfaces from your OpenAPI definition.
- Implementing the generated interfaces, you can create a service for the API.
- As a client, you can use generated interfaces to consume the API with some HTTP client generated behind the scenes.

When doing API-First with AsyncAPI, the process is similar. After you generate some interfaces and DTOs from your API definition, you use the generated interfaces to produce messages, send them to the broker, and implement them to consume messages from the broker.

There is still a fundamental difference between OpenAPI and AsyncAPI: OpenAPI is used to document Request-Response / Client-Server APIs, while AsyncAPI is used to document Event-Driven APIs which, except for WebSockets, are Broker-based.

And broker-based APIs, unlike Client-Server, are inherently **symmetric**.

## Broker-based APIs are Symmetric

![Client-server vs broker-based EDAs](/img/posts/zenwave/client-server-vs-broker-eda.excalidraw.svg)

Because APIs mediated by a broker are inherent **symmetric**, it's difficult to establish the roles of the client/server: what represents a `publish` operation from one side will be a `subscribe` operation seen from the other side. Also, a given service can act as a publisher and subscriber on the same API.

For these reasons, to avoid defining the same API operations multiple times from each perspective, we propose to define the API only once from the perspective of the provider of the functionality, which may be a producer, a consumer, or both.

Some definitions:

- SERVICE: An independent piece of software, typically a microservice, that provides a set of capabilities to other services.
- PROVIDER: The service that implements the functionality of the API. It may be accepting asynchronous command requests or publishing business domain events.
- CLIENT/s: The service/s that uses the API's functionality. It may be requesting asynchronous commands or subscribing to business domain events.
- PRODUCER: A service that writes a given message.
- CONSUMER: A service that reads a given message.

> Define your AsyncAPI from the perspective of the **PROVIDER** of the functionality, which may be a producer, a consumer, or both. Share this definition with your **CLIENTS**.

Use the table to understand which section of AsyncAPI (publish or subscribe) to use for each topic and which role (provider or client) to use on the plugin configuration.

| | Events | Commands |
|------------------------------|-----------------------|-------------------------|
| Provider | Produces (publish) | Consumes (subscribe) |
| Client | Consumes (subscribe) | Produces (publish) |
| OperationId Suggested Prefix | **on**<Event Name> | **do**<Command Name> |

If you still find it confusing which one is a provider and a client, just use this rule: it can be only one provider of a given message, while clients of a given message there can be many:

- If the provider is the producer, use publish section
- If it is the consumer, use subscribe section.

## Events, Commands, and Messages

There are two types of messages in a messaging system: events and commands. An event message describes a change that has already happened, while a command message describes an operation that needs to be carried out. In other words, events are used to notify subscribers about something that has already occurred, while commands are used to initiate an action or process.

- **Event:** A message describing a change that has already happened.
- **Command:** A message describing an operation that has to be carried out.

Also, while there can be only one provider that produces a given event, commands can be issued for one or many client producers.

## Understanding AsyncAPI Definition

While OpenAPI and AsyncAPI come to document completely different architectural styles, they are similar in many aspects; in fact, AsyncAPI YAML format was initially based on OpenAPI format and structure.

If you are familiar with OpenAPI, you may find useful the following image borrowed from AsyncAPI documentation (click image to follow):

[![OpenAPI and AsyncAPI](/img/posts/zenwave/openapi-asyncapi.png)](https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi)

### Info

Document your API: name, purpose, contact details, and license...

### Servers

Document where your API will be deployed and required security...

You can also document some server **protocol-specific configurations** using free-form **bindings** property

### Channels: Publish / Subscribe

Each channel represents one single broker topic, channel, or queue... where you are about to publish or subscribe.

Use the table above to understand which section, publish or subscribe, you may want to use.

In a nutshell:

> Providers publish events and subscribe to commands/queries/requests.

If you still find it confusing which is a provider and a client, use this rule: In a given messaging scenario, there can be only one provider of a message, while there can be multiple clients. If the provider is producing messages, use the `publish` section. If the provider is consuming messages, use the `subscribe` section.

### Messages

Use Messages to describe **Headers**, **Payload Schema**, and **Content-Type**. You can also include examples, descriptions, and protocol-specific binding documentation...

```yml
components:
messages:
turnOnOff:
name: turnOnOff
title: Turn on/off
summary: Command a particular streetlight to turn the lights on or off.
headers:
type: object
properties:
my-app-header:
type: string
payload:
$ref: "#/components/schemas/turnOnOffPayload"

```

### Message Payloads / Schemas

You can define message payloads as:

- Inline components/schemas in the same familiar way you do in OpenAPI
- External files: both `json-schema` and `avro schemas` (.avsc) are supported

```yml
components:
messages:
MessageWithAsyncAPISchema:
payload:
$ref: "#/components/schemas/turnOnOffPayload" ## asyncapi/inline schema
MessageWithExternalJsonSchema:
schemaFormat: 'application/schema+json;version=draft-07'
payload:
$ref: "some/external/file.schema" ## a json-schema file
MessageWithAvroSchema:
schemaFormat: application/vnd.apache.avro+json;version=1.9.0
payload:
$ref: "v1/imports/file.avsc" ## and avro schema file
```


### Reusing Configurations: Operation Traits, Message Traits...

Operation Traits, Message Traits are an excellent way to reuse chunks of configuration between different operations or messages.

For instance, if various messages share some common headers, you can configure them as Message Traits:
```yml
components:
messages:
CustomerEventMessage:
name: CustomerEventMessage
title: Async Event for a Customer
summary: Async Event for a Customer
schemaFormat: application/vnd.aai.asyncapi;version=2.4.0
traits:
- $ref: '#/components/messageTraits/CommonHeaders' # 'CommonHeaders' contents will replace 'traits' property
payload:
$ref: '#/components/schemas/CustomerEventPayload'

messageTraits:
CommonHeaders:
headers:
type: object
properties:
my-app-header:
type: integer
minimum: 0
maximum: 100
```

And the same concept applies to Operation Traits.


## Different Styles of Event Messages

### Notification Messages

An Event Notification **contains minimal information about the event** and enough information for interested consumers to locate additional details. The specifics of what information is included in an event notification can vary depending on the system or use case.

```json
{
"headers": {
"event-type": "customer-created",
"event-id": "",
"aggregate-id": "1",
"aggregate-type": "customer"
},
"payload": {
"id": 1,
"eventType": "created",
"link": "/customers/1"
}
}
```

### State Transfer Messages

On the other hand, a State Transfer message **contains the entire state of the aggregate**, so a consumer does not need to make additional calls. This can be useful in situations where subscribers need to maintain a synchronized view of the data. Compacted keyed topics typically use this style of messages.

```json
{
"headers": {
"event-id": "",
"aggregate-id": "1",
"aggregate-type": "customer"
},
"payload": {
"id": 1,
"firstName": "string",
"lastName": "string",
"password": "string",
"email": "string",
"username": "string",
"address": {
"id": 1,
"street": "string",
"city": "string",
"state": "string",
"zip": "string"
}
}
}
```


### Domain Event Messages

Domain Event Messages **contains information about the event and interesting portions of the underlying aggregate**, but not the entire state of the aggregate. This style of events is typically used for Event Sourcing integration patterns.

```json
{
"headers": {
"event-type": "customer-address-updated",
"event-id": "",
"aggregate-id": "1",
"aggregate-type": "customer"
},
"payload": {
"id": 1,
"eventType": "address-updated",
"customer": {
"id": 1,
"new-address": {
"street": "string",
"city": "string",
"state": "string",
"zip": "string"
}
}
}
}
```


## Next: Java Code Generator for AsyncAPI

[Next: Java Code Generator for AsyncAPI](zenwave-asyncapi-code-generator.md)

---

Originally published at [https://zenwave360.github.io](https://zenwave360.github.io/Event-Driven-Architectures/API-First-with-AsyncAPI)
106 changes: 106 additions & 0 deletions pages/blog/jhipster-jdl-to-asyncapi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
title: Convert JHipster JDL to AsyncAPI v2/v3 with ZenWave SDK
date: 2023-06-17T06:00:00+01:00
ivangsa marked this conversation as resolved.
Show resolved Hide resolved
type: Engineering
tags:
- ZenWave SDK
- Code Generator
- JHipster
- DSL
cover: /img/posts/zenwave/jhipster-to-asyncapi-banner.png
canonical: https://zenwave360.github.io/Domain-Driven-Design/JDL-Domain-Language/JHipster-As-IDL-for-AsyncAPIv2
authors:
- name: Ivan Garcia Sainz-Aja
photo: /img/avatars/ivangsa.webp
link: https://www.linkedin.com/in/ivangarciasainzaja/
byline: Software Architect at Sngular. Speaker. Building ZenWave 360º
excerpt: 'Because writing YAML by hand is now fun... You can generate AsyncAPI v2/v3 from JHipster JDL models with ZenWave SDK.'
---

# Generating AsyncAPI definition files from JDL with ZenWaveSDK

Writing YAML by hand is no fun, but you can simplify the process of writing AsyncAPI definition files by using a Domain Specific Language (DSL).

[JHipster Domain Language (JDL)](https://www.jhipster.tech/jdl/intro) is a Domain Specific Language (DSL) used to define the domain model of a web application. With JDL, you can describe the entities, relationships, and constraints of your system in a concise and readable way.

[Zenwave SDK](https://zenwave360.github.io/zenwave-sdk/) is a set of tools to generate (and reverse engineering) code from JDL and API-First models like AsyncAPI and OpenAPI.

Thanks to ZenWave SDK, you can convert JDL models into AsyncAPI definition files. This can save time and effort in the development process while ensuring that your APIs follow best practices and standards.

## JDL Example

```jdl
@aggregate
entity Customer {
username String required minlength(3) maxlength(250)
password String required minlength(3) maxlength(250)
email String required minlength(3) maxlength(250)
firstName String required minlength(3) maxlength(250)
lastName String required minlength(3) maxlength(250)
}
entity Address {
street String
city String
country String
zipCode String
}

relationship OneToOne {
Customer{address} to Address{customer}
}
```


## Generating AsyncAPI definition files from JDL with ZenWaveSDK

> See [JDL To AsyncAPI Generator](https://zenwave360.github.io/zenwave-sdk/plugins/jdl-to-asyncapi/) for a complete list of options and [GitHub repository](https://github.com/zenwave360/zenwave-sdk) for install instructions.

Because JDL can only describe static aspects of your models and doesn't cover dynamic behavior, ZenWave SDK can only infer CRUD operations from your entities, generating:

- One channel for each entity for both publishing Domain Events and subscribing to Commands/Requests.
- Messages and payloads for each entity Create/Update/Delete events (AVRO and AsyncAPI schema)

```shell
jbang zw -p io.zenwave360.sdk.plugins.JDLToAsyncAPIPlugin \
includeCommands=false \
specFile=src/main/resources/model/entities-model.jdl \
idType=integer \
idTypeFormat=int64 \
annotations=aggregate \
payloadStyle=event \
targetFile=src/main/resources/model/asyncapi.yml
```

You can choose to generate only Events or Commands using `includeEvents` (default: true) and `includeCommands` (default: false) to filter which channels you want to include in your AsyncAPI definition file.

You can also filter which entities you want to include Messages for in your AsyncAPI definition file using: `entities`, `skipEntities`, `annotations`, and `skipForAnnotations`.

**UPDATE:**

ZenWave SDK version 1.0.6 now supports generating AsyncAPI v3 format. Use `asyncapiVersion=v3` as:

```shell
jbang zw -p io.zenwave360.sdk.plugins.JDLToAsyncAPIPlugin \
includeCommands=false \
specFile=src/main/resources/model/entities-model.jdl \
idType=integer \
idTypeFormat=int64 \
annotations=aggregate \
payloadStyle=event \
asyncapiVersion=v3 \
targetFile=src/main/resources/model/asyncapi.yml
```

## Supported Schema Formats and Message Styles

You can generate AsyncAPI definition files with the following options:

- Supported Schema Formats: AVRO and AsyncAPI schema
- Supported [Payload Styles](https://zenwave360.github.io/Event-Driven-Architectures/API-First-with-AsyncAPI#different-styles-of-message-payloads): "Entity State Transfer" and "Domain Event" (for Create/Update/Delete events):
- State Transfer message contains the entire state of the aggregate, so a consumer does not need to make additional calls.
- Domain Event Messages contain information about the event and interesting portions of the underlying aggregate, but not the entire state of the aggregate.

By using JDL to define your domain model and ZenWave SDK to convert it into an AsyncAPI definition file, you can simplify the process of designing and documenting your APIs. This can improve your APIs' overall quality and consistency while reducing errors and inconsistencies.

---
Originally published at [https://zenwave360.github.io](https://zenwave360.github.io/Domain-Driven-Design/JDL-Domain-Language/JHipster-As-IDL-for-AsyncAPIv2).
Loading
Loading