I can successfully use Gradle to compile a fat JAR, but having trouble running the JAR after recently switching from the "compile" dependency specification to the "implementation/api" specification. I have isolated that the problem occurs in only one of the two following cases. The application runs in either case inside IntelliJ.
first/problem:
dependencies {implementation 'no.tornado:tornadofx:1.7.18'}
second/works:
dependencies {compile'no.tornado:tornadofx:1.7.18'}
The JAR compiles in both cases. The problem appears when I attempt to start the first case JAR on the command line and it throws the following error.
C:\aaa_eric\code\testr\mic\build\libs>java -jar mic-1.0-snapshot.jar
Error: Could not find or load main class app.MyApp
Caused by: java.lang.NoClassDefFoundError: tornadofx/App
Here is the JAR task in build.gradle. Is it possible that the tornadofx dependency is available at compile time, but not at run time? Thanks for any help.
jar {
manifest {
attributes 'Main-Class': 'app.MyApp'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
Changing configurations.compile.collect to configurations.compileClasspath.collect fixed the problem for me.
I was having the same problem and stumbled across this in https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/ConfigurationContainer.html:
An example showing how to refer to a given configuration by name in
order to get hold of all dependencies (e.g. jars, but only)
apply plugin: 'java' //so that I can use 'implementation', 'compileClasspath' configuration
dependencies {
implementation 'org.slf4j:slf4j-api:1.7.26'
}
//copying all dependencies attached to 'compileClasspath' into a specific folder
task copyAllDependencies(type: Copy) {
//referring to the 'compileClasspath' configuration
from configurations.compileClasspath
into 'allLibs'
}
One thing to note is that configurations.compileClasspath.collect worked for me even when I was using the compile specification instead of implement.
Related
Trying to execute a Corda "fat jar" RPC client that I've built, but it always fails with this error:
Error: Could not find or load main class,
I have confirmed that MANIFEST.MF contains the correct Main-Class attribute, and that this class is included inside the jar.
The relevant part of my build.gradle is:
jar {
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Executing the jar using java -jar myjar.jar always produces this error:
Error: Could not find or load main class
I have posted this question only for reference because some Corda developers have run into this. The problem with creating a "fat jar" as described above is that some Corda jar artifacts are signed, and so contain extra entries like:
META-INF/CORDACOD.SF
META-INF/CORDACOD.EC
These entries don't apply to the "fat jar" and so if you include them into the "fat jar" then the JVM will reject its classes as invalid when you try to execute it.
The best way to create a "fat jar" in Corda is by using a Gradle plugin like shadow. However, if you must do this work by hand then you should alter your jar task accordingly:
jar {
from(configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }) {
exclude "META-INF/*.SF"
exclude "META-INF/*.EC"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
exclude "META-INF/INDEX.LIST"
}
}
While trying to run jacoco in my gradle project, I am getting exceptions.
I have added following dependencies:
compile "org.jacoco:org.jacoco.report:0.7.8"
compile "org.jacoco:org.jacoco.core:0.7.8"
compile "org.ow2.asm:asm-all:5.1"
I also tried with different options like providedCompile, testCompile also.
I am getting this exception, while trying to run "gradle test jacoco" in gitbash.
Exceptions:
org.gralde.api.tasks: TaskExecutionException: Exception failed for
task:'practice-app:jacocoTestReport'
Caused by: java.lang.NoClassDefFoundError:
org/jacoco/report/IReportVistor
Caused by: java.lang.ClassNotFoundException:
org.jacoco.report.IReportVisitor
I also verified other checks like jacoco jars available in my local gradle repo etc.
I had also experienced the similar problem during Jacoco integration in one of our gradle project. The plugin somehow did not bring the required jars. Then, I tried to add all the dependencies manually
say :-
compile "org.jacoco:org.jacoco.report:0.7.8"
compile "org.jacoco:org.jacoco.core:0.7.8"
compile "org.ow2.asm:asm-all:0.7.8"
etc., but that trick also did not work. Still got classnotfound exception against jacoco jars. Then after a lot hit & trial, I came to know about jacocoClasspath. I did the followings:
1) First changed Jacoco version to
jacoco {
toolVersion = "0.7.8+"
}
As got some incompatibility version issue (Don't remember the exact error/exception).
2) Then, added the below code in build.gradle to ensure that required dependencies are present in the jacoco class path.
jacocoTestReport.doFirst {
configurations.testRuntime.each { jacocoClasspath += files(it); }
}
Notes:
1) doFirst will be executed before jacoco task gets executed.
2) I just added whatever present in my runtime to the jacocoClasspath. You may refine the code, to add only the required jars to the jacoco class path.
Deploying an EJB Jar to WildFly 8.2.0 with CDI enabled (i.e. with a minimal beans.xml file) is leading to "Enclosing method not found" exceptions being thrown. There is nothing particularly useful in the logs to identify the source of the error. How do I fix this?
This was because my EJB Jar was being created by Gradle as a "Fat" jar i.e.
task fatJar(type: Jar) {
baseName = project.name + '-all'
from {
configurations.compile
.collect {
println it
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
I also had these artifacts referenced in order to get access to the Java EE libraries I needed:
compile 'javax:javaee-api:7.0'
compile 'javax:javaee-web-api:7.0'
compile 'javax.jms:jms:1.1'
The problem was that these Javax libraries were being pulled into the JAR, which was unnecessary because Wildfly already provides them. The duplication was causing the Weld exception.
The solution was to exclude these Javax libraries from the Fat JAR:
task fatJar(type: Jar) {
baseName = project.name + '-all'
from {
configurations.compile
/*
Effectively the javax libraries are provided in scope,
so don't add them to the jar. Failing to exclude these
leads to Weld CDI exceptions like
*/
.findAll {
it.toString().indexOf('javax') == -1
}
.collect {
println it
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
With this change, the exceptions went away.
In my case I got this error when starting an app from Intellij Idea.
It happened suddenly in an app that worked. Using the debugger I could see that it looked for a method that I have deleted recently. The method was not in use.
The solution was to run mvn clean
I am learning Gradle but I don't understand the jar task code that creates a jar with all the dependencies inside ( taken from Gradle Cookbook ):
jar {
baseName = jarBaseName
manifest { attributes "Main-Class": mainClass }
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
My questions are:
1.The task name is jar. Because it's not written like jar<<{...} I'm assuming that this is run in the configuration phase, and not the execution one. Am I correct?
2.What exactly is configurations.compile? I'm assuming that some kind of dependencies classpath is queried, and each jar is zipTree-ed. Then all of this stuff is merged with the base classpath
. Please elaborate about it
3.The zipTree method, I'm assuming it kind of unarchives each jar but I'm not sure. Am I correct?
Regards,
Yes You're correct. When no action added (mostly with << see docs) the code is run at configuration phase. The code You provided is also run at configuration phase.
configurations.compile refers to a configuration named compile using configurations object (a kind of a configurations container). Prior to gradle 2.0 compile configuration is provided by default with java plugin. AFAIR now it's called javaCompile. According to zipTree You're also correct.
Yes You're.
Is there a way in gradle to specify a dependency (a jar), and then run that jarfile directly within a task?
Here is one way:
configurations {
tool
}
dependencies {
tool "some:tool:1.0"
}
task runTool(type: JavaExec) {
main = "some.tool.Main"
classpath configurations.tool
}
If you don't know the main class and/or want to do the equivalent of java -jar, you need to employ a workaround as described in http://issues.gradle.org/browse/GRADLE-1274.