Skip to content

Commit

Permalink
Merge branch 'master' into guide
Browse files Browse the repository at this point in the history
  • Loading branch information
quetzalliwrites committed Feb 24, 2023
2 parents 1222695 + d003971 commit 5ba8792
Show file tree
Hide file tree
Showing 4 changed files with 481 additions and 0 deletions.
162 changes: 162 additions & 0 deletions pages/docs/tutorials/create-asyncapi-document.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
title: Create AsyncAPI document
description: In this tutorial, you'll learn how to create an AsyncAPI document.
weight: 80
---

## Introduction

In this tutorial, you'll learn how to create an AsyncAPI document based on a sample real-world use case. Additionally, you will learn about event-driven architecture, message brokers, pub/sub pattern.

Let's pretend you have a company called Smarty Lighting, and you install smart-city streetlight lighting systems. This smart lighting system is a use case of the Internet of things (IoT).You will create a Smartylighting Streetlights API using Node.js and Mosquitto (MQTT) as the message broker. This API will allow you to manage city lights remotely.

You want to build a system that can turn streetlights on and off based on their environmental conditions:

- You will implement an event-driven architecture (EDA) with a message broker in its "center."

- Streetlights will publish information about their environmental lighting to the broker.

- Your application will connect to the broker and receive a stream of events from all the streetlights reporting their conditions.

- Your application decides based on events when to turn the streetlight off.

- Your application is not aware of how many streetlights are publishing events - it just connects to the broker and receives all events.


## Background context

Event-driven architecture (EDA) is a design pattern built around the production, detection, and reaction to events that take place in time. In this pattern, a message broker, event publishers and subscribers are its main components for event exchange within microservices.

[Message brokers](/docs/tutorials/getting-started/event-driven-architectures#message-broker) enables asynchronous communications between services so that the sending service need not wait for the receiving service’s reply. This allows interdependent services to “talk” with one another directly, even if they were written in different languages or implemented on different platforms.

Futhermore, the [Pub/sub](/docs/tutorials/getting-started/event-driven-architectures#publishersubscriber) is appealing for IoT use cases due to two key features: support for flexible coupling between publishers/subscribers and inherent support for point-to-multipoint transmission.

[MQTT](https://mqtt.org/), is a well-known protocol that is widely used in IoT applications because it was created particularly to address machine-to-machine (M2M) communication.

## Create AsyncAPI document

In this step, you will create an AsyncAPI document to describe the Streelights API. It will help you generate the code and the documentation later on.

To create one, you can either use the [AsyncAPI Studio](https://studio.asyncapi.com) or the [AsyncAPI CLI](https://github.com/asyncapi/cli), depending on your project need.

<Remember>

You can create a new `asyncapi.yaml` document by running:
`asyncapi new --example=tutorial.yml --no-tty`.

</Remember>

Go ahead to create the specification documents titled `asyncapi` with a `.yaml` extension.

<CodeBlock>
{`asyncapi: '2.5.0'
info:
title: Streetlights API
version: '1.0.0'
description: |
The Smartylighting Streetlights API allows you
to remotely manage the city lights.
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0'
servers:
mosquitto:
url: mqtt://test.mosquitto.org
protocol: mqtt
channels:
light/measured:
publish:
summary: Inform about environmental lighting conditions for a particular streetlight.
operationId: onLightMeasured
message:
name: LightMeasured
payload:
type: object
properties:
id:
type: integer
minimum: 0
description: Id of the streetlight.
lumens:
type: integer
minimum: 0
description: Light intensity measured in lumens.
sentAt:
type: string
format: date-time
description: Date and time when the message was sent.`}
</CodeBlock>

Let's break it down into pieces:

<CodeBlock>
{`asyncapi: '2.5.0'
info:
title: Streetlights API
version: '1.0.0'
description: |
The Smartylighting Streetlights API allows you
to remotely manage the city lights.
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0'`}
</CodeBlock>

- The `asyncapi` field indicates you use the AsyncAPI version 2.5.0.

- The `info` field holds information about the Streetlights API. Here, the title, version, description and license were defined.

Moving on, let's talk about the `servers` section.
<CodeBlock>
{`servers:
mosquitto:
url: mqtt://test.mosquitto.org
protocol: mqtt`}
</CodeBlock>

In this section, you point to the Eclipse Mosquitto message broker. The `url` point to a real instance of the broker [hosted by the Mosquitto community](https://test.mosquitto.org/) and the `protocol` as MQTT. If you do not want to use the test instance, you can spin up your own broker locally with `docker run -it -p 1883:1883 eclipse-mosquitto:1.5`. But remember to change `url` to `mqtt://localhost`

Now lets move on to the `channels` section. This section is used to describe the event names your API will be publishing and/or subscribing to.

<CodeBlock>
{`channels:
light/measured:
publish:
summary: Inform about environmental lighting conditions for a particular streetlight.
operationId: onLightMeasured`}
</CodeBlock>

In this example, `light/measured` is the channel name the Streetlight API will `subscribe` to (i.e, to interact with the Streetlight API you `publish` to the broker). The `operationId` property, describes what is the name of function or method that takes care of this functionality in the generated code.

Next is the `payload` property which is used to understand how the event should look like when publishing to that channel:

<CodeBlock>
{` payload:
type: object
properties:
id:
type: integer
minimum: 0
description: Id of the streetlight.
lumens:
type: integer
minimum: 0
description: Light intensity measured in lumens.
sentAt:
type: string
format: date-time
description: Date and time when the message was sent.`}
</CodeBlock>

The `payload` property defines the content of the event using AsyncAPI schemas. It means that your event payload should contain an `id` and a `lumens` property —which are integers bigger than zero—, and a `sentAt` property that should be a string containing a date and time.

> JSON Schema Draft 07 is 100% compatible with AsyncAPI schemas. You can also use other standards to describe payload schema, like, for example [Avro](https://github.com/asyncapi/avro-schema-parser#usage).
## Summary

In this tutorial, you learned how to create an AsyncAPI specification document via a real-life example with an IoT use case.

This tutorial is only a bootstrap; you'll need to add your own business logic into it. Take some time to play with it. There are still lots of things to be covered, but the intent of this tutorial is to make it simple for you to get an idea of the potential.

## Next steps
Now that you've completed this tutorial, go ahead to learn how to [validate your AsyncAPI document with Studio](https://www.asyncapi.com/docs/tutorials/studio-document-validation).
99 changes: 99 additions & 0 deletions pages/docs/tutorials/generate-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
title: Generate code
description: In this tutorial, you'll learn how to generate code from your AsyncAPI document.
weight: 100
---

## Introduction

In this tutorial, you'll learn how to generate code from your AsyncAPI document using the AsyncAPI generator tool.

## Background context
The [AsyncAPI Generator](https://github.com/asyncapi/generator) is a tool that you can use to generate whatever you want based on the AsyncAPI document. You can generate docs and code. It can be used as a library in a Node.js application or through the [AsyncAPI CLI](https://github.com/asyncapi/cli).

The generator tool supports a number of templates to generate code for a variety of different languages and protocols as the output. These templates help to specify what exactly must be generated, and in this tutorial, you'll use a [Node.js template](https://github.com/asyncapi/nodejs-template).

## Installation guide
<Remember>

It is important to have [Node.js](https://nodejs.org/en/download/) installed which will enable the installation of the required dependencies using <b>npm</b>.

</Remember>

import CliInstallation from '../../../assets/docs/fragments/cli-installation.md'

<CliInstallation/>

## Generate code

To generate code from the [AsyncAPI document created in a previous tutorial](https://asyncapi.com/docs/tutorials/create-asyncapi-document), follow the steps listed below:

<Remember>

If you did not follow the previous tutorial and do not have an `asyncapi.yaml` file ready, generate one running `asyncapi new --example=tutorial.yml --no-tty`.

</Remember>

1. Trigger generation of the Node.js code:
<CodeBlock language="bash">
{`asyncapi generate fromTemplate asyncapi.yaml @asyncapi/nodejs-template -o output -p server=mosquitto`}
</CodeBlock>

Let's break down the previous command:
- `asyncapi generate fromTemplate` is how you use AsyncAPI Generator via the AsyncAPI CLI.
- ` asyncapi.yaml` is how you point to your AsyncAPI document and can be a URL.
- `@asyncapi/nodejs-template` is how you specify the Node.js template.
- `-o` determines where to output the result.
- `-p` defines additional parameters you want to pass to the template. Here, the `server` parameter specifies the server's name as it is defined in AsyncAPI document.

2. List all files in directory and check that the Node.js application is generated:
<CodeBlock language="bash">
{`cd output && ls`}
</CodeBlock>

Upon execution of the command above, the following is an example of the expected result:
<CodeBlock language="bash">
{`$ ls
Dockerfile
asyncapi.yaml
docs
src
README.md
config
package.json`}
</CodeBlock>

## Start generated application
1. Install dependencies of the newly generated application:
<CodeBlock language="bash">
{`npm install`}
</CodeBlock>

2. Start the application:
<CodeBlock language="bash">
{`npm start`}
</CodeBlock>

## Send message to broker
1. In another terminal install the MQTT.js library:
<CodeBlock language="bash">
{`npm install mqtt -g`}
</CodeBlock>

2. Send a message to the MQTT broker that's connected to your generated application. Run the following MQTT client command:
<CodeBlock language="bash">
{`mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": 3, "sentAt": "2017-06-07T12:34:32.000Z"}'`}
</CodeBlock>

3. Go back to the previous terminal to check if your application logged the streetlight condition you just sent. You should see something like this displayed in the terminal:
<CodeBlock language="bash">
{`light/measured was received:
{ id: 1, lumens: 3, sentAt: '2017-06-07T12:34:32.000Z' }`}
</CodeBlock>
## Summary
In this tutorial, you learned how to generate your code from the [Streetlights API specification document created in a previous tutorial](https://asyncapi.com/docs/tutorials/create-asyncapi-document) using the AsyncAPI generator tool.

Additionally, you've learned how to run your code by installing the generated code's dependencies and sending several test messages to the Streelights application using the MQTT client.

## Next steps
Now that you've completed this tutorial, go ahead and learn how to [validate your AsyncAPI messages (events)](https://asyncapi.com/docs/tutorials/message-validation.md) through the message validation techniques supported by AsyncAPI.
93 changes: 93 additions & 0 deletions pages/docs/tutorials/message-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: Message validation in runtime
description: In this tutorial, you'll learn how to validate AsyncAPI messages (events).

weight: 130
---

## Introduction
In this tutorial, you'll learn how to validate messages (events) that are sent to your AsyncAPI application.

## Background context
Message validation can be performed at both the **producer** and **consumer** levels. Message validation requires the participation of the producer, consumer, and broker. We will learn how to validate messages at the consumer level by discarding invalid messages based on the parameters provided.

You will be using the [Eclipse Mosquitto](https://mosquitto.org/) broker. The MQTT protocol provides a lightweight method of messaging using a publish/subscribe model. You will also use an MQTT client that runs an MQTT library and connects to an MQTT broker over a network. Here publishers and subscribers are MQTT clients. The publisher and subscriber labels refer to whether the client is publishing or subscribing to receive messages.

In the previous tutorial, you generated your application using the [AsyncAPI Generator](https://github.com/asyncapi/generator) Node.js template.
<Remember>

If you did not follow the previous tutorial and do not have an `asyncapi.yaml` file ready, then generate one by running:
`asyncapi new --example=tutorial.yml --no-tty`.

Next, generate a server by running:

asyncapi generate fromTemplate asyncapi.yaml @asyncapi/nodejs-template -o output -p server=mosquitto
cd output && npm install

</Remember>

Now you will be validating the messages which you will be sending to your application using a Mosquitto broker and an MQTT client.

## Validate messages
In this step, you will send a message to your application using an MQTT broker and check the errors logged when you accidentally send an invalid message.

1. Start your generated application.

<CodeBlock language="bash">
{`npm start`}
</CodeBlock>

2. Let's send a message:

<CodeBlock language="bash">
{`mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": "3", "sentAt": "2017-06-07T12:34:32.000Z"}'`}
</CodeBlock>

Go back to the previous terminal and check if your application logged the streetlight condition you just sent, with errors related to the invalid message. You should see something displayed in the terminal similar to the following:

<CodeBlock language="bash">
{`light/measured was received:
{ id: 1, lumens: '3', sentAt: '2017-06-07T12:34:32.000Z' }
❗ Message Rejected. data.lumens should be integer`}
</CodeBlock>

Here, you can see that the property `lumens` has type `integer`, but you are sending a message with type `string`.

<CodeBlock language="yaml" highlightedLines={[10,11]}>
{` message:
name: lumensInfo
payload:
type: object
properties:
id:
type: integer
minimum: 0
description: Id of the streetlight.
lumens:
type: integer
minimum: 0
description: Light intensity measured in lumens.`}
</CodeBlock>

3. Send a correct message to your application:

<CodeBlock language="bash">
{`mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": 3, "sentAt": "2017-06-07T12:34:32.000Z"}'`}
</CodeBlock>

You can see that your generated application received a message in the terminal:

<CodeBlock language="bash">
{`light/measured was received:
{ id: 1, lumens: 3, sentAt: '2017-06-07T12:34:32.000Z' }`}
</CodeBlock>

This indicates that your message is valid and the application recieved it correctly.

## Summary
In this tutorial, you learned how to connect your generated application to an MQTT broker, send messages through it, identify when an invalid message is sent to your application, and how to correct an invalid message.

## Next steps
Now that you've completed this tutorial, enjoy our [AsyncAPI message validation guide](pages/docs/guides/message-validation).

---
Loading

0 comments on commit 5ba8792

Please sign in to comment.