0

We are building REST API with tests. The API runs perfectly and we don't have any issue with it. The errors we am getting are in the testing part.

The tests uses Rest Assured library. We have to use JDK 17 as an organization level choice.

We are facing a challenge in running our REST Assured Tests after updating to JDK 17. Perhaps it has something to do with reflection not being permitted in JDK 17

We are getting java.lang.ExceptionInInitializerError for following lines of code

    RestAssured.baseURI = Constants.BASE_URI;

    RestAssured.port = Constants.PORT;

    RestAssured.basePath = Constants.BASE_PATH;

Do you have any advice/solution/work-arounds. We cannot use a different version of Java since this is an organization level choice.

We setting the baseURI, port and basePath for all the tests using the code shared above. It was working earlier, but after we moved to JDK 17 there seems to be a problem.

java.lang.ExceptionInInitializerError
    at io.restassured.builder.RequestSpecBuilder.<init>(RequestSpecBuilder.java:79)
    at com.teamcenter.services.strong.utils.TestBase.createRequestSpecification(TestBase.java:99)
    at com.teamcenter.services.strong.utils.TestBase.createRequestSpecification(TestBase.java:82)
    at com.teamcenter.services.strong.utils.TestBase.setUp(TestBase.java:116)
    at com.teamcenter.services.strong.IncludeRuleTest.setUp(IncludeRuleTest.java:36)
    at junit.framework.TestCase.runBare(TestCase.java:140)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:130)
    at junit.framework.TestSuite.runTest(TestSuite.java:241)
    at junit.framework.TestSuite.run(TestSuite.java:236)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make java.lang.String(char[],int,int,java.lang.Void) accessible: module java.base does not "opens java.lang" to unnamed module @3cda1055
    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.Constructor.checkCanSetAccessible(Constructor.java:188)
    at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:181)
    at org.codehaus.groovy.reflection.CachedConstructor$1.run(CachedConstructor.java:44)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
    at org.codehaus.groovy.reflection.CachedConstructor.<init>(CachedConstructor.java:42)
    at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:79)
    at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:69)
    at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:49)
    at org.codehaus.groovy.util.LazyReference.get(LazyReference.java:36)
    at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:268)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)
    at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:253)
    at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:285)
    at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:295)
    at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:261)
    at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:873)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.createPojoSite(CallSiteArray.java:125)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:166)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at io.restassured.internal.RequestSpecificationImpl.<clinit>(RequestSpecificationImpl.groovy:86)
    ... 19 more
Slaw
  • 37,820
  • 8
  • 53
  • 80
  • 1
    I love [guessing](https://github.com/rest-assured/rest-assured/wiki/GettingStarted#java-9). – Elliott Frisch Feb 17 '23 at 04:35
  • For some explanation of the error, see [How to solve InaccessibleObjectException ("Unable to make {member} accessible: module {A} does not 'opens {package}' to {B}") on Java 9?](https://stackoverflow.com/q/41265266/6395627). – Slaw Feb 17 '23 at 04:36
  • @ElliottFrisch That talks about split packages. The error the OP has is not about split packages. Or am I missing something? – Slaw Feb 17 '23 at 04:48
  • @Slaw We have no idea how OP is packaging their code or even what version of restassured OP is using; hence **guessing**. But *module java.base does not "opens java.lang" to unnamed module* implies modules. Modules are Java 9+. And that note is labeled "java 9+" – Elliott Frisch Feb 17 '23 at 05:00

1 Answers1

3

This is a fundamental problem of Groovy.

Groovy is a dynamic language, using Reflection to access members, and it calls setAccessible(true) on all of them.

It wasn’t meant to work that way but has been implemented this way to fix access from closures to private members with the collateral damage of ignoring private everywhere. See

The constructor String(char[],int,int,java.lang.Void) does not even exist in older Java versions, so this is not the case of an old program relying on it, but instead, the Groovy runtime tries to cache all members of the class and is calling setAccessible(true) in advance, as we can deduce from the stacktrace

    at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:268)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
    at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
    at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)

Note the name part MetaClass suggesting per-class processing and the plural in the method name getConstructors suggesting that it tries to get all constructors.

Since you are not even trying to access a member of class String in the posted code, it seems that it is already enough to use/reference a type to trigger the initialization of the meta information.


For ordinary Java software, we would suggest to identify the places where the software is accessing internals, then include a specific --add-opens option as a temporary work-around, and rewrite the specific part to not access internals on the long term.

However, for Groovy, you’d have to add such an option for every package the script is using, with no option to rewrite the code to get rid the issue eventually.

Which does not imply that there can’t be truly problematic parts, accessing internals, perhaps accidentally. It’s just that you can’t tell them apart from legitimate uses of the classes.

It’s unlikely that a behavior lasting since 2007 gets fixed or that such a fix could be done without breaking things at other places, i.e. the unintended accesses mentioned above or even intended ones, as some people consider this a feature.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • 1
    Thank you. For those who will visit this thread in the future, I was working with older versions of Groovy and Rest-Assured. Problem solved post upgrade to rest-assured 5.3.0, groovy 4.0.9. Really appreciate the service of the stackoverflow community. – Dhiraj Shetty Feb 18 '23 at 05:22