Core Java

Messaging with HiveMQ MQTT Client

The HiveMQ MQTT Client is a Java library that enables applications to communicate using the MQTT (Message Queuing Telemetry Transport) protocol. It supports MQTT V3.x and MQTT V5.0 and provides multiple programming models, including blocking and asynchronous APIs. These programming models allow us to choose between simple synchronous execution and scalable non-blocking communication.

The library is widely used in IoT (Internet of Things) systems because MQTT is a lightweight publish-subscribe protocol that enables efficient message exchange between devices and servers through a broker. It provides features such as automatic reconnect, secure communication, and flexible message handling, which make it suitable for both small and enterprise systems.

This article focuses on the asynchronous model, which is commonly used in real-time applications such as IoT devices, event streaming systems, and messaging platforms.

1. Project Dependencies

    <dependencies>
        <dependency>
            <groupId>com.hivemq</groupId>
            <artifactId>hivemq-mqtt-client</artifactId>
            <version>1.3.13</version>
        </dependency>
    </dependencies>

The above configuration includes the HiveMQ MQTT Client dependency.

2. Creating MQTT Clients

The asynchronous client is created using a builder provided by the HiveMQ library.

public class MqttService {

    public static Mqtt5AsyncClient createClient(String clientId) {
        return Mqtt5Client.builder()
                .identifier(clientId)
                .serverHost("broker.hivemq.com")
                .serverPort(1883)
                .buildAsync();
    }
}

This method creates a reusable asynchronous MQTT client configured to connect to the public HiveMQ broker. The buildAsync() method ensures that all operations are non-blocking.

Creating a Blocking Client

    public static Mqtt5BlockingClient createClient() {
        return Mqtt5Client.builder()
                .identifier("blocking-client")
                .serverHost("broker.hivemq.com")
                .serverPort(1883)
                .buildBlocking();
    }

This code creates a blocking MQTT client using the builder API. The client executes operations synchronously, meaning each operation waits for completion before the next begins.

Connecting to the Broker

The asynchronous client connects to the broker using a non-blocking operation that returns a completion stage.

        Mqtt5AsyncClient client = MqttService.createClient("subscriber");
        client.connect().join();

The connect method initiates a connection to the broker and can register a callback using whenComplete. The join() method ensures the client is fully connected before proceeding to subscribe or publish messages.

3. Subscribing to a Topic

This application listens for messages published to a specific MQTT topic. It connects to the broker, subscribes to a topic, and prints any incoming messages to the console in real time.

 public class Subscriber {

    void main() {

        Mqtt5AsyncClient client = MqttService.createClient("subscriber");

        client.connect().join();
        IO.println("Subscriber connected");

        client.subscribeWith()
                .topicFilter("demo/topic")
                .callback(publish -> {
                    String msg = new String(publish.getPayloadAsBytes(), StandardCharsets.UTF_8);

                    IO.println("Received: " + msg);
                })
                .send()
                .join();

        IO.println("Subscriber listening on demo/topic");
    }
}

The Subscriber class creates an asynchronous MQTT client using a unique client identifier. It connects to the broker using connect().join() to ensure the connection is fully established before continuing. After connecting, it subscribes to the topic demo/topic.

The callback method is triggered whenever a message is received on that topic, converting the payload from bytes into a readable string and printing it to the console. The use of join() ensures that the subscription is successfully registered before the application continues running, making the subscriber ready to receive messages immediately.

4. Publishing Messages

This application sends messages to the same MQTT topic that the subscriber is listening to. Each message is published asynchronously and acknowledged by the broker.

public class Publisher {

    void main() {

        Mqtt5AsyncClient client = MqttService.createClient("publisher");

        client.connect().join();
        IO.println("Publisher connected");

        publish(client, "Hello from Java Publisher");
        publish(client, "Second message");
        publish(client, "MQTT is working!");

        client.disconnect().join();
        IO.println("Publisher disconnected");
    }

    private static void publish(Mqtt5AsyncClient client, String message) {

        client.publishWith()
                .topic("demo/topic")
                .payload(message.getBytes(StandardCharsets.UTF_8))
                .qos(MqttQos.EXACTLY_ONCE)
                .retain(true)
                .send()
                .join();

        IO.println("Published: " + message);
    }
}

The Publisher class creates an asynchronous MQTT client with a different client identifier to avoid conflicts with the subscriber. It connects to the broker and then publishes multiple messages to the demo/topic. Each message is converted into a byte array before being sent. The use of join() after send() ensures that each message is fully acknowledged by the broker before moving to the next one.

Finally, the client disconnects after all messages have been published, ensuring proper resource cleanup and preventing background threads from lingering.

Verification Flow

To see the MQTT communication:

Step 1: Start Subscriber – Terminal 1:

mvn compile exec:java -Dexec.mainClass="com.jcg.example.Subscriber"

Subscriber waits:

Subscriber connected
Subscriber listening on demo/topic

Step 2: Start Publisher – Terminal 2:

mvn compile exec:java -Dexec.mainClass="com.jcg.example.Publisher"

Expected Publisher Output:

Publisher connected
Published: Hello from Java Publisher
Published: Second message
Published: MQTT is working!
Publisher disconnected

Step 3: Observe Subscriber Output – Back in Terminal 1:

Received: Hello from Java Publisher
Received: Second message
Received: MQTT is working!
  • Both apps connect to the same broker: broker.hivemq.com
  • Publisher sends messages to demo/topic
  • Broker routes messages to all subscribers of that topic
  • Subscriber receives messages instantly via callback
Important Notes

  • Client IDs must be unique
  • Subscriber must start first. Otherwise messages may be missed.
  • Keep subscriber running. It is event driven and does not exit automatically.

5. Conclusion

In this article, a messaging system was built using the HiveMQ MQTT Client in Java. The implementation demonstrated how to create publisher and subscriber applications, connect them to a shared MQTT broker, and exchange messages through a common topic.

6. Download the Source Code

This article provided an introduction to the HiveMQ MQTT Client.

Download
You can download the full source code of this example here: hivemq mqtt client

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button