Adding "runtime" libraries in a Gradle build happens neither smoothly nor at all
So, there is something completely wrong with the logic of the user interface. Or with me. I just don't understand how it is supposed to work.
I have a Java project / Gradle build in IntellijIDEA 2021.2.3 (Ultimate Edition).
The goal is to read a YAML file with Jackson. Pretty easy, wouldn't you say.
In "build.gradle", the following dependencies have been added manually (among others which I leave out below)
dependencies {
// Jackson is needed to read YAML files
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
implementation 'com.fasterxml.jackson.core:jackson-core:2.13.1'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.1'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.1'
...
}
So far so good.
Compilation succeeds, but when trying to run the program:
Error: Unable to initialize main class starter.YamlRead
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory
Process finished with exit code 1
So, there is some problem with finding those libraries at runtime. It apparently doesn't happen automatically for some reason.
I find out that under:
File > ProjectStructure (left bar) Project Settings > Modules > Main
the libraries are indeed listed:

Likewise, under "modules", the libraries are listed as well (not sure where the entry for "databind" comes from here though):

But note that their "scope" is "Compile" for some reason that is left unexplained. This may mean either "Compile only" or "Compile and Runtime", not sure - but the runtime failure would indicate that this indeed means "Compile only".
At that point, I can switch them to "Runtime" scope.
It is unfortunate that I cannot mark libraries both with "Runtime" and "Compile" time - the interface gives me an "exclusive selection" dropdown menu.
To have them available for both occasions, I would need to "copy a line" but this interface does not have an option to do that and it may not be possible for all I know.
Anyway, switching them to "runtime" and clicking "Apply" gives a cryptic warning at the bottom of the dialog, which I interprete to mean that, if I change the "build.gradle" file later, the changes in this dialog will be lost.

But it still doesn't work, alas:
Error: Unable to initialize main class starter.YamlRead
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory
Process finished with exit code 1
I'm completely at a loss on how to continue.
What do I have to fix here?
请先登录再写评论。
>But note that their "scope" is "Compile" for some reason that is left unexplained.
Compile - means at cimpile and runtime scopes, please see related documentation about dependencies scopes.
>Anyway, switching them to "runtime" and clicking "Apply" gives a cryptic warning at the bottom of the dialog, which I interprete to mean that, if I change the "build.gradle" file later, the changes in this dialog will be lost.
Yes. In a Gradle/maven - based projects, IDE takes all configuration related to building and project structure from build files. So any chnages in the UI to the project structure will be lost on re-import from Gradle/Maven.
>But it still doesn't work, alas:
Do you have Gradle or IntelliJ IDEA set for Settings (Preferences on macOS) | Build, Execution, Deployment | Build Tools | Gradle | Build and run using option?
How does it work if you run it by Gradle from the command line? If you get same error from command line Gradle, it is likely the issue with dependencies configuration. E.g. check that you are using only compatible versions: https://stackoverflow.com/a/69283301/2000323
Thank you Andrey!
I have tried to create a new project with the same content to isolate the problem - and found the error:
In the runtime configuration, the classpath argument was pointing to the project directory toplevel ("phasmomycin2") -- as shown below -- instead of the "main" java directory ("phasmomycin2.main"). (Those are placeholders resolved by IDEA, right?) I don't know how that happened.
Note that IDEA highlights the textarea with the "class to execute" in red because it can't find that class. However, running this erroneous configuration still works (although not if you need 3rd party libraries apparently).
I was thinking about fixing the highlighted textarea "later", well it's fixed now.
Additionally, to make doubly sure that everything is configured properly, I manually removed the jackson dependencies from build.gradle and re-added them as described in
https://www.jetbrains.com/help/idea/work-with-gradle-dependency-diagram.html - "Gradle dependencies" Last modified: 07 September 2021
Right Click in the window for build.gradle inside the "dependencies" block": "Generate" > "Add Maven Artifact Dependency" then "Search for Artifact", which yields the expected text in build.gradle
The "Gradle Tool" (clickable element on the right border) then says:
Checking against File > Project Settings > Modules shows the dependencies under "$PROJECT/main" as "Compile" (no "Runtime" entries):
All fine.
I had a similar situation where I needed to have ‘org.apache.logging.log4j.core’ as a runtime library but when I issued my gradle ‘run’ command in Intellij Idea I got:
java.lang.ClassNotFoundException: org.apache.logging.log4j.Loggerdespite including it as a dependency in my build.gradle as
implementation (group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.20.0')In the end I fixed this by including
requires org.apache.logging.log4jin my module-info.java:module mymodule {exports mymodule;// simple logging facade for compile timerequires org.slf4j;// required log4j core for run time bindingrequires org.apache.logging.log4j;}