@Grab in Groovy Console on a Scala project fails with NoClassDefFoundError: org/apache/ivy/core/report/ResolveReport
Answered
If I create a new Scala project with
File > New > Project > Scala > sbt > Finish
and then open a Groovy console with Tools > Groovy console and put the following in the console
@Grab(group='commons-codec', module='commons-codec', version='1.12')
and run it I get
java.lang.NoClassDefFoundError: org/apache/ivy/core/report/ResolveReport
I was able to solve with
File > Project Structure > Modules> Dependencies > Add (+) > Library > groovy 2.5.4
And then on the Run tab I clicked on Build and restart, and then Run the console again
But now I have a scala project which uses gradle, so when I go to File > Project Structure > Modules I can't add the Library groovy 2.5.4
Is there any way to add the groovy library without editing the build.gradle?
Please sign in to leave a comment.
Or editing the build.gradle? Because adding
won't solve the ResolveReport error.
And adding
causes a LinkageError:
java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.apache.xerces.parsers.AbstractSAXParser.getErrorHandler()Lorg/xml/sax/ErrorHandler;" the class loader (instance of org/codehaus/groovy/tools/RootLoader) of the current class, org/apache/xerces/parsers/AbstractSAXParser, and the class loader (instance of <bootloader>) for interface org/xml/sax/XMLReader have different Class objects for the type org/xml/sax/ErrorHandler used in the signature
There is a related request to support @Grab annotations directory: https://youtrack.jetbrains.com/issue/IDEA-49022
>Is there any way to add the groovy library without editing the build.gradle?
In a Gradle-based project you should manage dependencies for project only via build.gradle file. Adding the dependency to a build.gradle file is the same as adding it in modules dependencies tab in a non-Gradle based projects like you did:
>I was able to solve with
File > Project Structure > Modules> Dependencies > Add (+) > Library > groovy 2.5.4
Make sure the modules has ResolveReport class in the dependencies and that there are no duplicated classes of different versions from different libraries.
> In a Gradle-based project you should manage dependencies for project only via build.gradle file. Adding the dependency to a build.gradle file is the same as adding it in modules dependencies tab in a non-Gradle based projects like you did
But adding the
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.5.4', ext: 'pom'
does NOT work. I get a ClassNotFoundError: org.apache.ivy.core.report.ResolveReport
So what exactly am I supposed to add to the build.gradle? This is a clean build.gradle with no other dependencies, I just started a new project just to try this.
Make sure the org.apache.ivy.core.report.ResolveReport class is in the project classpath. Can you Navigate | Class to ResolveReport class?
>compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.5.4', ext: 'pom'
does NOT work. I get a ClassNotFoundError: org.apache.ivy.core.report.ResolveReport
Then it means this dependency does not have this class. If you add ivy dependency separately with groovy one, make sure thay are compatible: e.g. use groovy 2.4.5 and ivy 2.4.0
Let's see I have the following build.gradle
plugins {
id 'groovy'
}
group 'com.rubenlaguna'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.5.4'
compile 'org.apache.ivy:ivy:2.4.0'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
The ResolveReport class in the the classpath since I can Navigate > Class > ResolveReport
If I run the following file Test.groovy as a script, with Run 'Test' it works
Now if I use the Tools > Groovy Console , which opens groovy_console_8.groovy and copy the same contents and then click on the Run button (Cmd-Enter). I gest NoClassDefFoundError: ResolveReport.
For me this really looks like the Tools > Groovy Console uses another classpath different than the compile/implementation gradle configuration (which is the one that the Run Test.groovy uses), and I don't know how to influence this classpath.
Groovy console (Tools | Groovy Console... action) uses the current module's classpath. Run/Debug Configuration also uses the classpath of the module, which is specified in Run/Debug Configuration. You can change the module in Groovy console later after the launch:
Please make sure this module has these dependencies listed with the "compile" scope. You can actually see the command line in the very 1st line when launching the console or run configuration (though groovy console writes classpath into a temp file). If issue still remains, could you provide a sample project?
Ok, I didn't know how / where to change the classpath of the Groovy Console until you posted that screenshot.
In my case it shows
with GroovyGradleTest Bundled Groovy 2.4.15 as the default. After selecting the GroovyGradleTest.main Groovy 2.5.4 it works. Thanks
What I don't understand is where the GroovyGradleTest Bundled Groovy 2.4.15 is coming from, and why I have 3 options there and you only have one.
>where the GroovyGradleTest Bundled Groovy 2.4.15 is coming from,
It means that this module does not have Groovy in it's dependencies and IDE uses the bundled Groovy jar in this case.
>why I have 3 options there and you only have one.
You have 3 modules in project and I have 1 in the attached screenshot.
If I go to Project Structure modules I get the following,
These modules I guess they are inferred automatically from build.gradle. So everybody that uses a build.gradle will get in principle 3 modules by default. right?
For me it's a bit weird that IntelliJ selects the Module 1 as the default as that one has nothing inside (I mean no dependencies). But anyway mistery solved. I didn't realized that I will get 3 modules from by almost empty build.gradle and that one of those modules does not contain any dependencies or source code.
I will try to figure out how exactly intellij creates modules out of the buld.gradle. I will possibly ask again in the forum if I can't figure out the answer myself.
For Gradle project IDE creates separate module for a source set (with the Settings (Preferences on macOS) | Build, Execution, Deployment | Build Tools | Gradle | Create separate module per source set by default enabled option) because with current IDE model Gradle source set maps to IDE module best, since they both have separate classpath. See http://mrhaki.blogspot.com/2016/03/gradle-goodness-source-sets-as-intellij.html