HiveMQ CE Embedded Not Starting

Hello all! I am relatively new to this technology, but I understand Java and MQTT enough to attempt building my own extension. I seem to be stuck on something trivial, so I hope the solution will be as much.

I am created an extremely basic extension to start (log.info(“Started extension”) kind of simple) and I am having trouble getting it to run.

The catch is that I’m packaging everything into a jar and running it from Fantom (https://fantom.org). The technology I am trying to integrate with (SkySpark) is purely Fantom, so I am making a call to start the service through the Java FFI (this is Fantom’s internal Java interface, but that’s not super important).

The method that calls the embedded server and extension is below:

public static void startLocalBroker(@Nullable String configPath) {	
	// TODO Start My Extension
	MyExtensionMain.main(new String[0]);
}

My extension is here:

	public static void main(String[] args) {
//    	if (configPath==null) configPath = "configuration/";
    	String configPath = new String("configuration/");
		
    	final EmbeddedExtension embeddedExtension = EmbeddedExtension.builder()
                .withId("my-extension-1")
                .withName("My Extension")
                .withVersion("0.8.0")
                .withPriority(0)
                .withStartPriority(1000)
                .withAuthor("masschaostheory")
                .withExtensionMain(new MyExtension())
                .build();
    	
        System.out.println("Setting Embedded HiveMQ Configuration");
    	final EmbeddedHiveMQBuilder builder = EmbeddedHiveMQ.builder()
    			.withConfigurationFolder(Path.of(configPath))
                .withEmbeddedExtension(embeddedExtension);
    	
    	System.out.println("Running Embedded HiveMQ");		
		try (final EmbeddedHiveMQ hiveMQ = builder.build()) {

            InternalConfigurations.PAYLOAD_PERSISTENCE_TYPE.set(PersistenceType.FILE);
            InternalConfigurations.RETAINED_MESSAGE_PERSISTENCE_TYPE.set(PersistenceType.FILE);

            hiveMQ.start().join();
        } catch (final Exception ex) {
            ex.printStackTrace();
        }
	}
	
	private static class MyExtension implements ExtensionMain {

	    private static final @NotNull Logger log = LoggerFactory.getLogger(MyExtension .class);

		@Override
		public void extensionStart(@NotNull ExtensionStartInput extensionStartInput,
				@NotNull ExtensionStartOutput extensionStartOutput) {
			// TODO Auto-generated method stub
			log.info("Starting MyExtension!");
		}

		@Override
		public void extensionStop(@NotNull ExtensionStopInput extensionStopInput,
				@NotNull ExtensionStopOutput extensionStopOutput) {
			// TODO Auto-generated method stub
			log.info("Stopping MyExtension");
		}

	}

When I run this as a Java class from Eclipse I get this:

Setting Embedded HiveMQ Configuration
Running Embedded HiveMQ
2021-07-07 22:59:13,255 INFO  - Setting default authentication behavior to ALLOW ALL
2021-07-07 22:59:13,260 INFO  - HiveMQ version: Development Snapshot
2021-07-07 22:59:13,296 INFO  - Starting EmbeddedHiveMQ.
2021-07-07 22:59:13,505 INFO  - Starting with file persistence mode.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/home/abible/.m2/repository/com/google/inject/guice/4.2.3/guice-4.2.3.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2021-07-07 22:59:14,976 INFO  - Starting HiveMQ extension system.
2021-07-07 22:59:14,977 WARN  - Extension folder could not be used: "/home/abible/.m2/repository/com/hivemq/hivemq-community-edition-embedded/2021.1/extensions does not exist"
2021-07-07 22:59:15,009 INFO  - Starting My Extension!
2021-07-07 22:59:15,009 INFO  - Embedded extension "My Extension" version 0.8.0 started successfully.
2021-07-07 22:59:15,030 INFO  - Starting TCP listener on address 0.0.0.0 and port 1883
2021-07-07 22:59:15,059 INFO  - Starting TCP listener on address 127.0.0.1 and port 1884
2021-07-07 22:59:15,066 INFO  - Started TCP Listener on address 0.0.0.0 and on port 1883
2021-07-07 22:59:15,066 INFO  - Started TCP Listener on address 127.0.0.1 and on port 1884
2021-07-07 22:59:15,066 INFO  - Started EmbeddedHiveMQ in 1770ms
2021-07-07 22:59:15,067 INFO  - Closing EmbeddedHiveMQ.
2021-07-07 22:59:17,097 INFO  - Shutting down extension system
2021-07-07 22:59:17,100 INFO  - Stopping My Extension
2021-07-07 22:59:17,100 INFO  - Embedded extension "My Extension" version 0.8.0 stopped successfully.
2021-07-07 22:59:19,480 INFO  - Stopped EmbeddedHiveMQ in 4413ms

This seems like acceptable output, and I would be happier if I got something similar when running this from my other application. Instead, I get this output:

Setting Embedded HiveMQ Configuration
Running Embedded HiveMQ
2021-07-07 23:08:26,574 INFO  - Setting default authentication behavior to ALLOW ALL
2021-07-07 23:08:26,581 INFO  - HiveMQ version: Development Snapshot
2021-07-07 23:08:26,634 INFO  - Starting EmbeddedHiveMQ.
2021-07-07 23:08:26,671 ERROR - Could not read the configuration file /home/abible/Github/pahoMqttExt/configuration/config.xml. Using default config
2021-07-07 23:08:26,676 INFO  - Starting with file persistence mode.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2021-07-07 23:08:28,299 INFO  - Starting HiveMQ extension system.
2021-07-07 23:08:28,300 WARN  - Extension folder could not be used: "/extensions does not exist"
2021-07-07 23:08:28,302 INFO  - Closing EmbeddedHiveMQ.
2021-07-07 23:08:28,307 INFO  - Shutting down extension system
2021-07-07 23:08:28,344 INFO  - Stopping My Extension
2021-07-07 23:08:28,344 INFO  - Embedded extension "My Extension" version 0.8.0 stopped successfully.
2021-07-07 23:08:30,753 INFO  - Stopped EmbeddedHiveMQ in 2450ms
java.util.concurrent.CompletionException: java.lang.NullPointerException
        at java.base/java.util.concurrent.CompletableFuture.reportJoin(CompletableFuture.java:412)
        at java.base/java.util.concurrent.CompletableFuture.join(CompletableFuture.java:2044)
        at com.zivatech.mqtt.extension.MyExtensionMain.main(MyExtensionMain.java:47)
        at com.zivatech.mqtt.MqttHelper.startLocalBroker(MqttHelper.java:13)
        at fan.hiveMQExt.HiveMQExt.make$(HiveMQExt.fan:34)
        at fan.hiveMQExt.HiveMQExt.make(HiveMQExt.fan:29)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at fan.sys.Method.invoke(Method.java:573)
        at fan.sys.Method$MethodFunc.callList(Method.java:212)
        at fan.sys.Type.make(Type.java:246)
        at fan.sys.ClassType.make(ClassType.java:110)
        at fan.sys.Type.make(Type.java:236)
        at fan.projMod.ExtMgr.instantiateExt(ExtMgr.fan:346)
        at fan.projMod.ExtMgr.instantiateEntry(ExtMgr.fan:322)
        at fan.projMod.ExtMgr$make$0.doCall(ExtMgr.fan:36)
        at fan.projMod.ExtMgr$make$0.call(ExtMgr.fan:32)
        at fan.sys.List.each(List.java:604)
        at fan.projMod.ExtMgr.make$(ExtMgr.fan:32)
        at fan.projMod.ExtMgr.make(ExtMgr.fan:25)
        at fan.projMod.LocalProj.make$(LocalProj.fan:41)
        at fan.projMod.LocalProj.make(LocalProj.fan:24)
        at fan.projMod.ProjBoot.startLocal(ProjBoot.fan:145)
        at fan.projMod.ProjBoot.start(ProjBoot.fan:75)
        at fan.projMod.Manifest$loadLocals$3.doCall(Manifest.fan:272)
        at fan.projMod.Manifest$loadLocals$3.call(Manifest.fan:265)
        at fan.sys.List.each(List.java:604)
        at fan.projMod.Manifest.loadLocals(Manifest.fan:265)
        at fan.projMod.Manifest.onOpenAll(Manifest.fan:237)
        at fan.projMod.Manifest.onReceive(Manifest.fan:210)
        at fan.projMod.ManifestActor.receive(Manifest.fan:554)
        at fan.concurrent.Actor._dispatch(Actor.java:274)
        at fan.concurrent.Actor._work(Actor.java:229)
        at fan.concurrent.ThreadPool$Worker.run(ThreadPool.java:273)
Caused by: java.lang.NullPointerException
        at com.hivemq.extensions.classloader.IsolatedExtensionClassloader.loadClassesWithStaticContext(IsolatedExtensionClassloader.java:83)
        at com.hivemq.extensions.loader.ExtensionLoaderImpl.loadEmbeddedExtension(ExtensionLoaderImpl.java:311)
        at com.hivemq.extensions.ExtensionBootstrapImpl.startExtensionSystem(ExtensionBootstrapImpl.java:84)
        at com.hivemq.HiveMQServer.start(HiveMQServer.java:87)
        at com.hivemq.embedded.internal.EmbeddedHiveMQImpl.stateChange(EmbeddedHiveMQImpl.java:160)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)

The issues seems to be that the IsolatedExtensionClassLoader.loadClassesWithStaticContext doesn’t seem to be picking up my extension.

Does anyone have any idea what I can do to debug this further? I would like to the point where I can get the server listening, or at least acknowledging that my extension exists. I appreciate the time, thank you in advance :slight_smile:

Okay, so I decided to remove the extension entirely and just start an Embedded HiveMQ server from the command line using the extension main class. Without the EmbeddedExtension getting loaded, I should be able to see whether or not the issue is with my extension implementation or elsewhere.

As for the IsolatedExtensionClassLoader issue, I’ll get there when the server runs independently of any other program calling it with the extension.

Since we are only using the HiveMQBuilder.builder().build() method, I should get a server to start without any issues… right?

Not so much:

$ sudo java -cp target/hiveMQ-all.jar com.zivatech.mqtt.extension.MyExtensionMain
2021-07-13 20:40:57,712 INFO  - Setting default authentication behavior to ALLOW ALL
2021-07-13 20:40:57,727 INFO  - HiveMQ version: Development Snapshot
2021-07-13 20:40:57,790 INFO  - Starting EmbeddedHiveMQ.
2021-07-13 20:40:57,799 ERROR - The configuration file folder /home/abible/Github/pahoMqttExt/target/conf does not exist. Using HiveMQ default config
2021-07-13 20:40:57,837 INFO  - Starting with file persistence mode.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/home/abible/Github/pahoMqttExt/target/hiveMQ-all.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2021-07-13 20:40:59,141 INFO  - Starting HiveMQ extension system.
2021-07-13 20:40:59,142 WARN  - Extension folder could not be used: "/home/abible/Github/pahoMqttExt/target/extensions does not exist"
2021-07-13 20:40:59,179 INFO  - Starting TCP listener on address 0.0.0.0 and port 1883
2021-07-13 20:40:59,239 INFO  - Started TCP Listener on address 0.0.0.0 and on port 1883
2021-07-13 20:40:59,239 INFO  - Started EmbeddedHiveMQ in 1449ms
2021-07-13 20:40:59,240 INFO  - Closing EmbeddedHiveMQ.
2021-07-13 20:41:01,281 INFO  - Shutting down extension system
2021-07-13 20:41:03,726 INFO  - Stopped EmbeddedHiveMQ in 4486ms

Immediately after the server starts, it shuts down. I am unsure why, but my previous code ran (and is still running) with no issues, but adding this extension in has been a headache. Does anyone know why this would happen? Or perhaps how I could enable a debug mode to give a more verbose output?

Oookay… I got it to start, but not how I thought.

For some reason my try statement was causing a bucket load of issues, including the immediate server stop.

try (final EmbeddedHiveMQ hiveMQ = builder.build()) {

            InternalConfigurations.PAYLOAD_PERSISTENCE_TYPE.set(PersistenceType.FILE);
            InternalConfigurations.RETAINED_MESSAGE_PERSISTENCE_TYPE.set(PersistenceType.FILE);

            hiveMQ.start().join();
        } catch (final Exception ex) {
            ex.printStackTrace();
        }

Instead, I am starting with a very simple call:

builder.build().start().join();

I feel like an idiot, but the extension starts and runs now… and that’s the way the news goes.