AsyncAPI Conference

Lagos Edition

18th - 19th of July, 2025 | Lagos, Nigeria

1 day until the end of Call for Speakers

Creating a template - Java

Found an error? Have a suggestion?Edit this page on GitHub

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.

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 but with a few differences and Java flair. This will help developers practice with AsyncAPI generator tool using statically typed language Java.

Prerequisites

To run it, ensure you have Java JDK 8 or higher, Gradle, and the AsyncAPI generator.

Overview of Java Template

In this section, you'll:

  1. Create a new directory to run Java code.
  2. Create the Java client.
  3. Test the Java Client
  4. Output Java template code.
  5. Create more channels

1. Create a new directory to run Java code

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.

Once that is done, you should create some new sub-directories to begin building your Java client.

  1. Create a new subdirectory called src
  2. Change into src and create two new subdirectories: fixtures and main/java.
  3. Create a file named asyncapi.yml in your fixtures directory and paste the asyncapi.yml document mentioned here into it.
  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.
  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.
  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.

Now your directory should look like this:

1java-mqtt-client-template 
2├── src
3|   └── fixtures
4|       └── asyncapi.yml
5│   └── main/java
6├── template
7|   └── index.js
8└── package.json
9└── build.gradle

Note: The client.java code must be in your src/main/java directory, or else Gradle won't build your application.

Java - package.json file

Add the following code snippet to your package.json file:

1{
2    "name": "java-mqtt-client-template",
3    "version": "0.0.1",
4    "description": "A template that generates a Java MQTT client using MQTT.",
5    "generator": {
6      "renderer": "react",
7      "apiVersion": "v1",
8      "generator": ">=1.10.0 <2.0.0",
9      "supportedProtocols": ["mqtt"]
10    },
11    "dependencies": {
12      "@asyncapi/generator-react-sdk": "^0.2.25"
13    },
14    "devDependencies": {
15      "rimraf": "^5.0.0"
16    }
17}

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.

Java - index.js file

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:

1//1
2import { File } from '@asyncapi/generator-react-sdk'
3//2
4export default function ({ asyncapi }) {
5//3
6  return <File name="Client.java">{asyncapi.info().title()}</File>
7}

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.

1Generation in progress. Keep calm and wait a bit... done
2Check out your shiny new generated files at test/project.

2. Create the Java client

2a. Setting up Gradle

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.

1plugins {
2    id 'java'
3    id 'application'
4}
5
6repositories {
7    mavenCentral()
8}
9
10dependencies {
11    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
12}
13
14application{
15    mainClass = project.hasProperty('mainClass') ? project.mainClass : 'Client'  // Default to 'Client' if no property is passed
16}

Here's what is contained in the code snippet above:

  • plugins - This section defines the plugins applied to the Gradle project.
    • id 'java' - This applies the Java plugin, which allows you to compile and run Java code.
    • id 'application' - This plugin is used to support building and running applications. It helps with creating an executable JAR.
  • repositories - This section tells you app to fetch dependencies from Maven Central to retrieve the MQTT client library.
  • dependencies - This specifies that the project depends on the Eclipse Paho MQTT client version 1.2.5, which is needed to compile and run.
  • 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.

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.

2b. Beefing up Client.java

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.

1import org.eclipse.paho.client.mqttv3.*;
2
3public class Client {
4    private static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
5    private static final String TOPIC = "temperature/changed";
6
7    private MqttClient client;
8
9    public Client() {
10        try {
11            // Generate a unique client ID
12            String clientId = MqttClient.generateClientId();
13                    
14            // Create and connect the MQTT client
15            client = new MqttClient(BROKER_URL, clientId);
16            MqttConnectOptions options = new MqttConnectOptions();
17            options.setCleanSession(true);
18                    
19            client.connect(options);
20            System.out.println("Connected to MQTT broker: " + BROKER_URL);
21        } catch (MqttException e) {
22            e.printStackTrace();
23        }
24    }
25     public void sendTemperatureChange(String id) {
26        try {
27            // Publish the message with the temperature change
28            MqttMessage message = new MqttMessage(id.getBytes());
29            client.publish(TOPIC, message);
30        } catch (MqttException e) {
31            e.printStackTrace();
32        }
33    }
34}

3. Test the Java Client

Create a src/main/java/TestClient.java file in your project and add the code snippet below.

Your directory should now look like this:

1java-mqtt-client-template 
2├── src
3|   └── fixtures
4|       └── asyncapi.yml
5│   └── main/java
6|       └── Client.java
7|       └── TestClient.java
8├── template
9|   └── index.js
10└── package.json
11└── build.gradle
1import java.util.Random;
2import java.util.concurrent.TimeUnit;
3
4public class TestClient {
5    public static void main(String[] args) {
6        Client client = new Client();
7        Random random = new Random();
8
9        int idLength = 8;
10        int minValue = (int) Math.pow(10, idLength - 1); // Minimum 8-digit number (e.g., 10000000)
11        int maxValue = (int) Math.pow(10, idLength) - 1; // Maximum 8-digit number (e.g., 99999999)
12        System.out.println("Validating generated generated Client.java");
13        System.out.println("Running tests in TestClient.java");
14        System.out.println("Sending temperature changes to the broker...");
15        System.err.println("\n");
16        while (true) {
17            int randomId = random.nextInt(maxValue - minValue + 1) + minValue;
18            client.sendTemperatureChange(String.valueOf(randomId));
19            System.out.println("New temperature detected " + randomId + " sent to temperature/changed");
20
21            try {
22                TimeUnit.SECONDS.sleep(1); // Sleep for 1 second
23            } catch (InterruptedException e) {
24                e.printStackTrace();
25            }
26        }
27    }
28}

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:

1New temperature detected 64250266 sent to temperature/changed
2New temperature detected 36947728 sent to temperature/changed
3New temperature detected 72955029 sent to temperature/changed

4. Output Java template code.

Open index.js and copy the content below so your file looks like the code snippet below:

1//1
2import { File } from '@asyncapi/generator-react-sdk'
3//2
4export default function ({ asyncapi }) {
5//3
6  return <File name="Client.java">
7  {`
8
9import org.eclipse.paho.client.mqttv3.*;
10public class Client {
11    private static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
12    private static final String TOPIC = "temperature/changed";
13
14    private MqttClient client;
15
16    public Client() {
17        try {
18            // Generate a unique client ID
19            String clientId = MqttClient.generateClientId();
20                    
21            // Create and connect the MQTT client
22            client = new MqttClient(BROKER_URL, clientId);
23            MqttConnectOptions options = new MqttConnectOptions();
24            options.setCleanSession(true);
25                    
26            client.connect(options);
27            System.out.println("Connected to MQTT broker: " + BROKER_URL);
28        } catch (MqttException e) {
29            e.printStackTrace();
30        }
31    }
32     public void sendTemperatureChange(String id) {
33        try {
34            // Publish the message with the temperature change
35            MqttMessage message = new MqttMessage(id.getBytes());
36            client.publish(TOPIC, message);
37        } catch (MqttException e) {
38            e.printStackTrace();
39        }
40    }
41}`
42  }</File>
43}

4a. Write the script to run the test code

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:

1   {
2    "name": "java-mqtt-client-template",
3    "version": "0.0.1",
4    "description": "A template that generates a Java MQTT client using MQTT.",
5    "generator": {
6      "renderer": "react",
7      "apiVersion": "v1",
8      "generator": ">=1.10.0 <2.0.0",
9      "supportedProtocols": ["mqtt"],
10      "parameters": {
11            "server": {
12              "description": "The server you want to use in the code.",
13              "required": true
14            }
15        }
16    },
17    "scripts": {
18        "test:clean": "rimraf src/main/java/Client.java",
19        "test:generate": "asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java --force-write --param server=dev",
20        "test:start": "gradle run -PmainClass=TestClient",
21        "test": "npm run test:clean && npm run test:generate && npm run test:start"
22    },
23    "dependencies": {
24      "@asyncapi/generator-react-sdk": "^0.2.25"
25    },
26    "devDependencies": {
27      "rimraf": "^5.0.0"
28    }
29  }

Run npm test to see if everything is working.

5. Create more channels

5a. Creating more reusable components

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.

Create a components directory at the root of your project and create a file named TopicFunction.js and add the code snippet below:

1/*
2 * This component returns a block of functions that users can use to send messages to specific topics.
3 * As input it requires a list of Channel models from the parsed AsyncAPI document.
4 */
5export function TopicFunction({ channels }) {
6  const topicsDetails = getTopics(channels);
7  let functions = '';
8
9  topicsDetails.forEach((t) => {
10    functions += `
11    public void send${t.name}(String id) {
12        String topic = "${t.topic}";
13        try {
14            MqttMessage message = new MqttMessage(id.getBytes());
15            client.publish(topic, message);
16            System.out.println("${t.name} change sent: " + id);
17        } catch (MqttException e) {
18            e.printStackTrace();
19        }
20    }\n`;
21  });
22
23  return functions;
24}
25  
26  /*
27   * This function returns a list of objects, one for each channel, each containing two properties: `name` and `topic`.
28   * name - holds information about the `operationId` definedin the AsyncAPI document
29   * topic - holds information about the topic's address.
30   *
31   * It requires as input, a list of Channel models from the parsed AsyncAPI document.
32   */
33  function getTopics(channels) {
34    const channelsCanSendTo = channels
35    let topicsDetails = []
36  
37    channelsCanSendTo.forEach((ch) => {
38      const topic = {}
39      const operationId = ch.operations().filterByReceive()[0].id()
40      topic.name = operationId.charAt(0).toUpperCase() + operationId.slice(1)
41      topic.topic = ch.address()
42  
43      topicsDetails.push(topic)
44    })
45  
46    return topicsDetails
47  }
48

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:

1import { File, Text } from '@asyncapi/generator-react-sdk';
2import { TopicFunction } from '../components/TopicFunction'
3
4export default function ({ asyncapi, params }) {
5    let channels = asyncapi.channels().filterByReceive();  // Get all the channels that receive messages
6
7    // Generate Java code for each topic dynamically using TopicFunction
8    const topicMethods = TopicFunction({ channels });  // This will return Java methods as text
9    
10    return (
11    <File name="Client.java">
12    {
13      
14`import org.eclipse.paho.client.mqttv3.*;
15
16public class Client {
17    private static final String BROKER_URL = "${asyncapi.servers().get(params.server).url()}";
18    private static final String TOPIC = "temperature/changed";
19
20    private MqttClient client;
21
22    public Client() {
23        try {
24            // Generate a unique client ID
25            String clientId = MqttClient.generateClientId();
26                    
27            // Create and connect the MQTT client
28            client = new MqttClient(BROKER_URL, clientId);
29            MqttConnectOptions options = new MqttConnectOptions();
30            options.setCleanSession(true);
31                    
32            client.connect(options);
33            System.out.println("Connected to MQTT broker: " + BROKER_URL);
34        } catch (MqttException e) {
35            e.printStackTrace();
36        }
37    }
38
39    ${topicMethods}
40
41    public static void main(String[] args) {
42        Client serviceClient = new Client();
43                
44        // Simulate sending a temperature change
45        //serviceClient.sendTemperatureDrop("Sensor-1: 25°C");
46    }
47}`
48    }
49    </File>
50  );
51}

Now your directory should look like this:

1java-mqtt-client-template 
2├── components
3|   └── TopicFunction.js
4├── src
5|   └── fixtures
6|       └── asyncapi.yml
7│   └── main/java
8|       └── Client.java
9|       └── TestClient.java
10├── template
11|   └── index.js
12└── package.json
13└── build.gradle

5b. Update AsyncAPI document with more channels

Add the following AsyncAPI document to have more channels:

1asyncapi: 2.6.0
2
3info:
4  title: Temperature Service
5  version: 1.0.0
6  description: This service is in charge of processing all the events related to temperature.
7
8servers:
9  dev:
10    url: tcp://test.mosquitto.org:1883
11    protocol: mqtt
12
13channels:
14  temperature/dropped:
15    description:  Notifies the user when the temperature drops past a certain point.
16    publish:
17      operationId: temperatureDrop
18      message:
19        description: Message that is being sent when the temperature drops past a certain point.
20        payload:
21          type: object
22          additionalProperties: false
23          properties:
24            temperatureId:
25              type: string
26
27  temperature/risen:
28    description: Notifies the user when the temperature rises past a certain point.
29    publish:
30      operationId: temperatureRise
31      message:
32        description: Message that is being sent when the temperature rises past a certain point.
33        payload:
34          type: object
35          additionalProperties: false
36          properties:
37            temperatureId:
38              type: string
39
40components:
41  schemas:
42    temperatureId:
43      type: object
44      additionalProperties: false
45      properties:
46        temperatureId:
47          type: string
48

5c. Update TestClient.java

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:

1import java.util.Random;
2import java.util.concurrent.TimeUnit;
3
4public class TestClient {
5    public static void main(String[] args) {
6        Client client = new Client();
7        Random random = new Random();
8
9        int idLength = 8;
10        int minValue = (int) Math.pow(10, idLength - 1); // Minimum 8-digit number (e.g., 10000000)
11        int maxValue = (int) Math.pow(10, idLength) - 1; // Maximum 8-digit number (e.g., 99999999)
12        System.out.println("Validating generated generated Client.java");
13        System.out.println("Running tests in TestClient.java");
14        System.out.println("Sending temperature changes to the broker...");
15        System.err.println("\n");
16        while (true) {
17            int randomId = random.nextInt(maxValue - minValue + 1) + minValue;
18            client.sendTemperatureDrop(String.valueOf(randomId));
19            System.out.println("Temperature drop detected " + randomId + " sent to temperature/dropped");
20            
21            client.sendTemperatureRise(String.valueOf(randomId));
22            System.out.println("Temperature risen detected " + randomId + " sent to temperature/risen");
23
24            try {
25                TimeUnit.SECONDS.sleep(1); // Sleep for 1 second
26            } catch (InterruptedException e) {
27                e.printStackTrace();
28            }
29        }
30    }
31}

Run npm test to validate that everything works as expected. You should see logs similar to the snippet below in your terminal:

1Connected to MQTT broker: tcp://test.mosquitto.org:1883
2
3Validating generated generated Client.java
4Running tests in TestClient.java
5Sending temperature changes to the broker...
6TemperatureDrop change sent: 43289900
7Temperature drop detected 43289900 sent to temperature/dropped
8TemperatureRise change sent: 43289900
9Temperature risen detected 43289900 sent to temperature/risen

Where to go from here?

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.😃

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. You can also check out the accompanying article about creating MQTT client code.

You can also check out the MQTT beginners guide tutorial to learn more about asynchronous messaging using MQTT.

Was this helpful?
Help us improve the docs by adding your contribution.
OR
Github:AsyncAPICreate Issue on GitHub