Skip to main content

Overview

The HiveMQ Extension SDK provides the Java API for developing HiveMQ extensions. The SDK defines interfaces for authentication, authorization, client initialization, packet interception, and service access.

SDK Dependency

Maven

Add the HiveMQ Extension SDK to your pom.xml:
<dependency>
    <groupId>com.hivemq</groupId>
    <artifactId>hivemq-extension-sdk</artifactId>
    <version>4.28.0</version>
    <scope>provided</scope>
</dependency>
Use provided scope because HiveMQ provides the SDK at runtime.

Gradle

Add the SDK to your build.gradle:
dependencies {
    compileOnly 'com.hivemq:hivemq-extension-sdk:4.28.0'
}
Or for Kotlin DSL (build.gradle.kts):
dependencies {
    compileOnly("com.hivemq:hivemq-extension-sdk:4.28.0")
}

Core Interfaces

ExtensionMain

The main entry point for every extension:
package com.hivemq.extension.sdk.api;

import com.hivemq.extension.sdk.api.annotations.NotNull;
import com.hivemq.extension.sdk.api.parameter.*;

public interface ExtensionMain {
    
    /**
     * Called when the extension is started.
     * Register providers and initialize resources here.
     */
    void extensionStart(
        @NotNull ExtensionStartInput input,
        @NotNull ExtensionStartOutput output
    );
    
    /**
     * Called when the extension is stopped.
     * Clean up resources here.
     */
    void extensionStop(
        @NotNull ExtensionStopInput input,
        @NotNull ExtensionStopOutput output
    );
}
Implementation Example:
public class MyExtension implements ExtensionMain {
    
    @Override
    public void extensionStart(
            @NotNull ExtensionStartInput input,
            @NotNull ExtensionStartOutput output) {
        
        ExtensionInformation info = input.getExtensionInformation();
        System.out.println("Starting " + info.getName() + " v" + info.getVersion());
        
        // Register providers
        Services services = input.getServices();
        // ...
    }
    
    @Override
    public void extensionStop(
            @NotNull ExtensionStopInput input,
            @NotNull ExtensionStopOutput output) {
        
        System.out.println("Stopping extension");
        // Cleanup
    }
}
See README.adoc:265 for embedded extension example.

ExtensionStartInput

Provides access to extension information and services:
public interface ExtensionStartInput {
    
    /**
     * @return Information about this extension
     */
    @NotNull ExtensionInformation getExtensionInformation();
    
    /**
     * @return Server information
     */
    @NotNull ServerInformation getServerInformation();
    
    /**
     * @return HiveMQ services (client, publish, subscription, etc.)
     */
    @NotNull Services getServices();
    
    /**
     * @return Previous version if this is an upgrade, null otherwise
     */
    @Nullable String getPreviousVersion();
}

ExtensionStartOutput

Controls extension startup behavior:
public interface ExtensionStartOutput {
    
    /**
     * Prevent the extension from starting.
     * Call this if initialization fails.
     */
    void preventExtensionStartup(@NotNull String reason);
}
Usage Example:
@Override
public void extensionStart(
        @NotNull ExtensionStartInput input,
        @NotNull ExtensionStartOutput output) {
    
    try {
        // Initialize database connection
        database.connect();
    } catch (Exception e) {
        output.preventExtensionStartup("Failed to connect to database: " + e.getMessage());
        return;
    }
}

Services API

The SDK provides services for interacting with HiveMQ:

ClientService

Manage and query MQTT clients:
ClientService clientService = services.clientService();

// Get client by ID
Optional<ClientInformation> client = clientService.getClient("client-123");

// Disconnect client
clientService.disconnectClient("client-123");

// Iterate all clients
clientService.iterateAllClients(new ClientCallback() {
    @Override
    public void onClientResult(ClientInformation client) {
        System.out.println("Client: " + client.getClientId());
    }
});

PublishService

Publish MQTT messages:
PublishService publishService = services.publishService();

// Create and publish message
Publish publish = Publish.builder()
    .topic("status/temperature")
    .qos(Qos.AT_LEAST_ONCE)
    .payload(ByteBuffer.wrap("23.5".getBytes()))
    .build();

publishService.publish(publish);

SubscriptionService

Manage client subscriptions:
SubscriptionService subscriptionService = services.subscriptionService();

// Get client subscriptions
Set<TopicSubscription> subscriptions = 
    subscriptionService.getSubscriptions("client-123");

// Add subscription programmatically
subscriptionService.addSubscription(
    "client-123",
    TopicSubscription.of("sensor/#", Qos.EXACTLY_ONCE)
);

// Remove subscription
subscriptionService.removeSubscription(
    "client-123",
    "sensor/#"
);

RetainedMessageService

Manage retained messages:
RetainedMessageService retainedService = services.retainedMessageService();

// Get retained messages for topic
Set<RetainedMessage> retained = retainedService.getRetainedMessages();

// Clear retained message
retainedService.clear("status/temperature");

ManagedExtensionExecutorService

Execute background tasks:
ManagedExtensionExecutorService executor = services.managedExtensionExecutorService();

// Submit background task
executor.submit(new Runnable() {
    @Override
    public void run() {
        // Background processing
    }
});

// Schedule periodic task
executor.scheduleAtFixedRate(
    () -> System.out.println("Heartbeat"),
    0, 60, TimeUnit.SECONDS
);

Provider Interfaces

Providers create instances of authenticators, authorizers, initializers, and interceptors.

AuthenticatorProvider

Provides authenticator instances:
public interface AuthenticatorProvider {
    
    /**
     * Called for each client authentication.
     * 
     * @param input Contains client and connection information
     * @return Authenticator instance or null to skip
     */
    @Nullable Authenticator getAuthenticator(
        @NotNull AuthenticatorProviderInput input
    );
}
See Authenticators.java:34 for internal interface.

AuthorizerProvider

Provides authorizer instances:
public interface AuthorizerProvider {
    
    /**
     * Called for each authorization check.
     * 
     * @param input Contains client information
     * @return Authorizer instance or null to skip
     */
    @Nullable Authorizer getAuthorizer(
        @NotNull AuthorizerProviderInput input
    );
}
See Authorizers.java:38 for internal interface.

ClientInitializer

Initializes client context on connection:
public interface ClientInitializer {
    
    /**
     * Called when a client connects successfully.
     * 
     * @param input Client and connection information
     * @param output Context for registering client-specific callbacks
     */
    void initialize(
        @NotNull InitializerInput input,
        @NotNull ClientContext output
    );
}
See Initializers.java:34 for internal interface.

InterceptorProvider

Provides packet interceptor instances:
public interface PublishInboundInterceptorProvider {
    
    /**
     * Called for each inbound PUBLISH packet.
     * 
     * @param input Provider input
     * @return Interceptor instance or null
     */
    @Nullable PublishInboundInterceptor getPublishInboundInterceptor(
        @NotNull PublishInboundInterceptorProviderInput input
    );
}
See Interceptors.java:44 for internal interface.

Annotations

The SDK uses JSR-305 annotations for null safety:
  • @NotNull - Parameter/return value must not be null
  • @Nullable - Parameter/return value may be null
  • @Immutable - Object is immutable after construction
  • @ThreadSafe - Class is thread-safe
Example:
import com.hivemq.extension.sdk.api.annotations.NotNull;
import com.hivemq.extension.sdk.api.annotations.Nullable;

public class MyAuthenticator implements Authenticator {
    
    @Override
    public void authenticate(
            @NotNull AuthenticationInput input,
            @NotNull AuthenticationOutput output) {
        
        @Nullable String username = input.getConnectPacket()
            .getUserName()
            .orElse(null);
        
        if (username == null) {
            output.failAuthentication();
            return;
        }
        
        // Authenticate...
    }
}

Package Structure

The Extension SDK is organized into packages:
com.hivemq.extension.sdk.api
├── annotations/          # Null safety and thread safety annotations
├── auth/                 # Authentication interfaces
├── client/               # Client information and context
├── events/               # Event interfaces
├── interceptor/          # Packet interceptor interfaces
│   ├── connack/
│   ├── connect/
│   ├── disconnect/
│   ├── publish/
│   ├── subscribe/
│   └── unsubscribe/
├── packets/              # MQTT packet representations
│   ├── auth/
│   ├── connect/
│   ├── disconnect/
│   ├── publish/
│   └── subscribe/
├── parameter/            # Input/output parameter objects
├── services/             # HiveMQ services
│   ├── auth/
│   ├── builder/
│   ├── executor/
│   ├── intializer/
│   ├── publish/
│   └── subscription/
└── ExtensionMain.java    # Main extension interface

Building Extensions

Project Setup

Minimal pom.xml for extension development:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>my-hivemq-extension</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.hivemq</groupId>
            <artifactId>hivemq-extension-sdk</artifactId>
            <version>4.28.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Building with Maven

mvn clean package
Output: target/my-hivemq-extension-1.0.0.jar

Building with Gradle

./gradlew clean build

Version Compatibility

  • Java 11+ required for extension development
  • SDK version should match HiveMQ major version
  • Extensions built for HiveMQ 4.x are compatible with all 4.x releases
Always use provided or compileOnly scope for the SDK dependency to avoid ClassLoader conflicts.

Next Steps

Authentication

Implement custom authentication

Authorization

Control publish and subscribe permissions

Client Initializers

Initialize client context on connection

Packet Interceptors

Intercept and modify MQTT packets

Build docs developers (and LLMs) love