groovy
  1. groovy
  2. GROOVY-6156

Grapes/@Grab does not work with JDK8

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.1.3, 2.2.x
    • Fix Version/s: 2.1.8, 1.8.10
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      Groovy appears not to be able to run TestNG tests. The code:

      @Grab('org.testng:testng:6.8.5')
      @Grab('org.codehaus.groovy:groovy-testng:2.2.0-SNAPSHOT')
      import org.testng.annotations.Test
      import static org.testng.Assert.assertEquals
      
      class testngFails {
        @Test void calculateTheResult() {
          assertEquals('Hello World.', 'Hello World.')
        }
      }
      

      when executed results in the output:

      Caught: org.testng.TestNGException:
      An error occurred while instantiating class testngFails: null
      org.testng.TestNGException:
      An error occurred while instantiating class testngFails: null
      at org.testng.internal.ClassHelper.createInstance1(ClassHelper.java:398)
      at org.testng.internal.ClassHelper.createInstance(ClassHelper.java:299)
      at org.testng.internal.ClassImpl.getDefaultInstance(ClassImpl.java:110)
      at org.testng.internal.ClassImpl.getInstances(ClassImpl.java:186)
      at org.testng.internal.TestNGClassFinder.<init>(TestNGClassFinder.java:120)
      at org.testng.TestRunner.initMethods(TestRunner.java:409)
      at org.testng.TestRunner.init(TestRunner.java:235)
      at org.testng.TestRunner.init(TestRunner.java:205)
      at org.testng.TestRunner.<init>(TestRunner.java:153)
      at org.testng.SuiteRunner$DefaultTestRunnerFactory.newTestRunner(SuiteRunner.java:522)
      at org.testng.SuiteRunner.init(SuiteRunner.java:157)
      at org.testng.SuiteRunner.<init>(SuiteRunner.java:111)
      at org.testng.TestNG.createSuiteRunner(TestNG.java:1273)
      at org.testng.TestNG.createSuiteRunners(TestNG.java:1260)
      at org.testng.TestNG.runSuitesLocally(TestNG.java:1114)
      at org.testng.TestNG.run(TestNG.java:1031)
      Caused by: java.lang.ExceptionInInitializerError
      at org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:29)
      at org.testng.internal.ClassHelper.createInstance1(ClassHelper.java:387)
      ... 15 more
      Caused by: java.lang.RuntimeException: No suitable ClassLoader found for grab
      at testngFails.<clinit>(testngFails.groovy)
      ... 17 more

        Issue Links

          Activity

          Hide
          Russel Winder added a comment -

          Paul, things are exactly the same.

          @Grab('org.testng:testng:6.8.7')
          @Grab('com.google.inject:guice:3.0')
          @Grab('org.codehaus.groovy:groovy-testng:2.3.0-SNAPSHOT')
          import org.testng.annotations.Test
          import static org.testng.Assert.assertEquals
          
          class GROOVY_6156 {
            @Test void calculateTheResult() {
              assertEquals('Hello World.', 'Hello World.')
            }
          }
          

          gives me:

          Caught: java.lang.NoClassDefFoundError: com/google/inject/Module
          java.lang.NoClassDefFoundError: com/google/inject/Module
          Caused by: java.lang.ClassNotFoundException: com.google.inject.Module

          whether I use Java 7 or Java 8.

          I have other @Grabs working on Java 8 so it is something specific to this combination.

          Show
          Russel Winder added a comment - Paul, things are exactly the same. @Grab('org.testng:testng:6.8.7') @Grab('com.google.inject:guice:3.0') @Grab('org.codehaus.groovy:groovy-testng:2.3.0-SNAPSHOT') import org.testng.annotations.Test import static org.testng.Assert.assertEquals class GROOVY_6156 { @Test void calculateTheResult() { assertEquals('Hello World.', 'Hello World.') } } gives me: Caught: java.lang.NoClassDefFoundError: com/google/inject/Module java.lang.NoClassDefFoundError: com/google/inject/Module Caused by: java.lang.ClassNotFoundException: com.google.inject.Module whether I use Java 7 or Java 8. I have other @Grabs working on Java 8 so it is something specific to this combination.
          Hide
          Paul King added a comment -

          Russel, does the @GrabConfig as per my example help?

          Show
          Paul King added a comment - Russel, does the @GrabConfig as per my example help?
          Hide
          Russel Winder added a comment -

          Yes it does. Sorry I had completely missed that.

          So the question here is, can the Guice dependency alone be put in via the system class loader or is it required to have TestNG and the Groovy-TestNG loaded there as well?

          Show
          Russel Winder added a comment - Yes it does. Sorry I had completely missed that. So the question here is, can the Guice dependency alone be put in via the system class loader or is it required to have TestNG and the Groovy-TestNG loaded there as well?
          Hide
          Russel Winder added a comment -

          Just did the experiment, it is only Guice that has to go in via the system class loader. The following works fine:

          @Grab('com.google.inject:guice:3.0')
          @GrabConfig(systemClassLoader=true)
          import java.util.concurrent.ConcurrentHashMap
          
          @Grab('org.testng:testng:6.8.7')
          @Grab('org.codehaus.groovy:groovy-testng:2.3.0-SNAPSHOT')
          import org.testng.annotations.Test
          import static org.testng.Assert.assertEquals
          
          class GROOVY_6156 {
            @Test void calculateTheResult() {
              assertEquals('Hello World.', 'Hello World.')
            }
          }
          

          Assuming the @GrabConfig is local to the one @Grab and not a global setting.

          Show
          Russel Winder added a comment - Just did the experiment, it is only Guice that has to go in via the system class loader. The following works fine: @Grab('com.google.inject:guice:3.0') @GrabConfig(systemClassLoader= true ) import java.util.concurrent.ConcurrentHashMap @Grab('org.testng:testng:6.8.7') @Grab('org.codehaus.groovy:groovy-testng:2.3.0-SNAPSHOT') import org.testng.annotations.Test import static org.testng.Assert.assertEquals class GROOVY_6156 { @Test void calculateTheResult() { assertEquals('Hello World.', 'Hello World.') } } Assuming the @GrabConfig is local to the one @Grab and not a global setting.
          Hide
          Paul King added a comment - - edited

          Unfortunately it's global at the moment. The plan was for the @Grapes annotation to be the grouping mechanism which meant you could have put the guice @Grab and @GrabConfig inside a @Grapes and it would have been isolated - but we haven't implemented it to date. The thinking has been that @Grab is meant for simple dependency declarations. If you have something more complex than what is currently supported, perhaps in general you are better off leveraging a build system like gradle or even considering OSGi if you need strict isolation and can justify the added complexity.

          So, today we just merge all @Grab related annotations together - making the @Grapes annotation effectively a no-op at the moment and hence why we don't encourage it much these days. If we had needed to keep the @Grab annotations around until runtime we would have needed @Grapes as a holder but as of Java 8 we could even hide that away with the @Repeatable meta-annotation.

          I still think we should eventually add the @Grapes isolation capability, so I'm not advocating deprecating @Grapes - just indicating the current state of play.

          Show
          Paul King added a comment - - edited Unfortunately it's global at the moment. The plan was for the @Grapes annotation to be the grouping mechanism which meant you could have put the guice @Grab and @GrabConfig inside a @Grapes and it would have been isolated - but we haven't implemented it to date. The thinking has been that @Grab is meant for simple dependency declarations. If you have something more complex than what is currently supported, perhaps in general you are better off leveraging a build system like gradle or even considering OSGi if you need strict isolation and can justify the added complexity. So, today we just merge all @Grab related annotations together - making the @Grapes annotation effectively a no-op at the moment and hence why we don't encourage it much these days. If we had needed to keep the @Grab annotations around until runtime we would have needed @Grapes as a holder but as of Java 8 we could even hide that away with the @Repeatable meta-annotation. I still think we should eventually add the @Grapes isolation capability, so I'm not advocating deprecating @Grapes - just indicating the current state of play.

            People

            • Assignee:
              CÚdric Champeau
              Reporter:
              Russel Winder
            • Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: