A starter to incorporate HiveMQ-CE into Spring Boot.
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.
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.
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
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
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
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; }
// ...
}
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);
}
}