Registries

HiveMQ registries provide a convenient way for extensions to register extension callbacks with the HiveMQ core.

You can access these registries through the Services class.

The following HiveMQ registries are available:

Table 1. Available HiveMQ Services
Registry Description

Initializer Registry

Allows extensions to set a client initializer for every mqtt client.

Security Registry

Allows extensions to define the authentication and authorization of MQTT clients.

Event Registry

Allows extensions to set a client lifecycle event listener for MQTT clients.

Metric Registry

Enables the extensions to access the metrics of HiveMQ and add custom metrics.

Initializer Registry

The initializer registry allows every extension to set a ClientInitializer.

Client Initializer

With the client initializer set up in the extension start method, it is possible to add:

  • Interceptors

  • Client lifecycle listeners

  • Default topic permissions

To use a client initializer, it must be implemented by the extension developer. See example below.

Multiple extensions can set a client initializer. Those initializers are called sequentially, starting with the client initializer of the extension with the highest priority. Extensions with the same priority have an undefined order of calling initialize.

Every client calls the same initialize method once.

The context of the client initializer will be added to every connected and connecting mqtt client after extension start.

When the extension stops, the context of its client initializer will be removed from every client automatically.

Example Usage

This section illustrates examples on how to set a ClientInitializer via the InitializerRegistry.

Accessing Initializer Registry

This example shows how to access InitializerRegistry via the Services class.

final InitializerRegistry initializerRegistry = Services.initializerRegistry();

Add Interceptors And Set Initializer

This example shows how to create a ClientInitializer, add an Interceptor and set the ClientInitializer to the registry.

ClientInitializer initializer = new ClientInitializer() {
    @Override
    public void initialize(InitializerInput initializerInput, ClientContext clientContext) {
        clientContext.addPublishInboundInterceptor(interceptor);
    }
}

Services.initializerRegistry().setClientInitializer(initializer);
Full Example Code
...

@Override
public void extensionStart(final ExtensionStartInput extensionStartInput, final ExtensionStartOutput extensionStartOutput) {

    //create shareable interceptor
    final PublishInboundInterceptor shareAbleInterceptor = new PublishInboundInterceptor() {
        @Override
        public void onInboundPublish(PublishInboundInput publishInboundInput, PublishInboundOutput publishInboundOutput) {
            System.out.println("Publish incoming for topic: " + publishInboundInput.getPublishPacket().getTopic());
        }
    };

    //create client initializer
    final ClientInitializer initializer = new ClientInitializer() {

        @Override
        public void initialize(InitializerInput initializerInput, ClientContext clientContext) {

            //add shareable interceptor
            clientContext.addPublishInboundInterceptor(shareAbleInterceptor);

            //add backend client only interceptor
            if (initializerInput.getClientInformation().getClientId().equals("backend")) {
                clientContext.addSubscribeInboundInterceptor(
                        (subscribeInboundInput, subscribeInboundOutput) -> System.out.println("Inbound backend subscribe")
                );
            }
        }

    };

    //get registry from Services
    final InitializerRegistry initializerRegistry = Services.initializerRegistry();

    //set client initializer
    initializerRegistry.setClientInitializer(initializer);

}

...

Security Registry

The Security Registry allows extensions to define the authentication and authorization of MQTT clients.

Extensions can access the SecurityRegistry through Services.securityRegistry():

final SecurityRegistry securityRegistry = Services.securityRegistry();

The Security Registry has the following functionality:

All providers are automatically removed when the extension is stopped.

Authenticator Provider

You can authenticate MQTT clients in two ways:

  • Implement an AuthenticatorProvider to provide a SimpleAuthenticator

  • Implement an EnhancedAuthenticatorProvider to provide an EnhancedAuthenticator

The authenticator provider is called at most once for each MQTT client connection with a client-specific AuthenticatorProviderInput. This parameter contains information about the MQTT client, the connection, and the broker. The returned authenticator is valid the entire time the client is connected. You can return:

  • A new authenticator object for each MQTT client or

  • The same authenticator to authenticate different clients. Sharing the same object has the following requirements:

    • The implementation does not store the authentication state in the object.

    • The implementation is thread safe.

  • null if you do not want to register an authenticator for the specific client (and let another extension register an authenticator).

For more information, see Authentication.

Authorizer Provider

To authorize individual PUBLISH and/or SUBSCRIBE packets, implement an AuthorizerProvider to provide a PublishAuthorizer and/or SubscriptionAuthorizer.

The authorizer provider is called at most once for each MQTT client connection with a client specific AuthorizerProviderInput. This parameter contains information about the MQTT client, its connection, and the broker. The returned authorizer is valid the entire time the client is connected. You can return:

  • A new authorizer object for each MQTT client or

  • The same authorizer to authorize different clients. Sharing the same object has the following requirements:

    • The implementation does not store the authorization state in the object.

    • The implementation is thread safe.

  • null if you do not want to register an authorizer for the specific client (and let another extension register an authorizer).

For more information, see Authorization.

Example Usage

Implement Authenticator Provider

This example shows how to implement an AuthenticatorProvider.

You only need to return an Authenticator in the getAuthenticator method.

public class MyAuthenticatorProvider implements AuthenticatorProvider {

    private final Map<String, String> usernamePasswordMap;

    public MyAuthenticatorProvider(Map<String, String> usernamePasswordMap) {
        this.usernamePasswordMap = usernamePasswordMap;
    }

    @Override
    public Authenticator getAuthenticator(AuthenticatorProviderInput authenticatorProviderInput) {

        //A new instance must be returned, because the authenticator has state.
        return new MySimpleAuthenticator(usernamePasswordMap);
    }
}

Implement Authenticator Provider With Shareable Authenticator

This example shows how to implement an AuthenticatorProvider with a shareable authenticator.

This authenticator must either be stateless or thread-safe.

You only need to return an Authenticator in the getAuthenticator method.

public class MyAuthenticatorProvider implements AuthenticatorProvider {

    private final SimpleAuthenticator authenticator;

    public MyAuthenticatorProvider(SimpleAuthenticator authenticator) {
        this.authenticator = authenticator;
    }

    @Override
    public Authenticator getAuthenticator(AuthenticatorProviderInput authenticatorProviderInput) {

        //return a shareable authenticator which must be thread-safe / stateless
        return authenticator;
    }
}

Implement Authorizer Provider

This example shows how to implement an AuthorizerProvider.

You need to return an SubscriptionAuthorizer or PublishAuthorizer in the getAuthorizer() method.

It is possible to implement both a SubscriptionAuthorizer and a PublishAuthorizer in the same class by implementing both interfaces.

public class MyAuthorizerProvider implements AuthorizerProvider {

    //create a shared instance of SubcsriptionAuthorizer
    private final MySubscriptionAuthorizer subscriptionAuthorizer = new MySubscriptionAuthorizer();

    @Override
    public Authorizer getAuthorizer(AuthorizerProviderInput authorizerProviderInput) {
        //always return the shared instance.
        //It is also possible to create a new instance here for each client
        return subscriptionAuthorizer;
    }
}

Implement Simple Authenticator

This example shows an implementation of a SimpleAuthenticator with username and password validation.

public class MySimpleAuthenticator implements SimpleAuthenticator {

    private final Map<String, String> usernamePasswordMap;

    private MySimpleAuthenticator(Map<String, String> usernamePasswordMap) {
        this.usernamePasswordMap = usernamePasswordMap;
    }

    @Override
    public void onConnect(SimpleAuthInput input, SimpleAuthOutput output) {

        //get connect packet from input object
        final ConnectPacket connectPacket = input.getConnectPacket();

        //validate the username and password combination
        if (validate(connectPacket.getUserName(), connectPacket.getPassword())) {

            //successful authentication if username and password are correct
            output.authenticateSuccessfully();

        } else {

            //failed authenticattion if username or password are incorrect
            output.failAuthentication(BAD_USER_NAME_OR_PASSWORD, "wrong password");
        }
    }

    private boolean validate(Optional<String> usernameOptional, Optional<ByteBuffer> passwordOptional) {

        //if no username or password is set, valdation fails
        if (!usernameOptional.isPresent() || !passwordOptional.isPresent()) {
            return false;
        }

        final String username = usernameOptional.get();
        final byte[] bytes = getBytesFromBuffer(passwordOptional.get());
        final String password = new String(bytes, StandardCharsets.UTF_8);

        //get password for username from map.
        final String passwordFromMap = usernamePasswordMap.get(username);

        //return true if passwords are equal, else false
        return password.equals(passwordFromMap);
    }

    private byte[] getBytesFromBuffer(ByteBuffer byteBuffer) {
        final byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);
        return bytes;
    }
}

Implement Async Simple Authenticator

This example shows an async implementation of a SimpleAuthenticator with external validation.

public class MyAsyncSimpleAuthenticator implements SimpleAuthenticator {

    @Override
    public void onConnect(SimpleAuthInput input, SimpleAuthOutput output) {

        //access managed extension executor service
        final ManagedExtensionExecutorService extensionExecutorService = Services.extensionExecutorService();

        //make output async with timeout of 10 seconds and when operation timed out, auth will fail
        final Async<SimpleAuthOutput> asyncOutput = output.async(Duration.of(10, SECONDS), TimeoutFallback.FAILURE);

        //submit external task to managed extension executor service
        extensionExecutorService.submit(new Runnable() {
            @Override
            public void run() {

                //validate client via external service call. This method is not provided by the HiveMQ extension system
                final boolean successful = externalServiceCallForValidation();

                if (successful) {
                    asyncOutput.getOutput().authenticateSuccessfully();
                } else {
                    asyncOutput.getOutput().failAuthentication();
                }

                //resume output to tell HiveMQ auth is complete
                asyncOutput.resume();
            }
        });
    }
}

Set Authenticator Provider

This example shows how to set an AuthenticatorProvider to the security registry.

public class AuthExtensionMain implements ExtensionMain{

    @Override
    public void extensionStart(ExtensionStartInput extensionStartInput, ExtensionStartOutput extensionStartOutput) {

        //access security registry
        final SecurityRegistry securityRegistry = Services.securityRegistry();

        //create username_password map
        final Map<String, String> usernamePasswordMap = new HashMap<>();
        usernamePasswordMap.put("test_name_1", "password_1");
        usernamePasswordMap.put("test_name_2", "password_2");
        usernamePasswordMap.put("test_name_3", "password_3");

        //create provider
        final MyAuthenticatorProvider provider = new MyAuthenticatorProvider(usernamePasswordMap);

        //set provider
        securityRegistry.setAuthenticatorProvider(provider);
    }

    @Override
    public void extensionStop(ExtensionStopInput extensionStopInput, ExtensionStopOutput extensionStopOutput) {
    }
}

Set Authorizer Provider

This example shows how to set an AuthorizerProvider to the security registry.

public class AuthorizerExtensionMain implements ExtensionMain{

    @Override
    public void extensionStart(ExtensionStartInput extensionStartInput, ExtensionStartOutput extensionStartOutput) {

        //access security registry
        final SecurityRegistry securityRegistry = Services.securityRegistry();

        //create provider
        final MyAuthorizerProvider provider = new MyAuthorizerProvider();

        //set provider
        securityRegistry.setAuthorizerProvider(provider);
    }

    @Override
    public void extensionStop(ExtensionStopInput extensionStopInput, ExtensionStopOutput extensionStopOutput) {
    }
}

Event Registry

The event registry allows every extension to register a ClientLifecycleEventListenerProvider, which must return an implementation of a ClientLifecycleEventListener.

The ClientLifecycleEventListenerProvider.getClientLifecycleEventListener() method is called once for every client, as soon as the first event is fired.

The EventRegistry can be accessed by the Services class.

Client Lifecycle Event Listener

With the ClientLifecycleEventListener set up in a extension, it is possible to listen to these client lifecycle events:

Table 2. Available ClientLifecycleEventListener Methods
Method Input Description

onMqttConnectionStart

ConnectionStartInput

This event is fired as soon as HiveMQ receives a valid MQTT connect packet.

onAuthenticationSuccessful

AuthenticationSuccessfulInput

This event is fired when a client’s authentication succeeds.

onAuthenticationFailedDisconnect

AuthenticationFailedInput

This event is fired when a client’s authentication failed.

onClientInitiatedDisconnect

ClientInitiatedDisconnectInput

This event is fired when a client disconnects gracefully (sends a disconnect packet).

onConnectionLost

ConnectionLostInput

This event is fired when a client disconnects ungracefully (closed connection without disconnect packet sent).

onServerInitiatedDisconnect

ServerInitiatedDisconnectInput

This event is fired when HiveMQ disconnects the client.

onDisconnect

DisconnectEventInput

This event is fired when any kind of disconnect occurs.

To use a ClientLifecycleEventListener, it must be implemented by the extension developer. See example below.

Multiple extensions can set individual ClientLifecycleEventListener. These listeners are called sequentially, starting with the listener of the extension with the highest priority. Extensions with the same priority have an undefined order of calling a listener.

As soon as a extension is started, every client uses the listener to fire its lifecycle events.

When a extension stops, the listener will be removed from every client automatically.

Client Lifecycle Events

Client lifecycle event methods are called by HiveMQ when a client connects, authenticates or disconnects.

The input parameters of these methods are all immutable and for information purpose only.

onMqttConnectionStart

As soon as a connect packet is decoded and validated by HiveMQ the ClientLifecycleEventListener.onMqttConnectionStart method is called with a ConnectionStartInput.

This method must be overridden in the implementation of the ClientLifecycleEventListener.

The input contains the following information:

  • MQTT CONNECT Packet

  • MQTT Version

  • Client ID

  • IP Address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

onAuthenticationSuccessful

When a client’s authentication succeeds the ClientLifecycleEventListener.onAuthenticationSuccessful method is called with an AuthenticationSuccessfulInput.

This method must be overridden in the implementation of the ClientLifecycleEventListener.

The input contains the following information:

  • MQTT Version

  • Client ID

  • IP Address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

onAuthenticationFailedDisconnect

When a client’s authentication fails the ClientLifecycleEventListener.onAuthenticationFailedDisconnect method is called with a AuthenticationFailedInput.

If this method was called no other disconnect method will be called.

When this method is not overridden in the ClientLifecycleEventListener, onDisconnect is called.

The input contains the following information:

  • Optional disconnect reason code

  • Optional reason string

  • Optional user properties

  • MQTT version

  • Client ID

  • IP address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

onClientInitiatedDisconnect

When a client sends a disconnect packet (disconnects gracefully) the ClientLifecycleEventListener.onClientInitiatedDisconnect method is called with a ClientInitiatedDisconnectInput.

If this method was called no other disconnect method will be called.

When this method is not overridden in the ClientLifecycleEventListener, onDisconnect is called.

The input contains the following information:

  • Optional disconnect reason code

  • Optional reason string

  • Optional user properties

  • MQTT version

  • Client ID

  • IP address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

onConnectionLost

When a client disconnects without sending any disconnect packet (disconnects ungracefully) the ClientLifecycleEventListener.onConnectionLost method is called with a ConnectionLostInput.

If this method was called no other disconnect method will be called.

When this method is not overridden in the ClientLifecycleEventListener, onDisconnect is called.

The input contains the following information:

  • Optional disconnect reason code

  • Optional reason string

  • Optional user properties

  • MQTT version

  • Client ID

  • IP address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

onServerInitiatedDisconnect

When HiveMQ disconnects a client the ClientLifecycleEventListener.onServerInitiatedDisconnect method is called with a ServerInitiatedDisconnectInput.

If this method was called no other disconnect method will be called.

When this method is not overridden in the ClientLifecycleEventListener, onDisconnect is called.

The input contains the following information:

  • Optional disconnect reason code

  • Optional reason string

  • Optional user properties

  • MQTT version

  • Client ID

  • IP address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

onDisconnect

For every kind of specific disconnect method which is not overridden in the ClientLifecycleEventListener implementation the ClientLifecycleEventListener.onDisconnect method is called with a DisconnectEventInput.

This method will never be called, when every specific disconnect method is overridden in the ClientLifecycleEventListener.

The specific methods are:

This method must be overridden in the implementation of the ClientLifecycleEventListener.

The input contains the following information:

  • Optional disconnect reason code

  • Optional reason string

  • Optional user properties

  • MQTT version

  • Client ID

  • IP address

  • Listener with port, bind address and type

  • ConnectionAttributeStore

  • TLS

For more information, see Example Usage.

Example Usage

This section illustrates examples on how to set a ClientLifecycleEventListenerProvider via the EventRegistry.

Accessing Event Registry

This example shows how to access EventRegistry via the Services class.

final EventRegistry eventRegistry = Services.eventRegistry();

Implement A Simple ClientLifecycleEventListener

This example shows how to implement a very simple ClientLifecycleEventListener.

Only mandatory methods have been overridden in this example.

//create a class implementing ClientLifecycleEventListener
public class SimpleEventListener implements ClientLifecycleEventListener {

    //override mandatory onMqttConnectionStart method
    @Override
    public void onMqttConnectionStart(final @NotNull ConnectionStartInput connectionStartInput) {
        final MqttVersion version = connectionStartInput.getConnectionInformation().getMqttVersion();
        switch (version) {
            case V_5:
                log.info("MQTT 5 client connected with id: {} ", connectionStartInput.getClientInformation().getClientId());
                break;
            case V_3_1_1:
                log.info("MQTT 3.1.1 client connected with id: {} ", connectionStartInput.getClientInformation().getClientId());
                break;
            case V_3_1:
                log.info("MQTT 3.1 client connected with id: {} ", connectionStartInput.getClientInformation().getClientId());
                break;
        }
    }

    //override mandatory onAuthenticationSuccessful method
    @Override
    public void onAuthenticationSuccessful(final @NotNull AuthenticationSuccessfulInput authenticationSuccessfulInput) {
        log.info("Authentication succeeded for client: {}", authenticationSuccessfulInput.getClientInformation().getClientId());
    }

    //override mandatory onDisconnect method
    @Override
    public void onDisconnect(final @NotNull DisconnectEventInput disconnectEventInput) {
        log.info("Client disconnected: {}", disconnectEventInput.getClientInformation().getClientId());
    }
}

Implement A Full ClientLifecycleEventListener

This example shows how to implement a ClientLifecycleEventListener with all methods overridden.

//create a class implementing ClientLifecycleEventListener
public class FullEventListener implements ClientLifecycleEventListener {

    //override mandatory onMqttConnectionStart method
    @Override
    public void onMqttConnectionStart(final @NotNull ConnectionStartInput connectionStartInput) {
        final MqttVersion version = connectionStartInput.getConnectPacket().getMqttVersion();
        switch (version) {
            case V_5:
                log.info("MQTT 5 client connected with id: {} ", connectionStartInput.getClientInformation().getClientId());
                break;
            case V_3_1_1:
                log.info("MQTT 3.1.1 client connected with id: {} ", connectionStartInput.getClientInformation().getClientId());
                break;
            case V_3_1:
                log.info("MQTT 3.1 client connected with id: {} ", connectionStartInput.getClientInformation().getClientId());
                break;
        }
    }

    //override mandatory onAuthenticationSuccessful method
    @Override
    public void onAuthenticationSuccessful(final @NotNull AuthenticationSuccessfulInput authenticationSuccessfulInput) {
        log.info("Authentication succeeded for client: {}", authenticationSuccessfulInput.getClientInformation().getClientId());
    }

    //override optional onAuthenticationFailedDisconnect method
    @Override
    public void onAuthenticationFailedDisconnect(final @NotNull AuthenticationFailedInput authenticationFailedInput) {
        log.info("Authentication failed for client: {}", authenticationFailedInput.getClientInformation().getClientId());
    }

    //override optional onConnectionLost method
    @Override
    public void onConnectionLost(final @NotNull ConnectionLostInput connectionLostInput) {
        log.info("Ungraceful disconnect from client: {}", connectionLostInput.getClientInformation().getClientId());
    }

    //override optional onClientInitiatedDisconnect method
    @Override
    public void onClientInitiatedDisconnect(final @NotNull ClientInitiatedDisconnectInput clientInitiatedDisconnectInput) {
        log.info("Graceful disconnect from client: {}", clientInitiatedDisconnectInput.getClientInformation().getClientId());
    }

    //override optional onServerInitiatedDisconnect method
    @Override
    public void onServerInitiatedDisconnect(final @NotNull ServerInitiatedDisconnectInput serverInitiatedDisconnectInput) {
        log.info("Server disconnected client: {}", serverInitiatedDisconnectInput.getClientInformation().getClientId());
    }

    //override mandatory onDisconnect method
    @Override
    public void onDisconnect(final @NotNull DisconnectEventInput disconnectEventInput) {
        //as every other disconnect method is overridden this one will never be called from HiveMQ
        log.info("Client disconnected: {}", disconnectEventInput.getClientInformation().getClientId());
    }
}

Register A ClientLifecycleEventListenerProvider

This example shows how to implement and register a ClientLifecycleEventListenerProvider.

It uses the two different ClientLifecycleEventListener explained above.

...

@Override
public void extensionStart(final ExtensionStartInput extensionStartInput, final ExtensionStartOutput extensionStartOutput) {

    //create new SimpleEventListener
    final ClientLifecycleEventListener simpleEventListener = new SimpleEventListener();

    //create new FullEventListener
    final ClientLifecycleEventListener fullEventListener = new FullEventListener();

    final ClientLifecycleEventListenerProvider eventListenerProvider = new ClientLifecycleEventListenerProvider() {

        //override mandatory getClientLifecycleEventListener method
        @Override
        public @Nullable ClientLifecycleEventListener getClientLifecycleEventListener(final @NotNull ClientLifecycleEventListenerProviderInput clientLifecycleEventListenerProviderInput) {

            //check client id for returning either simple or full listener
            if (clientLifecycleEventListenerProviderInput.getClientInformation().getClientId().contains("simple")) {
                return simpleEventListener;
            } else {
                return fullEventListener;
            }
        }
    };

    //call Services.eventRegistry() to set the provider.
    Services.eventRegistry().setClientLifecycleEventListener(eventListenerProvider);
}

...

Metric Registry

The MetricRegistry of HiveMQ can be used to gather information about pre-defined HiveMQ metrics or to hook custom metrics that your extension defines. Since no artificial wrappers are used, you can access the feature-rich Dropwizard Metrics library directly.

With the MetricRegistry it is possible to write extensions that allows the integration of HiveMQ with any monitoring system (that supports Dropwizard Metrics). Extensions for Prometheus, InfluxDB or others can be found in the marketplace.

HiveMQ uses the de facto standard Java metrics library Dropwizard Metrics, so extension developers can benefit from the whole ecosystem about that library and writing custom integrations is a breeze.

Example Metric Registry Usage

The following examples show you how to use the MetricRegistry to add and fetch metrics.

Accessing Metric Registry

This example shows how to access MetricRegistry via the Services class.

final MetricRegistry metricRegistry = Services.metricRegistry();

Register a Custom Metric

You can add custom metrics to the metric registry that allow you to monitor specific behaviors of your extension accurately.

This example shows how to monitor the number of failed client authentications.

...
@Override
public void extensionStart(final ExtensionStartInput extensionStartInput, final ExtensionStartOutput extensionStartOutput) {

    final MetricRegistry metricRegistry = Services.metricRegistry();

    // create the new metric, that is increased when a client isn't successfully authenticated
    final Counter failedAuthCounter = metricRegistry.counter("com.example.extension.authentication.failed");

    // log the amount of failed client authentications every 10 seconds
    Services.extensionExecutorService().scheduleAtFixedRate(() -> {
        log.info("Authentication failed {} times", failedAuthCounter.getCount());
    }, 10, 10, TimeUnit.SECONDS);

    // create authenticator where clients that start with id "obsolete" fail to authenticate
    final AuthenticatorProvider authenticatorProvider = new AuthenticatorProvider() {
        @Override
        public Authenticator getAuthenticator(final AuthenticatorProviderInput authenticatorProviderInput) {
            return new SimpleAuthenticator() {
                @Override
                public void onConnect(final SimpleAuthInput simpleAuthInput, final SimpleAuthOutput simpleAuthOutput) {
                    final String clientId = simpleAuthInput.getClientInformation().getClientId();

                    if (clientId.startsWith("obsolete")) {
                        failedAuthCounter.inc();
                        simpleAuthOutput.failAuthentication();
                    } else {
                        simpleAuthOutput.authenticateSuccessfully();
                    }
                }
            };
        }
    };

    Services.securityRegistry().setAuthenticatorProvider(authenticatorProvider);
}
...

Fetch a HiveMQ Metric

This examples shows how to get a HiveMQ metric via the MetricRegistry. For a list of all available HiveMQ metrics, see HiveMQ Metrics.

...
@Override
public void extensionStart(final ExtensionStartInput extensionStartInput, final ExtensionStartOutput extensionStartOutput) {

    final MetricRegistry metricRegistry = Services.metricRegistry();

    final SortedMap<String, Gauge> gauges = metricRegistry.getGauges(
        MetricFilter.contains("com.hivemq.networking.connections.current"));

    //we expect a single result here
    final Gauge connectionsGauge = gauges.values().iterator().next();

    // every 10 seconds log the amount of clients that are connected
    Services.extensionExecutorService().scheduleAtFixedRate(() -> {
        log.info("Currently {} clients are connected", connectionsGauge.getValue());
    }, 10, 10, TimeUnit.SECONDS);
}
...