[OPENDJ-6488] Non-obvious error message from setup when using outdated Java Created: 26/Jul/19  Updated: 08/Nov/19  Resolved: 02/Oct/19

Status: Done
Project: OpenDJ
Component/s: setup
Affects Version/s: 7.0.0
Fix Version/s: Not applicable

Type: Bug Priority: Major
Reporter: Mark Craig Assignee: Jean-Noël Rouvignac
Resolution: Won't Fix Votes: 0
Labels: None

Issue Links:
is related to OPENDJ-6489 DS docs no longer build on Jenkins Done
Story Points: 1
Dev Assignee: Jean-Noël Rouvignac


Users would rather see something like "Java 8 is no longer supported. Upgrade to at least Java 11.0.3." Not "An unexpected error has been raised during setup: 'java.lang.StringBuilder'":

$ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
$ mvn -Dformats=html
[INFO] --- exec-maven-plugin:1.5.0:exec (set-up-opendj) @ schema-reference ---

Store the following deployment key (deployment key password is the same as the
root user password) in a safe place and re-use it when configuring other
servers in the topology:


Validating parameters..... Done
An unexpected error has been raised during setup: 'java.lang.StringBuilder'
See /tmp/opendj-setup-3535527918245789417.log for a detailed log of the failed
Please report this error and provide the log file mentioned above.
[ERROR] Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1) 

Comment by Peter Major [X] (Inactive) [ 28/Jul/19 ]

The actual underlying stacktrace is:

java.lang.ArrayStoreException: java.lang.StringBuilder
	at com.forgerock.opendj.util.StringPrepProfile.prepareUnicode(StringPrepProfile.java:434)
	at org.forgerock.opendj.ldap.schema.SchemaUtils.normalizeStringAttributeValue(SchemaUtils.java:711)
	at org.forgerock.opendj.ldap.schema.CaseIgnoreEqualityMatchingRuleImpl.normalizeAttributeValue(CaseIgnoreEqualityMatchingRuleImpl.java:38)
	at org.forgerock.opendj.ldap.schema.MatchingRule.normalizeAttributeValue(MatchingRule.java:509)
	at org.forgerock.opendj.ldap.Ava.getEqualityNormalizedValue(Ava.java:670)
	at org.forgerock.opendj.ldap.Ava.toNormalizedByteString(Ava.java:719)
	at org.forgerock.opendj.ldap.Rdn.toNormalizedByteString(Rdn.java:522)
	at org.forgerock.opendj.ldap.Dn.toNormalizedByteString(Dn.java:1023)
	at org.forgerock.opendj.ldif.Ldif.toNormalizedByteArray(Ldif.java:850)
	at org.forgerock.opendj.ldif.Ldif.readEntriesAsMap(Ldif.java:836)
	at org.forgerock.opendj.ldif.Ldif.patch(Ldif.java:544)
	at org.forgerock.opendj.ldif.Ldif.patch(Ldif.java:513)
	at org.forgerock.opendj.setup.model.SetupUtils.patchLdifFile(SetupUtils.java:811)
	at org.forgerock.opendj.setup.model.SetupUtils.writeVersionsInConfigFile(SetupUtils.java:797)
	at org.forgerock.opendj.setup.model.Setup.writeVersionsInConfig(Setup.java:1681)
	at org.forgerock.opendj.setup.model.Setup.configure(Setup.java:1667)
	at org.forgerock.opendj.setup.model.Setup.setup(Setup.java:1542)
	at org.forgerock.opendj.setup.cli.SetupCli.run(SetupCli.java:208)
	at org.forgerock.opendj.setup.cli.SetupCli.main(SetupCli.java:161)

When DJ is compiled with JDK 11 to bytecode 8, and the generic Reject.ifNull method is being called (that was compiled by 8 to 8), looks like the JVM gets confused in terms of what the varargs array type should be. Both arguments implement Comparable, but with a different generic type, and it looks like that the automatic type inference for the generic method call goes sideways. A quick fix would be to make the ifNull call generic: Reject.<Object>ifNull(...); but finding all these possible issues would not be simple. Alternative solution would be to use Object... type instead of generics in Reject.ifNull, but that would be a potentially binary incompatible change, and it would reintroduce some unintentional compiler warnings.

Even when one gets past this one issue, there is another:

Exception in thread "main" java.lang.NoSuchMethodError: java.nio.CharBuffer.flip()Ljava/nio/CharBuffer;
	at org.forgerock.opendj.ldap.Ava.toNormalizedUrlSafe(Ava.java:745)
	at org.forgerock.opendj.ldap.Rdn.toNormalizedUrlSafeString(Rdn.java:558)
	at org.forgerock.opendj.ldap.Dn.toNormalizedUrlSafeString(Dn.java:1048)
	at org.opends.server.backends.pluggable.EntryContainer.<init>(EntryContainer.java:414)
	at org.opends.server.backends.pluggable.RootContainer.openEntryContainer(RootContainer.java:219)
	at org.opends.server.backends.pluggable.RootContainer.openAndRegisterEntryContainers(RootContainer.java:260)
	at org.opends.server.backends.pluggable.RootContainer.lambda$open$0(RootContainer.java:144)
	at org.opends.server.backends.jeb.JEStorage.write(JEStorage.java:1085)
	at org.opends.server.backends.pluggable.TracedStorage.write(TracedStorage.java:442)
	at org.opends.server.backends.pluggable.RootContainer.open(RootContainer.java:142)
	at org.opends.server.backends.pluggable.BackendImpl.newRootContainer(BackendImpl.java:772)
	at org.opends.server.backends.pluggable.BackendImpl.importLDIF(BackendImpl.java:543)
	at org.opends.server.tools.ImportLdif.processLocal(ImportLdif.java:712)
	at org.opends.server.tools.tasks.TaskTool.process(TaskTool.java:315)
	at org.opends.server.tools.ImportLdif.runTaskTool(ImportLdif.java:335)
	at org.opends.server.tools.tasks.TaskTool.run(TaskTool.java:289)
	at org.opends.server.tools.tasks.TaskTool.runEmbeddedOffline(TaskTool.java:118)
	at org.opends.server.tools.ImportLdif.importLdifEmbeddedOffline(ImportLdif.java:252)
	at org.forgerock.opendj.setup.model.Profile$ScriptOperations.importLdif(Profile.java:695)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
	at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127)
	at profile.run(profile.groovy:130)

One way to fix these is:
Which is rather annoying.
At this point I think the best way to move on this issue is to move forward: change the base requirement for DJ to JDK 11, and update all the things to require at least JDK 11.

Comment by Jean-Noël Rouvignac [ 29/Jul/19 ]

Many thanks for your help Peter.
The issue with ArrayStoreException is very surprising. It looks like Java 11 is able to instantiate fairly complex array descriptions that Java 8 does not grok.

The NoSuchMethodError is a classical issue of the return type of a method that changed to a contravariant return type. The return type for CharBuffer.flip() has changed to a more sub class of what it previously was. Compiling on JDK 11 uses the method overload with the more precise type which is Java-11 only. When running that code on Java 8, the JVM barfs because it cannot find this Java-11 only API.
Travis used the trick to cast to Buffer in commons, but I find this ugly.

At this point I agree it is better to wait for full compilation into Java 11 binaries and fully discard support for Java 8.

Comment by Jean-Noël Rouvignac [ 02/Oct/19 ]

Since this problem arises deep in the bowels of Java code (missing Java 11 methods that do not exist in Java 8 -> NoSuchMethodError), it is not obvious how we can deal with it properly.
The fix is simply to compile effectively with Java 8 when the supported platform is Java 8, and move fully to Java 11 when we will only support Java 11.

As a consequence we are not going to fix this.

Comment by Matthew Swift [ 07/Nov/19 ]

Moved to closed state because the fixVersion has already been released.

Generated at Mon Nov 30 14:33:23 UTC 2020 using Jira 7.13.12#713012-sha1:6e07c38070d5191bbf7353952ed38f111754533a.