You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue summarizes the current known issues associated with running OMERO.server under a JDK 17 environment and discusses a set of workarounds and proposed changes.
State of Java support
As of OMERO.server 5.6.10, the requirement table of the OMERO documentation 1 defines the current state of Java support. JDK 11 LTS released in September 2018 is the recommendation, JDK 17 LTS released in September 2021 is marked as unsupported and JDK 21 LTS which has been released in September 2023 is not yet captured.
In this table, upstream support for JDK 11 LTS is listed as ending in October 2024 i.e. 6 months from now. The reality is slightly more complex as this timeline largely depends on the OpenJDK build e.g. Oracle JDK 11 is already in extended support 2, the RedHat build of OpenJDK will enter Extended Life Cycle Support in October 3 while Azul Zulu will maintain builds of OpenJDK until 2032 4.
Introducing proper support for Java 17 (and possibly 21) in 2024 would give the community the option either to stay on JDK 11 or upgrade to a more recent JDK LTS version depending on their environment and requirements.
Encapsulation errors and workaround
The bulk of the issues associated with running OMERO.server on JDK 17 are related to the strong encapsulation introduced in Java 16 initially defined in JEP403 5. Various resources are available which describe these changes and their impact on downstream code e.g. 6.
Trying to start OMERO.server-5.6.10-ice36 in a JDK 21 environment on Ubuntu 22.04 results in the following exception
2024-04-16 09:22:33,127 INFO [ ome.services.blitz.Entry] ( main) Creating OMERO.blitz. Please wait...
2024-04-16 09:22:34,440 WARN [ ome.system.OmeroContext] ( main) Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'internal-ome.api.RawFileStoreSubstituter' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.RawFileStore.xml]: Cannot resolve reference to bean 'readOnlyStatus' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'readOnlyStatus' defined in class path resource [ome/services/startup.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [ome.services.util.ReadOnlyStatus]: Constructor threw exception; nested exception is java.lang.ExceptionInInitializerError
2024-04-16 09:22:34,445 ERROR [ ome.services.blitz.Entry] ( main) Error on startup.
org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [OMERO.blitz], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'OMERO.blitz' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-blitz.jar!/beanRefContext.xml]: Cannot resolve reference to bean 'ome.server' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ome.server' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/beanRefContext.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [ome.system.OmeroContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'internal-ome.api.RawFileStoreSubstituter' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.RawFileStore.xml]: Cannot resolve reference to bean 'readOnlyStatus' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'readOnlyStatus' defined in class path resource [ome/services/startup.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [ome.services.util.ReadOnlyStatus]: Constructor threw exception; nested exception is java.lang.ExceptionInInitializerError
at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:404)
at ome.system.OmeroContext.getInstance(OmeroContext.java:202)
at ome.services.blitz.Entry.start(Entry.java:189)
at ome.services.blitz.Entry.main(Entry.java:146)
...
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @fdc8126
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:159)
at javassist.util.proxy.DefineClassHelper$JavaOther.defineClass(DefineClassHelper.java:213)
at javassist.util.proxy.DefineClassHelper$Java11.defineClass(DefineClassHelper.java:52)
at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:260)
at javassist.ClassPool.toClass(ClassPool.java:1232)
at javassist.CtClass.toClass(CtClass.java:1384)
at bitronix.tm.resource.jdbc.proxy.JdbcJavassistProxyFactory.generateProxyClass(JdbcJavassistProxyFactory.java:265)
at bitronix.tm.resource.jdbc.proxy.JdbcJavassistProxyFactory.createProxyConnectionClass(JdbcJavassistProxyFactory.java:156)
... 110 common frames omitted
After setting omero.jvmcfg.append to --add-opens java.base/java.lang=ALL-UNNAMED and restarting the server
2024-04-16 09:25:03,635 ERROR [ ome.services.blitz.Entry] ( main) Error on startup.
org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [OMERO.blitz], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'OMERO.blitz' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-blitz.jar!/beanRefContext.xml]: Cannot resolve reference to bean 'ome.server' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ome.server' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/beanRefContext.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [ome.system.OmeroContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ome.util.MapPut#0' defined in class path resource [ome/services/hibernate.xml]: Cannot resolve reference to bean 'fullTextIndexer' while setting bean property 'object'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fullTextIndexer' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.Search.xml]: Cannot resolve reference to bean 'eventLogLoader' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'eventLogQueue' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.Search.xml]: Cannot resolve reference to bean 'internal-ome.api.ITypes' while setting bean property 'types'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'internal-ome.api.ITypes' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.ITypes.xml]: Cannot resolve reference to bean 'internal-ome.api.IUpdate' while setting bean property 'updateService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'internal-ome.api.IUpdate' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.IUpdate.xml]: Cannot resolve reference to bean 'internal-ome.api.LocalAdmin' while setting bean property 'adminService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'internal-ome.api.IAdmin' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.IAdmin.xml]: Cannot resolve reference to bean 'passwordProvider' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'chainedPasswordProvider' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.IAdmin.xml]: Cannot resolve reference to bean 'ldapPasswordProvider' while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ldapPasswordProvider' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.IAdmin.xml]: Cannot resolve reference to bean 'internal-ome.api.ILdap' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'internal-ome.api.ILdap' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.ILdap.xml]: Cannot resolve reference to bean 'contextSource' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextSource' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.ILdap.xml]: Cannot resolve reference to bean 'contextSourceSwapper' while setting bean property 'targetSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextSourceSwapper' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.ILdap.xml]: Cannot resolve reference to bean 'defaultContextSource' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultContextSource' defined in URL [jar:file:/opt/omero/OMERO.server-5.6.10-ice36/lib/server/omero-server.jar!/ome/services/service-ome.api.ILdap.xml]: Bean instantiation via constructor failed; nested exception is java.lang.IllegalAccessError: class org.springframework.ldap.core.support.AbstractContextSource (in unnamed module @0x161b062a) cannot access class com.sun.jndi.ldap.LdapCtxFactory (in module java.naming) because module java.naming does not export com.sun.jndi.ldap to unnamed module @0x161b062a
at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:404)
at ome.system.OmeroContext.getInstance(OmeroContext.java:202)
at ome.services.blitz.Entry.start(Entry.java:189)
at ome.services.blitz.Entry.main(Entry.java:146)
...
Caused by: java.lang.IllegalAccessError: class org.springframework.ldap.core.support.AbstractContextSource (in unnamed module @0x161b062a) cannot access class com.sun.jndi.ldap.LdapCtxFactory (in module java.naming) because module java.naming does not export com.sun.jndi.ldap to unnamed module @0x161b062a
at org.springframework.ldap.core.support.AbstractContextSource.<clinit>(AbstractContextSource.java:77)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271)
... 171 common frames omitted
Setting omero.jvmcfg.append to --add-opens java.base/java.lang=ALL-UNNAMED --add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMED is sufficient to start OMERO.server and perform some minimal workflows: login, import, view, delete...
Minimal testing also indicated the changes above are sufficient to start OMERO.server in a JDK 21 LTS environment.
Dependency upgrades
While the paragraph above describes configuration workarounds that can be used immediately to deploy OMERO.server in a JDK 17 environment, a more robust approach would be to update the underlying libraries to versions that are not relying on features now prevented by the upstream Java changes.
Bitronix Transaction Manager
Bitronix Transaction Manager (btm) is a direct dependency of the omero-server component 7. This library is an implementation of the Java Transaction API 1.1 (JTA). Up to OMERO.server 5.4.x, the dependency was using org.codehaus.btm:btm. In OMERO 5.5.0 and during the transition to decoupled components & the Gradle build system, this dependency was changed to com.github.marcus-nl.btm:btm:3.0.0-mk1.
The latter artifact comes from a fork of https://github.com/scalar-labs/btm which was inactive at the time but it looks like recent activity has started again on this repository. The state of these different existing implementations should be reviewed to assess whether we could upgrade this dependency to a recent version compatible with the JDK encapsulation changes.
Spring LDAP core
spring-ldap-core is a transitive dependency of the omero-server component through org.springframework.security:spring-security-ldap8. The usage of internal com.sun.jndi.ldap classes was fixed upstream in 2.3.4.RELEASE 9. Upgrading manually spring-ldap-core to this version and reverting the --add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMED from the configuration above was sufficient to start the server.
At minimum, it should be possible to upgrade org.springframework.security:spring-ldap-core but this is probably a good opportunity to upgrade spring-security-ldap and review the state of the entire set of Spring dependencies as we have a mixture of versions.
This issue summarizes the current known issues associated with running OMERO.server under a JDK 17 environment and discusses a set of workarounds and proposed changes.
State of Java support
As of OMERO.server 5.6.10, the requirement table of the OMERO documentation 1 defines the current state of Java support. JDK 11 LTS released in September 2018 is the recommendation, JDK 17 LTS released in September 2021 is marked as unsupported and JDK 21 LTS which has been released in September 2023 is not yet captured.
In this table, upstream support for JDK 11 LTS is listed as ending in October 2024 i.e. 6 months from now. The reality is slightly more complex as this timeline largely depends on the OpenJDK build e.g. Oracle JDK 11 is already in extended support 2, the RedHat build of OpenJDK will enter Extended Life Cycle Support in October 3 while Azul Zulu will maintain builds of OpenJDK until 2032 4.
Introducing proper support for Java 17 (and possibly 21) in 2024 would give the community the option either to stay on JDK 11 or upgrade to a more recent JDK LTS version depending on their environment and requirements.
Encapsulation errors and workaround
The bulk of the issues associated with running OMERO.server on JDK 17 are related to the strong encapsulation introduced in Java 16 initially defined in JEP403 5. Various resources are available which describe these changes and their impact on downstream code e.g. 6.
Trying to start OMERO.server-5.6.10-ice36 in a JDK 21 environment on Ubuntu 22.04 results in the following exception
After setting
omero.jvmcfg.append
to--add-opens java.base/java.lang=ALL-UNNAMED
and restarting the serverSetting
omero.jvmcfg.append
to--add-opens java.base/java.lang=ALL-UNNAMED --add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMED
is sufficient to start OMERO.server and perform some minimal workflows: login, import, view, delete...Minimal testing also indicated the changes above are sufficient to start OMERO.server in a JDK 21 LTS environment.
Dependency upgrades
While the paragraph above describes configuration workarounds that can be used immediately to deploy OMERO.server in a JDK 17 environment, a more robust approach would be to update the underlying libraries to versions that are not relying on features now prevented by the upstream Java changes.
Bitronix Transaction Manager
Bitronix Transaction Manager (btm) is a direct dependency of the
omero-server
component 7. This library is an implementation of the Java Transaction API 1.1 (JTA). Up to OMERO.server 5.4.x, the dependency was usingorg.codehaus.btm:btm
. In OMERO 5.5.0 and during the transition to decoupled components & the Gradle build system, this dependency was changed tocom.github.marcus-nl.btm:btm:3.0.0-mk1
.The latter artifact comes from a fork of https://github.com/scalar-labs/btm which was inactive at the time but it looks like recent activity has started again on this repository. The state of these different existing implementations should be reviewed to assess whether we could upgrade this dependency to a recent version compatible with the JDK encapsulation changes.
Spring LDAP core
spring-ldap-core
is a transitive dependency of theomero-server
component throughorg.springframework.security:spring-security-ldap
8. The usage of internalcom.sun.jndi.ldap
classes was fixed upstream in 2.3.4.RELEASE 9. Upgrading manuallyspring-ldap-core
to this version and reverting the--add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMED
from the configuration above was sufficient to start the server.At minimum, it should be possible to upgrade
org.springframework.security:spring-ldap-core
but this is probably a good opportunity to upgradespring-security-ldap
and review the state of the entire set of Spring dependencies as we have a mixture of versions./cc @jburel @pwalczysko @khaledk2 @dominikl @chris-allan @kkoz @joshmoore
Footnotes
https://omero.readthedocs.io/en/v5.6.10/sysadmins/version-requirements.html#id5 ↩
https://www.oracle.com/uk/java/technologies/java-se-support-roadmap.html ↩
https://access.redhat.com/articles/1299013#OpenJDK_Life_Cycle ↩
https://www.azul.com/products/azul-support-roadmap/ ↩
https://openjdk.org/jeps/403 ↩
https://blogs.oracle.com/javamagazine/post/a-peek-into-java-17-continuing-the-drive-to-encapsulate-the-java-runtime-internals ↩
https://github.com/ome/omero-server/blob/f67fdb63410655c6d5a5fc5e566149479bfaa8bc/build.gradle#L48 ↩
https://github.com/ome/omero-server/blob/f67fdb63410655c6d5a5fc5e566149479bfaa8bc/build.gradle#L36 ↩
https://github.com/spring-projects/spring-ldap/releases/tag/2.3.4.RELEASE ↩
The text was updated successfully, but these errors were encountered: