allegro / hermes

Fast and reliable message broker built on top of Kafka.
http://hermes.allegro.tech
Other
818 stars 218 forks source link

Hermes Frontend with enabled buffer persistence does not run on docker with JRE #1846

Closed rw-dp closed 1 month ago

rw-dp commented 6 months ago

I'm trying to run Hermes Frontend in version 2.5.4 with enabled buffer persistence using implementation of OpenHFT ChronicleMap on docker build with dockerfile. My first attempt to enable buffer persistence was simply to set new parameters as it is described in documentation. But application printed following exception on startup:

ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'persistentBufferExtension' defined in class path resource [pl/allegro/tech/hermes/frontend/config/FrontendConfiguration.class]: null
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:310)
    at pl.allegro.tech.hermes.frontend.HermesFrontend.main(HermesFrontend.java:13)
Caused by: java.lang.ExceptionInInitializerError: null
    at net.openhft.chronicle.core.Jvm.getSetAccessible0Method(Jvm.java:235)
    at net.openhft.chronicle.core.Jvm.<clinit>(Jvm.java:142)
    at net.openhft.chronicle.map.ChronicleMapBuilder.<clinit>(ChronicleMapBuilder.java:165)
    at pl.allegro.tech.hermes.frontend.buffer.chronicle.ChronicleMapMessageRepository.<init>(ChronicleMapMessageRepository.java:41)
    at pl.allegro.tech.hermes.frontend.buffer.chronicle.ChronicleMapMessageRepository.<init>(ChronicleMapMessageRepository.java:55)
    at pl.allegro.tech.hermes.frontend.buffer.PersistentBufferExtension.enableLocalStorage(PersistentBufferExtension.java:85)
    at pl.allegro.tech.hermes.frontend.buffer.PersistentBufferExtension.extend(PersistentBufferExtension.java:64)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1869)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1826)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766)
    ... 13 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at net.openhft.chronicle.core.Jvm.getSetAccessible0Method(Jvm.java:232)
    ... 26 common frames omitted
Caused by: java.lang.IllegalAccessException: module java.base does not open java.lang.reflect to unnamed module @3c835ff8
    at java.base/java.lang.invoke.MethodHandles.privateLookupIn(Unknown Source)
    ... 31 common frames omitted

Then I found an article How to run Chronicle Libraries Under Java 17, according to which I should pass to java command following parameters:

--add-exports=java.base/jdk.internal.ref=ALL-UNNAMED
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED

I added these new parameters and on startup application printed different exception:

ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'persistentBufferExtension' defined in class path resource [pl/allegro/tech/hermes/frontend/config/FrontendConfiguration.class]: java.lang.ClassNotFoundException: com.sun.tools.javac.api.JavacTool
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:310)
    at pl.allegro.tech.hermes.frontend.HermesFrontend.main(HermesFrontend.java:13)
Caused by: java.lang.AssertionError: java.lang.ClassNotFoundException: com.sun.tools.javac.api.JavacTool
    at net.openhft.chronicle.values.CompilerUtils.reset(CompilerUtils.java:64)
    at net.openhft.chronicle.values.CompilerUtils.<clinit>(CompilerUtils.java:53)
    at net.openhft.chronicle.values.ValueModel.createClass(ValueModel.java:326)
    at net.openhft.chronicle.values.ValueModel.createNativeClass(ValueModel.java:306)
    at net.openhft.chronicle.values.ValueModel.nativeClass(ValueModel.java:282)
    at net.openhft.chronicle.values.Values.nativeClassFor(Values.java:89)
    at net.openhft.chronicle.values.Values.newNativeReference(Values.java:57)
    at net.openhft.chronicle.hash.impl.VanillaChronicleHash.createGlobalMutableState(VanillaChronicleHash.java:351)
    at net.openhft.chronicle.hash.impl.VanillaChronicleHash.initOwnTransients(VanillaChronicleHash.java:404)
    at net.openhft.chronicle.hash.impl.VanillaChronicleHash.initTransients(VanillaChronicleHash.java:400)
    at net.openhft.chronicle.map.VanillaChronicleMap.initTransients(VanillaChronicleMap.java:186)
    at net.openhft.chronicle.map.VanillaChronicleMap.<init>(VanillaChronicleMap.java:117)
    at net.openhft.chronicle.map.ChronicleMapBuilder.newMap(ChronicleMapBuilder.java:1983)
    at net.openhft.chronicle.map.ChronicleMapBuilder.lambda$createWithFile$2(ChronicleMapBuilder.java:1720)
    at net.openhft.chronicle.hash.impl.util.CanonicalRandomAccessFiles.lambda$tryRunExclusively$7(CanonicalRandomAccessFiles.java:196)
    at net.openhft.chronicle.hash.impl.util.CanonicalRandomAccessFiles.lambda$acquire0$1(CanonicalRandomAccessFiles.java:67)
    at java.base/java.util.concurrent.ConcurrentHashMap.compute(Unknown Source)
    at net.openhft.chronicle.hash.impl.util.CanonicalRandomAccessFiles.acquire0(CanonicalRandomAccessFiles.java:57)
    at net.openhft.chronicle.hash.impl.util.CanonicalRandomAccessFiles.tryRunExclusively(CanonicalRandomAccessFiles.java:175)
    at net.openhft.chronicle.map.ChronicleMapBuilder.createWithFile(ChronicleMapBuilder.java:1717)
    at net.openhft.chronicle.map.ChronicleMapBuilder.recoverPersistedTo(ChronicleMapBuilder.java:1622)
    at net.openhft.chronicle.map.ChronicleMapBuilder.createOrRecoverPersistedTo(ChronicleMapBuilder.java:1605)
    at net.openhft.chronicle.map.ChronicleMapBuilder.createOrRecoverPersistedTo(ChronicleMapBuilder.java:1597)
    at pl.allegro.tech.hermes.frontend.buffer.chronicle.ChronicleMapMessageRepository.<init>(ChronicleMapMessageRepository.java:47)
    at pl.allegro.tech.hermes.frontend.buffer.PersistentBufferExtension.loadOldMessages(PersistentBufferExtension.java:103)
    at pl.allegro.tech.hermes.frontend.buffer.PersistentBufferExtension.lambda$rollBackupFiles$1(PersistentBufferExtension.java:79)
    at java.base/java.util.ArrayList.forEach(Unknown Source)
    at pl.allegro.tech.hermes.frontend.buffer.PersistentBufferExtension.rollBackupFiles(PersistentBufferExtension.java:79)
    at pl.allegro.tech.hermes.frontend.buffer.PersistentBufferExtension.extend(PersistentBufferExtension.java:60)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1869)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1826)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766)
    ... 13 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.api.JavacTool
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Unknown Source)
    at net.openhft.chronicle.values.CompilerUtils.reset(CompilerUtils.java:60)
    ... 48 common frames omitted

It seems that running Hermes Frontend on JRE with enabled buffer persistence using implementation of OpenHFT ChronicleMap is not possible due to lack of Java module: jdk.compiler. Although changing the image from eclipse-temurin:17.0.7_7-jre to eclipse-temurin:17.0.7_7-jdk in dockerfile solves the problem and application starts successfully, it causes many security issues on production environment.

I've looked into the code of newer versions of Hermes and I did not find any changes that could solve this problem. Please confirm that my analysis is correct and if so, please fix Hermes Frontend to work on JRE with enabled buffer persistence using implementation of OpenHFT ChronicleMap on docker.

BR

szczygiel-m commented 1 month ago

since persistence buffers are deprecated and will be removed in the future, we are not planning to take any action on that, closing