After upgrading to Confluence 8 with JDK17 a 'System Error' is triggered in method 'isShowSignUp' due to 'NoClassDefFoundError: Could not initialize class org.springframework.ldap.core.support.LdapContextSource'
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
When Confluence starts, it needs to access the User Directories in order to get the number of licensed users. As this is not possible, you will get a 'System Error' in the Confluence UI.
In this specific use-case, JDK 17 is restricting the access to some LDAP access classes in Confluence 8, which prevents this process to complete successfully.
Environment
Confluence 8.0 or later using JDK 17.
Diagnosis
In the atlassian-confluence.log
, you see entries like the following one at start-up time:
2023-07-05 12:17:36,484 ERROR [http-nio-8090-exec-2 url: /login.action] [apache.struts2.result.VelocityResult] doExecute Unable to render velocity template: '/login.vm'
-- url: /login.action | userName: anonymous | action: login | traceId: 06d3a2d227984e5b
org.apache.velocity.exception.MethodInvocationException: Invocation of method 'isShowSignUp' in class com.atlassian.confluence.user.actions.LoginAction threw exception java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.ldap.core.support.LdapContextSource at /login.vm[line 6, column 28]
at org.apache.velocity.runtime.parser.node.ASTMethod.handleInvocationException(ASTMethod.java:342)
at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:284)
...
...
Caused by: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.ldap.core.support.LdapContextSource
at java.base/java.util.concurrent.FutureTask.report(Unknown Source)
at java.base/java.util.concurrent.FutureTask.get(Unknown Source)
at com.atlassian.confluence.util.ReadOnlyLicenseCalculator.getNumberOfLicensedUsers(ReadOnlyLicenseCalculator.java:62)
...
...
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.ldap.core.support.LdapContextSource
at com.atlassian.crowd.directory.LdapContextSourceFactory.createContextSource(LdapContextSourceFactory.java:73)
at com.atlassian.crowd.directory.LdapContextSourceProvider.getPooledContextSource(LdapContextSourceProvider.java:28)
at com.atlassian.crowd.directory.SpringLDAPConnector.getContextSource(SpringLDAPConnector.java:208)
at com.atlassian.crowd.directory.SpringLDAPConnector.setAttributes(SpringLDAPConnector.java:184)
at com.atlassian.crowd.directory.loader.RemoteDirectoryInstanceFactoryUtil.newRemoteDirectory(RemoteDirectoryInstanceFactoryUtil.java:42)
...
...
Cause
Some tools and libraries use reflection to access parts of the JDK that are meant for internal use only. This use of reflection negatively impacts the security and maintainability of the JDK. To aid migration, JDK 9 through JDK 16 allowed this reflection to continue, but emitted warnings about illegal reflective access. However, JDK 17 is strongly encapsulated, so this reflection is no longer permitted by default.
Consequently, some internal APIs need to be expose for being accessible by other libraries which depend upon them.
Additional information also available in:
- JEP 403: Strongly Encapsulate JDK Internals
- JEP 261: Module System
- CONFSERVER-83907 - Confluence 8.3 EAP Feedback
Solution
Solution 1
You can use the already prepared file jpms-args.txt
contains the necessary arguments to expose these internal APIs:
Add following system property in your
setenv.sh
file:# Add various JPMS arguments to allow Confluence to work on Java 17 CATALINA_OPTS="@$CATALINA_HOME/confluence/WEB-INF/jpms-args.txt ${CATALINA_OPTS}"
- Restart Confluence
Solution 2
Otherwise, add the specific JVM flag to solve the situation related to the class LdapContextSource:
Add following system property in your
setenv.sh
file:CATALINA_OPTS="--add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMED ${CATALINA_OPTS}"
- Restart Confluence