@asyncapi/generator 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/Dockerfile +7 -8
- package/docs/asyncapi-document.md +2 -1
- package/docs/configuration-file.md +112 -33
- package/docs/generator-template-java.md +560 -0
- package/docs/generator-template.md +62 -29
- package/docs/hooks.md +3 -3
- package/docs/installation-guide.md +5 -51
- package/docs/migration-cli.md +5 -5
- package/docs/migration-nunjucks-react.md +1 -1
- package/docs/nunjucks-render-engine.md +4 -2
- package/docs/template.md +2 -2
- package/docs/usage.md +14 -32
- package/docs/versioning.md +3 -1
- package/lib/conditionalGeneration.js +162 -0
- package/lib/filtersRegistry.js +1 -1
- package/lib/generator.js +93 -40
- package/lib/hooksRegistry.js +8 -1
- package/lib/logMessages.js +6 -1
- package/lib/parser.js +10 -0
- package/lib/templateConfigValidator.js +30 -1
- package/package.json +2 -3
- package/test/generator.test.js +1 -1
- package/test/hooksRegistry.test.js +173 -0
- package/test/integration.test.js +47 -0
- package/test/parser.test.js +100 -2
- package/test/templateConfigValidator.test.js +18 -1
- package/test/test-project/README.md +5 -1
- package/test/test-project/docker-compose.yml +7 -15
- package/test/test-project/test-project.test.js +6 -2
- package/test/test-project/test-registry.test.js +7 -2
- package/test/test-project/test.sh +1 -1
- package/test/test-templates/nunjucks-template/package-lock.json +43 -119
- package/test/test-templates/react-template/.ageneratorrc +33 -0
- package/test/test-templates/react-template/package.json +4 -20
- package/test/test-templates/react-template/template/conditionalFile.txt +0 -0
- package/test/test-templates/react-template/template/conditionalFolder/conditionalFile.txt +0 -0
- package/test/test-templates/react-template/template/conditionalFolder2/input.txt +0 -0
- package/test/utils.test.js +53 -0
- package/test/test-project/test-entrypoint.sh +0 -12
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Creating a template - Java"
|
|
3
|
+
weight: 190
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
This tutorial teaches you how to create a simple generator template using a Java MQTT client. You'll use the AsyncAPI document and the template you develop to generate Java code. Additionally, you'll create template code with a reusable component to reuse the custom functionality you create and test your code using an MQTT client.
|
|
7
|
+
|
|
8
|
+
This section guides you through creating a flexible MQTT-supported template that will generate a **Java** client from the template and the AsyncAPI document referenced above. The following steps are similar to the [Creating a template - Python](https://www.asyncapi.com/docs/tools/generator/generator-template) but with a few differences and Java flair. This will help developers practice with AsyncAPI generator tool using statically typed language **Java**.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
To run it, ensure you have Java JDK 8 or higher, Gradle, and the AsyncAPI generator.
|
|
13
|
+
- **Gradle** - Get gradle at https://gradle.org/install/
|
|
14
|
+
- **JDK** - Get jdk at https://www.oracle.com/ca-en/java/technologies/downloads/
|
|
15
|
+
|
|
16
|
+
## Overview of Java Template
|
|
17
|
+
|
|
18
|
+
In this section, you'll:
|
|
19
|
+
|
|
20
|
+
1. Create a new directory to run Java code.
|
|
21
|
+
2. Create the Java client.
|
|
22
|
+
3. Test the Java Client
|
|
23
|
+
4. Output Java template code.
|
|
24
|
+
5. Create more channels
|
|
25
|
+
|
|
26
|
+
### 1. Create a new directory to run Java code
|
|
27
|
+
|
|
28
|
+
Create a new directory called **java-mqtt-client-template** at the root of your project. This is where all your Java templating work will go.
|
|
29
|
+
|
|
30
|
+
Once that is done, you should create some new sub-directories to begin building your Java client.
|
|
31
|
+
1. Create a new subdirectory called `src`
|
|
32
|
+
2. Change into `src` and create two new subdirectories: `fixtures` and `main/java`.
|
|
33
|
+
3. Create a file named `asyncapi.yml` in your fixtures directory and paste the `asyncapi.yml` document mentioned [here](https://www.asyncapi.com/docs/tools/generator/generator-template#background-context) into it.
|
|
34
|
+
4. Create a new file named **package.json** in your **java-mqtt-client-template** directory. This file is used to define the **dependencies** for your template.
|
|
35
|
+
5. Create a new file called **build.gradle** in your **java-mqtt-client-template** directory. This file is used to build your generated java code for your template.
|
|
36
|
+
6. Create a new file named **index.js** in a `template` folder from root directory. This file is used to define the **logic** for your template.
|
|
37
|
+
|
|
38
|
+
Now your directory should look like this:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
java-mqtt-client-template
|
|
42
|
+
├── src
|
|
43
|
+
| └── fixtures
|
|
44
|
+
| └── asyncapi.yml
|
|
45
|
+
│ └── main/java
|
|
46
|
+
├── template
|
|
47
|
+
| └── index.js
|
|
48
|
+
└── package.json
|
|
49
|
+
└── build.gradle
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
Note: The `client.java` code must be in your `src/main/java` directory, or else Gradle won't build your application.
|
|
54
|
+
|
|
55
|
+
### Java - package.json file
|
|
56
|
+
Add the following code snippet to your package.json file:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"name": "java-mqtt-client-template",
|
|
61
|
+
"version": "0.0.1",
|
|
62
|
+
"description": "A template that generates a Java MQTT client using MQTT.",
|
|
63
|
+
"generator": {
|
|
64
|
+
"renderer": "react",
|
|
65
|
+
"apiVersion": "v1",
|
|
66
|
+
"generator": ">=1.10.0 <2.0.0",
|
|
67
|
+
"supportedProtocols": ["mqtt"]
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@asyncapi/generator-react-sdk": "^0.2.25"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"rimraf": "^5.0.0"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Navigate to the `java-mqtt-client-template` directory and run the command `npm install` on your terminal to install the dependencies specified in `package.json`.
|
|
79
|
+
|
|
80
|
+
### Java - index.js file
|
|
81
|
+
|
|
82
|
+
The **index.js** file is used to define the logic for your template. Inside the template folder, create an **index.js** file and add the code snippet below:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
//1
|
|
86
|
+
import { File } from '@asyncapi/generator-react-sdk'
|
|
87
|
+
//2
|
|
88
|
+
export default function ({ asyncapi }) {
|
|
89
|
+
//3
|
|
90
|
+
return <File name="Client.java">{asyncapi.info().title()}</File>
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To see this in action, navigate to the `java-mqtt-client-template` directory. Then, run `asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java` command in your terminal. You should get a sucess message as shown below and a `Client.java` file in `src/main/java`.
|
|
95
|
+
|
|
96
|
+
``` cmd
|
|
97
|
+
Generation in progress. Keep calm and wait a bit... done
|
|
98
|
+
Check out your shiny new generated files at test/project.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 2. Create the Java client
|
|
102
|
+
|
|
103
|
+
#### 2a. Setting up Gradle
|
|
104
|
+
The first step in creating the Java client to send messages using the MQTT protocol is to ensure that your `build.gradle` file includes the correct dependencies. Add the code snippet below into your `build.gradle` file.
|
|
105
|
+
|
|
106
|
+
```groovy
|
|
107
|
+
plugins {
|
|
108
|
+
id 'java'
|
|
109
|
+
id 'application'
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
repositories {
|
|
113
|
+
mavenCentral()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
dependencies {
|
|
117
|
+
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
application{
|
|
121
|
+
mainClass = project.hasProperty('mainClass') ? project.mainClass : 'Client' // Default to 'Client' if no property is passed
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Here's what is contained in the code snippet above:
|
|
126
|
+
|
|
127
|
+
- **plugins** - This section defines the plugins applied to the Gradle project.
|
|
128
|
+
- **id 'java'** - This applies the Java plugin, which allows you to compile and run Java code.
|
|
129
|
+
- **id 'application'** - This plugin is used to support building and running applications. It helps with creating an executable JAR.
|
|
130
|
+
- **repositories** - This section tells you app to fetch dependencies from Maven Central to retrieve the MQTT client library.
|
|
131
|
+
- **dependencies** - This specifies that the project depends on the Eclipse Paho MQTT client version 1.2.5, which is needed to compile and run.
|
|
132
|
+
- **application** - This section defines how the application should be executed. **mainClass** specifies the main class to be executed in a Java application. It can be specified via the command line else it defaults to the **Client.java** file.
|
|
133
|
+
|
|
134
|
+
Navigate to the `java-mqtt-client-template` directory. Run the command `gradle build` in your terminal to build your Java application. **Note**: Every time you update the `build.gradle` file, you must recompile it to get the new changes.
|
|
135
|
+
|
|
136
|
+
#### 2b. Beefing up Client.java
|
|
137
|
+
|
|
138
|
+
Here is the sample code to pasted into the `Client.java` file you generated above running the `asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java` command.
|
|
139
|
+
|
|
140
|
+
```java
|
|
141
|
+
import org.eclipse.paho.client.mqttv3.*;
|
|
142
|
+
|
|
143
|
+
public class Client {
|
|
144
|
+
private static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
|
|
145
|
+
private static final String TOPIC = "temperature/changed";
|
|
146
|
+
|
|
147
|
+
private MqttClient client;
|
|
148
|
+
|
|
149
|
+
public Client() {
|
|
150
|
+
try {
|
|
151
|
+
// Generate a unique client ID
|
|
152
|
+
String clientId = MqttClient.generateClientId();
|
|
153
|
+
|
|
154
|
+
// Create and connect the MQTT client
|
|
155
|
+
client = new MqttClient(BROKER_URL, clientId);
|
|
156
|
+
MqttConnectOptions options = new MqttConnectOptions();
|
|
157
|
+
options.setCleanSession(true);
|
|
158
|
+
|
|
159
|
+
client.connect(options);
|
|
160
|
+
System.out.println("Connected to MQTT broker: " + BROKER_URL);
|
|
161
|
+
} catch (MqttException e) {
|
|
162
|
+
e.printStackTrace();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
public void sendTemperatureChange(String id) {
|
|
166
|
+
try {
|
|
167
|
+
// Publish the message with the temperature change
|
|
168
|
+
MqttMessage message = new MqttMessage(id.getBytes());
|
|
169
|
+
client.publish(TOPIC, message);
|
|
170
|
+
} catch (MqttException e) {
|
|
171
|
+
e.printStackTrace();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 3. Test the Java Client
|
|
178
|
+
Create a **src/main/java/TestClient.java** file in your project and add the code snippet below.
|
|
179
|
+
|
|
180
|
+
Your directory should now look like this:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
java-mqtt-client-template
|
|
184
|
+
├── src
|
|
185
|
+
| └── fixtures
|
|
186
|
+
| └── asyncapi.yml
|
|
187
|
+
│ └── main/java
|
|
188
|
+
| └── Client.java
|
|
189
|
+
| └── TestClient.java
|
|
190
|
+
├── template
|
|
191
|
+
| └── index.js
|
|
192
|
+
└── package.json
|
|
193
|
+
└── build.gradle
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
```java
|
|
197
|
+
import java.util.Random;
|
|
198
|
+
import java.util.concurrent.TimeUnit;
|
|
199
|
+
|
|
200
|
+
public class TestClient {
|
|
201
|
+
public static void main(String[] args) {
|
|
202
|
+
Client client = new Client();
|
|
203
|
+
Random random = new Random();
|
|
204
|
+
|
|
205
|
+
int idLength = 8;
|
|
206
|
+
int minValue = (int) Math.pow(10, idLength - 1); // Minimum 8-digit number (e.g., 10000000)
|
|
207
|
+
int maxValue = (int) Math.pow(10, idLength) - 1; // Maximum 8-digit number (e.g., 99999999)
|
|
208
|
+
System.out.println("Validating generated generated Client.java");
|
|
209
|
+
System.out.println("Running tests in TestClient.java");
|
|
210
|
+
System.out.println("Sending temperature changes to the broker...");
|
|
211
|
+
System.err.println("\n");
|
|
212
|
+
while (true) {
|
|
213
|
+
int randomId = random.nextInt(maxValue - minValue + 1) + minValue;
|
|
214
|
+
client.sendTemperatureChange(String.valueOf(randomId));
|
|
215
|
+
System.out.println("New temperature detected " + randomId + " sent to temperature/changed");
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
TimeUnit.SECONDS.sleep(1); // Sleep for 1 second
|
|
219
|
+
} catch (InterruptedException e) {
|
|
220
|
+
e.printStackTrace();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
Run the command `gradle run -PmainClass=TestClient` to run your Java program with Gradle on your terminal. You should see output similar to the snippet below logged on your terminal:
|
|
227
|
+
|
|
228
|
+
``` cmd
|
|
229
|
+
New temperature detected 64250266 sent to temperature/changed
|
|
230
|
+
New temperature detected 36947728 sent to temperature/changed
|
|
231
|
+
New temperature detected 72955029 sent to temperature/changed
|
|
232
|
+
```
|
|
233
|
+
### 4. Output Java template code.
|
|
234
|
+
Open **index.js** and copy the content below so your file looks like the code snippet below:
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
//1
|
|
238
|
+
import { File } from '@asyncapi/generator-react-sdk'
|
|
239
|
+
//2
|
|
240
|
+
export default function ({ asyncapi }) {
|
|
241
|
+
//3
|
|
242
|
+
return <File name="Client.java">
|
|
243
|
+
{`
|
|
244
|
+
|
|
245
|
+
import org.eclipse.paho.client.mqttv3.*;
|
|
246
|
+
public class Client {
|
|
247
|
+
private static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
|
|
248
|
+
private static final String TOPIC = "temperature/changed";
|
|
249
|
+
|
|
250
|
+
private MqttClient client;
|
|
251
|
+
|
|
252
|
+
public Client() {
|
|
253
|
+
try {
|
|
254
|
+
// Generate a unique client ID
|
|
255
|
+
String clientId = MqttClient.generateClientId();
|
|
256
|
+
|
|
257
|
+
// Create and connect the MQTT client
|
|
258
|
+
client = new MqttClient(BROKER_URL, clientId);
|
|
259
|
+
MqttConnectOptions options = new MqttConnectOptions();
|
|
260
|
+
options.setCleanSession(true);
|
|
261
|
+
|
|
262
|
+
client.connect(options);
|
|
263
|
+
System.out.println("Connected to MQTT broker: " + BROKER_URL);
|
|
264
|
+
} catch (MqttException e) {
|
|
265
|
+
e.printStackTrace();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
public void sendTemperatureChange(String id) {
|
|
269
|
+
try {
|
|
270
|
+
// Publish the message with the temperature change
|
|
271
|
+
MqttMessage message = new MqttMessage(id.getBytes());
|
|
272
|
+
client.publish(TOPIC, message);
|
|
273
|
+
} catch (MqttException e) {
|
|
274
|
+
e.printStackTrace();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}`
|
|
278
|
+
}</File>
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
#### 4a. Write the script to run the test code
|
|
282
|
+
In **package.json** define a script property that you invoke by calling `npm run <your_script>`. After adding these scripts in **package.json**, it will look like the following code snippet:
|
|
283
|
+
|
|
284
|
+
``` json
|
|
285
|
+
{
|
|
286
|
+
"name": "java-mqtt-client-template",
|
|
287
|
+
"version": "0.0.1",
|
|
288
|
+
"description": "A template that generates a Java MQTT client using MQTT.",
|
|
289
|
+
"generator": {
|
|
290
|
+
"renderer": "react",
|
|
291
|
+
"apiVersion": "v1",
|
|
292
|
+
"generator": ">=1.10.0 <2.0.0",
|
|
293
|
+
"supportedProtocols": ["mqtt"],
|
|
294
|
+
"parameters": {
|
|
295
|
+
"server": {
|
|
296
|
+
"description": "The server you want to use in the code.",
|
|
297
|
+
"required": true
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
"scripts": {
|
|
302
|
+
"test:clean": "rimraf src/main/java/Client.java",
|
|
303
|
+
"test:generate": "asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java --force-write --param server=dev",
|
|
304
|
+
"test:start": "gradle run -PmainClass=TestClient",
|
|
305
|
+
"test": "npm run test:clean && npm run test:generate && npm run test:start"
|
|
306
|
+
},
|
|
307
|
+
"dependencies": {
|
|
308
|
+
"@asyncapi/generator-react-sdk": "^0.2.25"
|
|
309
|
+
},
|
|
310
|
+
"devDependencies": {
|
|
311
|
+
"rimraf": "^5.0.0"
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
Run `npm test` to see if everything is working.
|
|
316
|
+
### 5. Create more channels
|
|
317
|
+
|
|
318
|
+
#### 5a. Creating more reusable components
|
|
319
|
+
|
|
320
|
+
Similar to the previous `TopicFunction` function we will create a function to make reusable components regardless of the number of channels in the asyncAPI document.
|
|
321
|
+
|
|
322
|
+
Create a **components** directory at the root of your project and create a file named `TopicFunction.js` and add the code snippet below:
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
/*
|
|
326
|
+
* This component returns a block of functions that users can use to send messages to specific topics.
|
|
327
|
+
* As input it requires a list of Channel models from the parsed AsyncAPI document.
|
|
328
|
+
*/
|
|
329
|
+
export function TopicFunction({ channels }) {
|
|
330
|
+
const topicsDetails = getTopics(channels);
|
|
331
|
+
let functions = '';
|
|
332
|
+
|
|
333
|
+
topicsDetails.forEach((t) => {
|
|
334
|
+
functions += `
|
|
335
|
+
public void send${t.name}(String id) {
|
|
336
|
+
String topic = "${t.topic}";
|
|
337
|
+
try {
|
|
338
|
+
MqttMessage message = new MqttMessage(id.getBytes());
|
|
339
|
+
client.publish(topic, message);
|
|
340
|
+
System.out.println("${t.name} change sent: " + id);
|
|
341
|
+
} catch (MqttException e) {
|
|
342
|
+
e.printStackTrace();
|
|
343
|
+
}
|
|
344
|
+
}\n`;
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
return functions;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/*
|
|
351
|
+
* This function returns a list of objects, one for each channel, each containing two properties: `name` and `topic`.
|
|
352
|
+
* name - holds information about the `operationId` definedin the AsyncAPI document
|
|
353
|
+
* topic - holds information about the topic's address.
|
|
354
|
+
*
|
|
355
|
+
* It requires as input, a list of Channel models from the parsed AsyncAPI document.
|
|
356
|
+
*/
|
|
357
|
+
function getTopics(channels) {
|
|
358
|
+
const channelsCanSendTo = channels
|
|
359
|
+
let topicsDetails = []
|
|
360
|
+
|
|
361
|
+
channelsCanSendTo.forEach((ch) => {
|
|
362
|
+
const topic = {}
|
|
363
|
+
const operationId = ch.operations().filterByReceive()[0].id()
|
|
364
|
+
topic.name = operationId.charAt(0).toUpperCase() + operationId.slice(1)
|
|
365
|
+
topic.topic = ch.address()
|
|
366
|
+
|
|
367
|
+
topicsDetails.push(topic)
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
return topicsDetails
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Import the `TopicFunction` component in your template code in **index.js** and add the template code to generate the functions for the topics which the `Temperature Service` application is subscribed to. In your case, the final version of your template code should look like this:
|
|
376
|
+
|
|
377
|
+
```js
|
|
378
|
+
import { File, Text } from '@asyncapi/generator-react-sdk';
|
|
379
|
+
import { TopicFunction } from '../components/TopicFunction'
|
|
380
|
+
|
|
381
|
+
export default function ({ asyncapi, params }) {
|
|
382
|
+
let channels = asyncapi.channels().filterByReceive(); // Get all the channels that receive messages
|
|
383
|
+
|
|
384
|
+
// Generate Java code for each topic dynamically using TopicFunction
|
|
385
|
+
const topicMethods = TopicFunction({ channels }); // This will return Java methods as text
|
|
386
|
+
|
|
387
|
+
return (
|
|
388
|
+
<File name="Client.java">
|
|
389
|
+
{
|
|
390
|
+
|
|
391
|
+
`import org.eclipse.paho.client.mqttv3.*;
|
|
392
|
+
|
|
393
|
+
public class Client {
|
|
394
|
+
private static final String BROKER_URL = "${asyncapi.servers().get(params.server).url()}";
|
|
395
|
+
private static final String TOPIC = "temperature/changed";
|
|
396
|
+
|
|
397
|
+
private MqttClient client;
|
|
398
|
+
|
|
399
|
+
public Client() {
|
|
400
|
+
try {
|
|
401
|
+
// Generate a unique client ID
|
|
402
|
+
String clientId = MqttClient.generateClientId();
|
|
403
|
+
|
|
404
|
+
// Create and connect the MQTT client
|
|
405
|
+
client = new MqttClient(BROKER_URL, clientId);
|
|
406
|
+
MqttConnectOptions options = new MqttConnectOptions();
|
|
407
|
+
options.setCleanSession(true);
|
|
408
|
+
|
|
409
|
+
client.connect(options);
|
|
410
|
+
System.out.println("Connected to MQTT broker: " + BROKER_URL);
|
|
411
|
+
} catch (MqttException e) {
|
|
412
|
+
e.printStackTrace();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
${topicMethods}
|
|
417
|
+
|
|
418
|
+
public static void main(String[] args) {
|
|
419
|
+
Client serviceClient = new Client();
|
|
420
|
+
|
|
421
|
+
// Simulate sending a temperature change
|
|
422
|
+
//serviceClient.sendTemperatureDrop("Sensor-1: 25°C");
|
|
423
|
+
}
|
|
424
|
+
}`
|
|
425
|
+
}
|
|
426
|
+
</File>
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Now your directory should look like this:
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
java-mqtt-client-template
|
|
435
|
+
├── components
|
|
436
|
+
| └── TopicFunction.js
|
|
437
|
+
├── src
|
|
438
|
+
| └── fixtures
|
|
439
|
+
| └── asyncapi.yml
|
|
440
|
+
│ └── main/java
|
|
441
|
+
| └── Client.java
|
|
442
|
+
| └── TestClient.java
|
|
443
|
+
├── template
|
|
444
|
+
| └── index.js
|
|
445
|
+
└── package.json
|
|
446
|
+
└── build.gradle
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### 5b. Update AsyncAPI document with more channels
|
|
450
|
+
|
|
451
|
+
Add the following AsyncAPI document to have more channels:
|
|
452
|
+
|
|
453
|
+
```yaml
|
|
454
|
+
asyncapi: 2.6.0
|
|
455
|
+
|
|
456
|
+
info:
|
|
457
|
+
title: Temperature Service
|
|
458
|
+
version: 1.0.0
|
|
459
|
+
description: This service is in charge of processing all the events related to temperature.
|
|
460
|
+
|
|
461
|
+
servers:
|
|
462
|
+
dev:
|
|
463
|
+
url: tcp://test.mosquitto.org:1883
|
|
464
|
+
protocol: mqtt
|
|
465
|
+
|
|
466
|
+
channels:
|
|
467
|
+
temperature/dropped:
|
|
468
|
+
description: Notifies the user when the temperature drops past a certain point.
|
|
469
|
+
publish:
|
|
470
|
+
operationId: temperatureDrop
|
|
471
|
+
message:
|
|
472
|
+
description: Message that is being sent when the temperature drops past a certain point.
|
|
473
|
+
payload:
|
|
474
|
+
type: object
|
|
475
|
+
additionalProperties: false
|
|
476
|
+
properties:
|
|
477
|
+
temperatureId:
|
|
478
|
+
type: string
|
|
479
|
+
|
|
480
|
+
temperature/risen:
|
|
481
|
+
description: Notifies the user when the temperature rises past a certain point.
|
|
482
|
+
publish:
|
|
483
|
+
operationId: temperatureRise
|
|
484
|
+
message:
|
|
485
|
+
description: Message that is being sent when the temperature rises past a certain point.
|
|
486
|
+
payload:
|
|
487
|
+
type: object
|
|
488
|
+
additionalProperties: false
|
|
489
|
+
properties:
|
|
490
|
+
temperatureId:
|
|
491
|
+
type: string
|
|
492
|
+
|
|
493
|
+
components:
|
|
494
|
+
schemas:
|
|
495
|
+
temperatureId:
|
|
496
|
+
type: object
|
|
497
|
+
additionalProperties: false
|
|
498
|
+
properties:
|
|
499
|
+
temperatureId:
|
|
500
|
+
type: string
|
|
501
|
+
|
|
502
|
+
```
|
|
503
|
+
#### 5c. Update TestClient.java
|
|
504
|
+
We must now update the **TestClient.java** file to test the different channels in the AsyncAPI document above. The tests will be similar to the previous ones you performed earlier. Paste the following code snippet into your **TestClient.java** file:
|
|
505
|
+
|
|
506
|
+
```java
|
|
507
|
+
import java.util.Random;
|
|
508
|
+
import java.util.concurrent.TimeUnit;
|
|
509
|
+
|
|
510
|
+
public class TestClient {
|
|
511
|
+
public static void main(String[] args) {
|
|
512
|
+
Client client = new Client();
|
|
513
|
+
Random random = new Random();
|
|
514
|
+
|
|
515
|
+
int idLength = 8;
|
|
516
|
+
int minValue = (int) Math.pow(10, idLength - 1); // Minimum 8-digit number (e.g., 10000000)
|
|
517
|
+
int maxValue = (int) Math.pow(10, idLength) - 1; // Maximum 8-digit number (e.g., 99999999)
|
|
518
|
+
System.out.println("Validating generated generated Client.java");
|
|
519
|
+
System.out.println("Running tests in TestClient.java");
|
|
520
|
+
System.out.println("Sending temperature changes to the broker...");
|
|
521
|
+
System.err.println("\n");
|
|
522
|
+
while (true) {
|
|
523
|
+
int randomId = random.nextInt(maxValue - minValue + 1) + minValue;
|
|
524
|
+
client.sendTemperatureDrop(String.valueOf(randomId));
|
|
525
|
+
System.out.println("Temperature drop detected " + randomId + " sent to temperature/dropped");
|
|
526
|
+
|
|
527
|
+
client.sendTemperatureRise(String.valueOf(randomId));
|
|
528
|
+
System.out.println("Temperature risen detected " + randomId + " sent to temperature/risen");
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
TimeUnit.SECONDS.sleep(1); // Sleep for 1 second
|
|
532
|
+
} catch (InterruptedException e) {
|
|
533
|
+
e.printStackTrace();
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Run `npm test` to validate that everything works as expected. You should see logs similar to the snippet below in your terminal:
|
|
541
|
+
|
|
542
|
+
```cmd
|
|
543
|
+
Connected to MQTT broker: tcp://test.mosquitto.org:1883
|
|
544
|
+
|
|
545
|
+
Validating generated generated Client.java
|
|
546
|
+
Running tests in TestClient.java
|
|
547
|
+
Sending temperature changes to the broker...
|
|
548
|
+
TemperatureDrop change sent: 43289900
|
|
549
|
+
Temperature drop detected 43289900 sent to temperature/dropped
|
|
550
|
+
TemperatureRise change sent: 43289900
|
|
551
|
+
Temperature risen detected 43289900 sent to temperature/risen
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## Where to go from here?
|
|
555
|
+
|
|
556
|
+
Great job completing this tutorial! You have learnt how to use an AsyncAPI file to create a Java MQTT template and used it with the Paho-MQTT library in Java to connect to an MQTT broker and publish messages.😃
|
|
557
|
+
|
|
558
|
+
If you want to tinker with a completed template and see what it would look like in production, check out the [Java-MQTT-client-template](https://github.com/ssala034/Java-MQTT-client-template). You can also check out the accompanying [article about creating MQTT client code](https://www.brainfart.dev/blog/asyncapi-codegen-python).
|
|
559
|
+
|
|
560
|
+
You can also check out the [MQTT beginners guide](https://medium.com/python-point/mqtt-basics-with-python-examples-7c758e605d4) tutorial to learn more about asynchronous messaging using MQTT.
|