HiveMQ MQTT Client

repository·master·Indexed 22 days ago

https://github.com/hivemq/hivemq-mqtt-client

A high-performance Java client library for MQTT 3.1.1 and 5.0. It features three API flavors—Reactive (RxJava/Reactor), Asynchronous (CompletableFuture), and Blocking—and provides robust backpressure support, TCP/SSL/TLS/WebSocket transports, and proxy support (SOCKS4, SOCKS5, HTTP CONNECT). The library includes specialized features for MQTT 5, such as pluggable Enhanced Authentication and Topic Alias mapping.

Tokens
3.4K
Snippets
8
Records
12
Agent score
28%

What's inside hivemq-mqtt-client

  1. Core features and capabilities

    master

    The HiveMQ MQTT Client is a high-performance library supporting MQTT 3.1.1 and 5.0 with the following key capabilities:

    • Backpressure Support: Supports QoS 1 and 2, and QoS 0 (via dropping incoming messages). It integrates MQTT flow control with reactive pull backpressure.
    • Transports: Supports TCP, SSL/TLS (up to TLS 1.3, including mutual authentication, SNI, and session resumption), WebSockets, and Secure WebSockets.
    • Proxy Support: SOCKS4, SOCKS5, and HTTP CONNECT.
    • Reliability: Automatic and configurable thread management, reconnect handling, message redelivery, and automatic resubscription if a session expires.
    • Manual Acknowledgment: Allows selective manual acknowledgment for specific streams. The client ensures MQTT-compliant ordering of acknowledgments regardless of the order in which they are received.
    • MQTT 5 Specifics: Pluggable Enhanced Authentication, automatic Topic Alias mapping, and interceptors for QoS flows.
  2. Understand the three API flavours

    master

    The HiveMQ MQTT Client provides three distinct API styles to suit different programming models. You can switch between these styles at any time using the provided switch methods.

    1. Blocking API: Synchronous calls that block the current thread until the operation completes. Best for simple scripts or linear logic.
    2. Async API: Non-blocking calls that return CompletableFuture. Best for high-performance applications using standard Java concurrency.
    3. Reactive API: Uses reactive streams (RxJava types like Single, Flowable, Completable). Best for complex event-driven logic and handling backpressure.
    // Switching between API styles
    Mqtt5Client client = Mqtt5Client.builder().buildAsync();
    
    Mqtt5BlockingClient blockingClient = client.toBlocking();
    Mqtt5AsyncClient asyncClient = client.toAsync();
    Mqtt5RxClient rxClient = client.toRx();
  3. Understand the API flavors

    master

    The HiveMQ MQTT Client provides three distinct API flavors that can be used concurrently or switched between flexibly. All flavors follow a consistent, fluent API style.

    • Reactive API: Compatible with Reactive Streams, providing APIs for RxJava and Reactor.
    • Asynchronous API: Uses futures and callbacks.
    • Blocking API: A simple API designed for quick starts and testing.
  4. Respect API boundaries and DoNotImplement annotations

    master

    To ensure your integration remains stable across library updates, follow these two rules:

    1. Avoid internal packages: Do not use any code located within com.hivemq.client.internal packages. These are not part of the public API and are subject to change without notice.
    2. Do not implement annotated interfaces: If an interface is annotated with @DoNotImplement, do not attempt to provide your own implementation. These interfaces are managed by the library to allow for future method additions without breaking backwards compatibility.
  5. Consume messages with `publishes()`

    master

    To ensure no messages are lost, you should call client.publishes(...) before calling subscribe. This allows the client to buffer messages that arrive immediately after a subscription is initiated.

    Additionally, calling publishes() before connect() allows you to receive messages from a previous session if a persistent session is used.

    Available Filters:

    • MqttGlobalPublishFilter.ALL: Receives all incoming messages.
  6. Use the Async API

    master

    The Async API provides non-blocking operations that return CompletableFuture. You can initialize it via .buildAsync() or switch using .toAsync().

    Common Operations

    • Connect/Publish/Subscribe/Unsubscribe/Disconnect: These methods are analogous to the Blocking API but return CompletableFuture instead of blocking.
    • Per-Subscribe Consumption: You can provide a callback directly during subscription:
      client.subscribeWith()
            .topicFilter("test/topic")
            .callback(System.out::println)
            .send();
    • Global Consumption:
      client.publishes(MqttGlobalPublishFilter.ALL, System.out::println);
    Mqtt5AsyncClient client = Mqtt5Client.builder()
            .identifier(UUID.randomUUID().toString())
            .serverHost("broker.hivemq.com")
            .buildAsync();
    
    client.connect()
            .thenCompose(connAck -> client.publishWith().topic("test/topic").payload("1".getBytes()).send())
            .thenCompose(publishResult -> client.disconnect());
  7. Install HiveMQ MQTT Client via Maven

    master

    To use the HiveMQ MQTT Client in a Maven project, add the dependency to your pom.xml. Ensure your maven.compiler.source and maven.compiler.target are set to 1.8 or higher.

    <project>
        <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.hivemq</groupId>
                <artifactId>hivemq-mqtt-client</artifactId>
                <version>1.3.17</version>
            </dependency>
        </dependencies>
    </project>
  8. Use the Reactive API

    master

    The Reactive API uses RxJava types to handle MQTT streams. It is initialized via .buildRx() or switched via .toRx().

    Key Reactive Types

    • Single<T>: Represents a single asynchronous value (e.g., connect() returns Single<Mqtt5ConnAck>).
    • Flowable<T>: Represents an asynchronous stream of values (e.g., publishes() returns a Flowable).
    • Completable: Represents an asynchronous operation that completes without emitting a value (e.g., disconnect()).
    • FlowableWithSingle<T, R>: A combination of a single value and a stream (e.g., subscribeStreamWith() returns a FlowableWithSingle containing the SubAck and the matching Publish messages).

    Subscription Patterns

    • Stream Subscription: Use subscribeStreamWith() to get a stream of messages directly.
    • Global Stream: client.publishes(MqttGlobalPublishFilter.ALL) returns a Flowable of all incoming messages.
    Mqtt5RxClient client = Mqtt5Client.builder()
            .identifier(UUID.randomUUID().toString())
            .serverHost("broker.hivemq.com")
            .buildRx();
    
    // Example: Connecting and then subscribing to a stream
    Completable connectScenario = client.connect()
            .doOnSuccess(connAck -> System.out.println("Connected"))
            .ignoreElement();
    
    FlowableWithSingle<Mqtt5Publish, Mqtt5SubAck> subAckAndMatchingPublishes = client.subscribeStreamWith()
            .topicFilter("a/b/c").qos(MqttQos.AT_LEAST_ONCE)
            .applySubscribe();
    
    Completable subscribeScenario = subAckAndMatchingPublishes
            .doOnNext(publish -> System.out.println("Received: " + publish.getTopic()))
            .ignoreElements();
    
    connectScenario.andThen(subscribeScenario).blockingAwait();
  9. Use the shaded version of HiveMQ MQTT Client

    master

    If you encounter transitive dependency conflicts, use the shaded version. This version bundles internal transitive dependencies under a different package name. The shaded version includes the websocket, proxy, and epoll modules by default.

    // Gradle
    dependencies {
      implementation("com.hivemq:hivemq-mqtt-client-shaded:1.3.17")
    }
    <!-- Maven -->
    <dependency>
        <groupId>com.hivemq</groupId>
        <artifactId>hivemq-mqtt-client-shaded</artifactId>
        <version>1.3.17</version>
    </dependency>
  10. Install HiveMQ MQTT Client via Gradle

    master

    To use the HiveMQ MQTT Client in a Gradle project, add the core dependency to your build.gradle(.kts) file. Java 8 or higher is required.

    For optional features like WebSockets, Proxies, Epoll, or Reactor support, include the corresponding modules using implementation(platform(...)) for the platform BOM or direct implementation.

    dependencies {
      implementation("com.hivemq:hivemq-mqtt-client:1.3.17")
    }
    
    // Optional features
    dependencies {
      implementation(platform("com.hivemq:hivemq-mqtt-client-websocket:1.3.17"))
      implementation(platform("com.hivemq:hivemq-mqtt-client-proxy:1.3.17"))
      implementation(platform("com.hivemq:hivemq-mqtt-client-epoll:1.3.17"))
      implementation("com.hivemq:hivemq-mqtt-client-reactor:1.3.17")
    }
  11. Use the Blocking API

    master

    The Blocking API is used for synchronous MQTT operations. You can initialize it via the builder using .buildBlocking() or switch from another client using .toBlocking().

    Common Operations

    • Connect: client.connect() or client.connectWith()...send().
    • Publish: client.publishWith()...send() or client.publish(Mqtt5Publish).
    • Subscribe: client.subscribeWith()...send() or client.subscribe(Mqtt5Subscribe).
    • Unsubscribe: client.unsubscribeWith()...send() or client.unsubscribe(Mqtt5Unsubscribe).
    • Disconnect: client.disconnect() or client.disconnectWith()...send().
    • Consume Messages: Use client.publishes(MqttGlobalPublishFilter.ALL) to get a Mqtt5Publishes object. Call this before subscribing to ensure no messages are lost.
    final Mqtt5BlockingClient client = Mqtt5Client.builder()
            .identifier(UUID.randomUUID().toString())
            .serverHost("broker.hivemq.com")
            .buildBlocking();
    
    client.connect();
    
    try (final Mqtt5Publishes publishes = client.publishes(MqttGlobalPublishFilter.ALL)) {
        client.subscribeWith().topicFilter("test/topic").qos(MqttQos.AT_LEAST_ONCE).send();
    
        // Receive with timeout
        publishes.receive(1, TimeUnit.SECONDS).ifPresent(System.out::println);
    } finally {
        client.disconnect();
    }
  12. Create an MQTT client

    master

    Clients are created using fluent builders. You can use the generic MqttClient.builder() and specify the version, or use version-specific builders (Mqtt3Client.builder() or Mqtt5Client.builder()) if the version is known upfront.

    // Using the generic builder with version specification
    Mqtt5Client client = MqttClient.builder()
            .identifier(UUID.randomUUID().toString())
            .serverHost("broker.hivemq.com")
            .useMqttVersion5()
            .build();
    
    Mqtt3Client client3 = MqttClient.builder()
            .useMqttVersion3()
            .build();
    
    // Using version-specific builders
    Mqtt5Client client5 = Mqtt5Client.builder().build();
    Mqtt3Client client3Specific = Mqtt3Client.builder().build();