Skip to content

Latest commit

 

History

History
323 lines (270 loc) · 14.5 KB

README.md

File metadata and controls

323 lines (270 loc) · 14.5 KB

hivemq-spring-boot-starter

A starter to incorporate HiveMQ-CE into Spring Boot.

Building

This starter is only demo and not (yet) published to Maven central. In order to use it, you have to clone this repository and build it from scratch. To do so, use following commands:

git clone https://github.com/janosch24/hivemq-spring-boot-starter
gradlew publish

This will build the starter and publish it to your local Maven repository.

Usage

To use HiveMQ there's no additional code in your application required. You just have to customize your build script and (if required) your application configuration.

Gradle

Upon the usual Spring Boot starter, you have to use following dependency in your build.gradle script in order to embed HiveMQ into your Spring Boot application:

dependencies {
    implementation 'com.example.hivemq.boot:hivemq-spring-boot-starter:2024.9'
}

As the starter is only published locally, you should also include your local Maven repository in your application build script:

reporitories {
    mavenLocal()
}

It is also recommended to put an appropriate version entry into your application's MANIFEST, so HiveMQ can find its version on startup and make an appropriate log entry.

tasks.named("bootJar") {
    manifest {
        attributes 'HiveMQ-Version': '2024.9'
    }
}

HiveMQ uses javax style XML-parsing for config file reading. This clashes with Spring Boot managed dependencies for JAXB. In order to make it work, you have to 'downgrade' some dependencies. You can do this by employing the Spring Boot dependency management plugin in your build.gradle:

plugins {
    id 'io.spring.dependency-management' version '1.1.6'
} 

Then put following entries into your project's gradle.properties file:

jakarta-activation.version = 1.2.2
jakarta-xml-bind.version = 2.3.3
glassfish-jaxb.version = 2.3.9

NOTE: For a ready to go example, see hivemq-spring-boot-demo

Configuration

This starter in conjunction with HiveMQ comes with sensible default values. There is no configuration required at all, in order to have default behavior incorporated into a Spring Boot application. Nevertheless, all configuration parameters, required by HiveMQ, can be customized.
For a general understanding: This starter consumes Spring Boot style configurations (either properties or yaml) and streamlines a standard HiveMQ XML-based configuration file upon startup, so HiveMQ can find it.

To customize configuration, all values must be prefixed by hivemq. For a full set of properties, see example below. Following table lists all possible values:

Property mandatory default description
hivemq.enabled no true Whether to enable HiveMQ
hivemq.auto-start no true Whether to automatically start HiveMQ on application startup
hivemq.config.folder no .hivemq/conf HiveMQ configuration folder
extensions.folder no .hivemq/extensions HiveMQ extensions folder
extensions.collector.enabled no true Whether to collect embedded extensions, see section below
extensions.collector.info.publish no true Whether to publish info regarding embedded extensions on startup
extensions.collector.info.topic no boot/extensions MQTT topic to publish info to
log.folder no .hivemq/log HiveMQ logging folder, for logging see section below
log.level no info one of error, warn, info, debug, trace
config.listeners no one tcp-listener 0.0.0.0/1883 Listener configuration follows HiveMQ Community Edition listener configuration
config.mqtt no defined by HiveMQ MQTT related configuration follows HiveMQ Community Edition MQTT specific configuration
config.persistence no defined by HiveMQ Persistence configuration follows HiveMQ Community Edition persistence specific configuration
config.security no defined by HiveMQ Security related configuration follows HiveMQ Community Edition security specific configuration

Following example gives a full set of available configuration properties:

hivemq:
  enabled: true
  auto-start: true
  config.folder: .hivemq/conf
  data.folder: .hivemq/data
  extensions.folder: .hivemq/extensions
  extensions.collector.enabled: true
  extensions.collector.info.publish: true
  extensions.collector.info.topic: "boot/extensions"
  log.folder: .hivemq/log
  log.level: info

  config:
    listeners:
      tcp-listeners:
        - name: first-tcp-listener
          port: 1883
          bind-address: 0.0.0.0
        - name: second-tcp-listener
          port: 1884
          bind-address: localhost

      websocket-listeners:
        - name: default-websocket-listener
          port: 8000
          bind-address: 0.0.0.0
          path: /mqtt
          allow-extensions: true
          subprotocols: mqttv3.1, mqtt

      tls-tcp-listeners:
        - name: default-tls-tcp-listener
          port: 8883
          bind-address: 0.0.0.0
          tls:
            protocols: TLSv1.1, TLSv1.2
            cipher-suites:
              - TLS_RSA_WITH_AES_128_GCM_SHA256
              - TLS_RSA_WITH_AES_128_CBC_SHA
              - TLS_RSA_WITH_AES_256_CBC_SHA
            client-authentication-mode: none
            handshake-timeout: 10000
            concurrentHandshakeLimit: -1
            native-ssl: false
            keystore:
              path: path-to-keystore
              password: my-secret-password
              private-key-password: my-super-secret-password
            truststore:
              path: path-to-truststore
              password: my-secret-password

      tls-websocket-listeners:
        - name: default-tls-websocket-listener
          port: 8080
          bind-address: 0.0.0.0
          path: /mqtt
          allow-extensions: true
          subprotocols: mqttv3.1, mqtt
          tls:
            protocols:
              - TLSv1.1
              - TLSv1.2
            cipher-suites: TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA
            client-authentication-mode: none
            handshake-timeout: 10000
            concurrentHandshakeLimit: -1
            native-ssl: false
            keystore:
              path: path-to-keystore
              password: my-secret-password
              private-key-password: my-super-secret-password
            truststore:
              path: path-to-truststore
              password: my-secret-password

    mqtt:
      keep-alive.allow-unlimited: false
      keep-alive.max-keep-alive: 65535
      message-expiry.max-interval: 3600
      packets.max-packet-size: 268435460
      quality-of-service.max-qos: 2
      queued-messages.max-queue-size: 1000
      queued-messages.strategy: discard-oldest
      receive-maximum.server-receive-maximum: 10
      retained-messages.enabled: true
      session-expiry.max-interval: 60
      shared-subscriptions.enabled: true
      subscription-identifier.enabled: true
      topic-alias.enabled: true
      topic-alias.max-per-client: 5
      wildcard-subscriptions.enabled: true

    persistence:
      mode: in-memory

    security:
      allow-empty-client-id.enabled: false
      payload-format-validation.enabled: false
      utf8-validation.enabled: true
      allow-request-problem-information.enabled: true

NOTE: Given values for HiveMQ related configurations are just examples, for available value ranges and default values consult the HiveMQ Community Edition Wiki

Logging

HiveMQ is shipped with a logback.xml for logging. Spring Boot detects and uses it unless you define your own logback.xml. If so, in turn you cannot use HiveMQs logback.xml, as it is not ready to be included in your own logging configuration. Further, if your application already uses a Spring flavoured logback-spring.xml configuration, it will be ignored, as the one from HiveMQ takes precedence. Therefore, this starter is equipped with a logback configuration, which you can include in your own logback configuration. It is mainly derived from HiveMQs original logback.xml, but adds some Spring Boot specific stuff. You can use it from your logback-spring.xml as shown in the following example:

<configuration>

    <include resource="logback-spring-hivemq.xml"/>

    <property name="DEFAULT_PATTERN"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-30.30thread] %-5level %-40(%class{35}:%L) - %msg%n%ex" />

</configuration>

NOTE: If you define a DEFAULT_PATTERN, HiveMQ logging will follow this, uses its predefined pattern otherwise.

In order to avoid clashes between your own logback-spring.xml and HiveMQs internal configuration, it is recommended to force Spring Boot to use your version of the file logback-spring.xml:

logging:
  config: classpath:logback-spring.xml

Embedded Extensions

Using this starter you can use embedded extensions, as described in HiveMQ Community Edition Quickstart guide. As embedded HiveMQ supports only a single embedded extension, this starter provides a convenience wrapper which collects all available embedded extensions of type com.hivemq.embedded.EmbeddedExtension into a single extension.
Note, that both, priority and start priority of that single wrapper-extension, will be the maximum values of all collected extensions. Nevertheless, all collected embedded extensions are sorted by start priority (highest comes first).
In order to use your own embedded extension, you simply have to create a bean either way Spring Boot recommends it.

@Bean
public EmbeddedExtension myEmbeddedExtension() {
    return EmbeddedExtension.builder()
            .withId("my-embedded-extension")
            .withName("My Embedded Extension")
            .withVersion("1.0.0")
            .withPriority(0)
            .withStartPriority(1000)
            .withAuthor("Me")
            .withExtensionMain(new MyEmbeddedExtensionMain())
            .build();
}

You can also define your embedded extension as a component, for instance:

@Component
public final class MyEmbeddedExtension implements EmbeddedExtension, ExtensionMain {

  @Override
  public @NotNull String getId() { return "my-embedded-extension"; }

  @Override
  public @NotNull String getName() { return "My Embedded Extension"; }

  // ...

  @Override
  public @NotNull ExtensionMain getExtensionMain() { return this; }

  // ...
}

Manual start HiveMQ

HiveMQ automatically starts during application startup per default. Sometimes you may want to have a deferred startup, perhaps to have other resources running first. To achieve this, HiveMQ can get manually started. First you have to set the appropriate property:

hivemq.auto-start: false

Then let Spring Boot inject a HiveMQ starter, for instance like shown for the CommandLineRunner in the following example:

@SpringBootApplication
public class MySpringBootApplication {
    @Bean
    public CommandLineRunner startup(final ApplicationContext ctx, final HiveMQEmbeddedStarter hiveMQ) {
        return args -> {
          // Do what ever we want,
          // before we start HiveMQ
    
          // Now start HiveMQ ...
          hiveMQ.startup();
    
          // Do other stuff,
          // after HiveMQ got started ...
        };
    }
    
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }
}