allegro/hermes

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

Closed this issue · 1 comments

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

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