The HiveMQ MQTT Client Library for Java and Its Blocking API Flavor
As a software engineer, you need a robust MQTT client library to build your IoT applications in Java. The HiveMQ MQTT library will help you handle the communication between your device and the MQTT broker. This library is a popular choice among Java developers due to its reliability and ease of use.
This three-part blog post series will examine the three API flavors of the HiveMQ MQTT Client:
Blocking
Async
Reactive
In the first post, we introduce the blocking API, a synchronous programming model easy to understand and use. The second post will dive deep into the Async API and the final and third post will introduce the Reactive API. All three articles will explore the unique features and benefits of each approach, plus provide code examples.
With the blocking API, you can easily connect to a broker, subscribe to topics, publish messages, and disconnect when finished. The API’s design is simple and intuitive, with easy-to-understand method calls that make it easy to start programming an MQTT client application. Let’s take a closer look at the blocking API and understand when to best use it.
How to get started with the Blocking 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
, to obtain the dependency:
Examples
With the blocking API, the program execution is stopped or “blocked” until an operation completes. For example, after sending a ‘CONNECT’ request to the MQTT broker, the next instruction executes only after receiving the CONNACK
from the MQTT broker. This programming style is the most intuitive of the three as it follows an imperative step-by-step execution familiar to programmers. Error handling follows the traditional try/catch pattern. To illustrate the usage of this API flavor, the following is an example of a client that subscribes to an MQTT topic and a client that publishes messages to an MQTT topic.
Blocking Publisher
Implement a blocking 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 withbuildBlocking()
.Use
connect()
to connect to the MQTT broker. Note this call blocks until the MQTT broker sends aCONNACK
message. Therefore, the client application printsSuccessfully connected!
only after a successful connection attempt. If any error occurs during connecting, the catch clause is executed.The goal is to publish 10 messages, as the blocking API favors imperative programming, so use a traditional for-loop.
Next, we use the static method
Mqtt5Publish.builder()
to build thePUBLISH
message. We provide the topic, payload, QoS and complete the instantiation withbuild()
Publish the message. Note, that this call blocks until the client library receives a
PUBACK
, only then the loop continues and the nextPUBLISH
is built and sent. This also implies that only oneQoS=1
message flow happens in parallel. If any error occurs during publishing, they are handled in the catch clause.After we sent all 10
PUBLISH
messages and received all 10PUBACK
messages, we printSuccessfully published!
.To disconnect, we use
disconnect()
. The catch clause handles every error that occurs during disconnecting. After successfully disconnecting from the MQTT broker, the program writesSuccessfully disconnected!
to the console.
Blocking Subscriber
To implement a blocking 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 withbuildBlocking()
.Before connecting use
publishes(MqttGlobalPublishFilter.ALL)
to register aMqtt5Publishes
object that holds all incomingPUBLISH
messages. Registering theMqtt5Publishes
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 theMqtt5Publishes
object is ready to handle them, resulting in lost messages.Use
connect()
to connect to the MQTT broker. Note, this call blocks until the MQTT broker sends aCONNACK
message. Therefore, the application printsSuccessfully connected!
only after a successful connection attempt. If any error occurs during connecting, the catch clause is executed.After a successful connection attempt, we use
subscribeWith()
to start building aSUBSCIBE
message. Provide the topic filter and usesend()
to write theSUBSCRIBE
message to the MQTT broker. Note, that this call blocks until the application receives theSUBACK
. Only after that,Successfully subscribed!
is printed. If any error occurs the catch clause handles them.Now, we use the
Mqtt5Publishes
object from step 2 to work with incoming publishes. Thepublishes.receive()
call halts the execution of the program until the application receives an incomingPUBLISH
message. After we obtain anMqtt5Publish
we can log the payload to the console. To receive further publishes, use a while-loop. Usingwhile(true)
is only for demonstration purposes, the application will only stop after being externally terminated.
Switching API Flavor
The HiveMQ MQTT Client allows you to simply switch to the reactive or async API flavor using toAsync()
or toRx()
. This enables you to choose the API style best fitted for each part of your application. This example shows you how to switch from the blocking API flavor to the async API flavor which is explained in the second post of this series. It also illustrates how to switch from the blocking API flavor to the reactive API flavor from the third and last post in the series.
Conclusion
In conclusion, the blocking API of the HiveMQ MQTT Client is a powerful tool for developing MQTT clients in Java. It allows you to write code in a linear, step-by-step manner. This makes it easier to understand the flow of control. With blocking APIs, you can simply call a method and wait for the response to return before continuing with the next step in your program. Although easy to understand, the blocking API does not allow you the possibility to use threads efficiently. Therefore, we recommend using the blocking flavor only when performance and latency are no issue, for example in automated tests. If you’re interested in writing an application with a more efficient threading model, consider looking at the Async flavor or the Reactive flavor of the HiveMQ MQTT Client. In the next posts in this series, we will introduce these flavors and explain how they can help you to build highly performant and scalable MQTT-based applications. Stay tuned to learn more about these powerful tools!
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.