The HiveMQ MQTT Client Library for Java and Its Async API Flavor
In this second part of the series on the three API flavors of the HiveMQ MQTT Client, we will take a closer look at the async flavor of the HiveMQ MQTT Client API. As opposed to the blocking API, which provides a synchronous programming model, the async API allows for asynchronous programming, which enables us to implement a more efficient threading model.
Here is an example illustrating the difference between the blocking API flavor and the async API flavor: When sending a CONNECT
message to the MQTT broker with the blocking API, the current thread is blocked until the client library receives a CONNACK
. The thread is blocked during this time and can not be utilized to execute tasks.
In the async API flavor, the current thread is not blocked between sending the CONNECT
and receiving the CONNACK
. Instead, we tell the application what to do once the CONNACK
arrives. Therefore, the current thread can execute tasks, while the client library waits for the CONNACK
.
How to get started with the Async API of the HiveMQ MQTT Client in Java
To start, you will need the HiveMQ MQTT Client library.
Assuming your project uses Gradle add this to your build.gradle.kts
, in order to obtain the dependency:
Examples
When using the async API flavor, each instruction returns a CompletableFuture
; it is a class that represents a computation result that may be completed asynchronously in the future either successfully or exceptionally. CompletableFutures
allow for chaining and combining multiple asynchronous operations. We use the CompletableFuture
to attach handling that executes once the operation is completed.
Async Publisher
You can implement an async publisher as follows:
Use the static method
Mqtt5Client.builder()
to obtain a builder. Provide the client identifier, the MQTT broker host and port. Finish the building process withbuildAsync()
.Use
connect()
to connect to the MQTT broker. Note this call instantly returns aCompletableFuture
. That future completes once the client library receives aCONNACK
.Use
thenCompose
to attach handling to theCompletableFuture
that was returned byconnect()
.First, state that the connection was successful.
Inside the callback use a for-loop to publish 10 messages.
Next, use the static method
Mqtt5Publish.builder()
to build thePUBLISH
message. Provide the topic, payload, QoS and complete the instantiation withbuild()
Instruct the client library to publish the message. Obtain the returned future and add it to the list. As this call does not wait for the
PUBACK
from the MQTT broker to send anotherPUBLISH
, the message flows are in parallel.Combine all publish-futures into a single future that is completed once all publish futures are completed.
Attach a callback that reports
Successfully published!
and disconnects the MQTT client.Attach another callback to the disconnect-future that reports
Successfully disconnected!
.The
exceptionally
method helps us to attach error handling, if one occurs during the steps above.
Async Subscriber
To implement an async subscriber do the following:
Use the static method
Mqtt5Client.builder()
to obtain a builder. Provide the client identifier, the MQTT broker host and port. Finish the building process withbuildAsync()
.Before connecting, use
publishes()
to register a callback. The client library invokes that callback every time it receives an incomingPUBLISH
message. Registering the callback before connecting to the MQTT broker is a good practice because it ensures no messages are lost during the connection process. This is because the callback is responsible for handling incoming messages. If it is not registered before connecting, messages can arrive before the callback is ready to handle them, resulting in lost messages.Use
connect()
to connect to the MQTT broker. Note this call instantly returns aCompletableFuture
. That future completes once the client library receives aCONNACK
.Use
thenCompose
to attach handling to theCompletableFuture
that was returned byconnect()
.First, state that the connection was successful.
Second, instruct the client library to send a
SUBSCRIBE
message to the MQTT broker. This call also returns instantly with aCompletableFuture
.
Attach a callback to the subscribe-future that prints
Successfully subscribed!
once the subscribe future is complete.The
exceptionally
method helps us to attach error handling, if an error occurs during the steps above.
Switching API Flavor
The HiveMQ MQTT Client allows you to simply switch to the blocking or reactive API flavor using toBlocking()
or toRx()
. This will enable you to choose the API style best fitted for each part of your application. The following example shows you how to switch from the async API flavor to the blocking API flavor broken down in the first post of this series. It also illustrates how to switch from the async API flavor to the reactive API flavor that we discuss in the third and last post in the series.
Conclusion
To conclude, the async flavor of the HiveMQ MQTT Client API provides a powerful tool for developers who want to build highly performant and scalable MQTT applications. While it may be less intuitive than the blocking API, the async API allows for asynchronous programming, which enables a more efficient threading model and can lead to significant performance gains.
To fully take advantage of the async API, developers must be familiar with asynchronous programming concepts in Java, such as CompletableFutures. However, even if they are not, the async API is still a great way to get started with asynchronous programming in Java.
Overall, the Async flavor of the HiveMQ MQTT Client API is a valuable addition to any developer’s toolkit. By leveraging the power of asynchronous programming, developers can build applications that can handle large volumes of data, while still maintaining high performance and scalability.
HiveMQ Team
The HiveMQ team loves writing about MQTT, Sparkplug, Industrial IoT, protocols, how to deploy our platform, and more. We focus on industries ranging from energy, to transportation and logistics, to automotive manufacturing. Our experts are here to help, contact us with any questions.