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