new to gradle and java here and I am trying to use Android's Log method from android.util.Log. It seems I can compile and it finds what it needs, but it can not find it at runtime. I have tried using 'runtime' instead of 'compile' in the dependencies section, but not luck.
java -jar build/libs/testJavaHttp.jar
Exception in thread "main" java.lang.NoClassDefFoundError: android/util/Log
at myproject.test.HttpToFile.downloadFile(HttpToFile.java:20)
at myproject.test.Main.main(Main.java:12)
Caused by: java.lang.ClassNotFoundException: android.util.Log
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
In build.gradle
apply plugin: 'java'
dependencies {
compile files('../androidsdk/platforms/android-25/android.jar')
}
jar {
manifest {
attributes 'Main-Class': 'myproject.test.Main'
}
}
You are trying to run the jar and the jar is not packed with dependencies, use shadow jar plugin or pack required artifacts in, by extending the jar task.
jar {
archiveName = 'Name.jar'
manifest {
attributes 'Main-Class': 'myproject.test.Main',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' '),
'Implementation-Version': 1.0
}
from(configurations.myconfig.collect { it.isDirectory() ? it : zipTree(it) }) {
// in here you can exclude what you need as well if needed.
}
}
To not pull the 'entire world' into a jar you can create configuration just with libraries you require:
configurations{
myconfig // to create configuration
compile.extendsFrom(myConfig) //to include it in compile as well
}
and then use this config in the jar creation and in dependecies.
dependencies {
myconfig files('../androidsdk/platforms/android-25/android.jar')
}
But looking at your code there is not much to pull there. You need to consider packing all needed artifacts and transitives if you expect it to be a runnable jar, as you run it with 'java -jar [...]' command.
PS. Everything that is in compile is going to be included in runtime configuration as well.
Related
I am building a jar file using gradle. I have local jar files as dependencies. Those jars have additional local dependencies stored in the same directory. I used the following build.gradle file
plugins { id 'application' }
repositories {
flatDir{ dirs 'lib'
}
dependencies {
implementation name: 'localjar1'
implementation name: 'localjar2'
}
application { mainClass = 'mypackage.MyApp' }
jar {
from { configurations.runtimeClasspath.collect {it.isDirectory ? : zipTree(it) } }
manifest { attributes 'Main-Class': 'mypackage.MyApp' }
}
I built the jar using gradle jar, but when I try to run the jar:
java -jar myapp\build\libs\myapp.jar
I get the following error:
Unable to initialize main class mypackage.MyApp
Caused by java.lang.NoClassDefFoundError: com/localpackage/SomeClass
How do bring that dependency in correctly?
I also tried to include the entire local library as a dependency
implementation fileTree(dir: 'lib', include: '*jar')
But when I do this I get the error: java.lang.ClassNotFoundException: mypackage.MyApp
What else should I try?
** Note: I can run the application using gradle run
I have a java console app with 5 classes and has one dependancy, gradle, com.google.code.gson.
I do build an executable jar successfully, however I get the following error when I execute the jar using the command java -jar <jarName>.jar
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
Creating the artifact:
File -> Project Structure -> Artifacts -> "Click on Plus button" -> JAR -> From module with dependancies
I expected the jar file to run
build.gradle
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
test {
useJUnitPlatform()
}
jar {
manifest {
attributes "Main-Class": "org.example.Main"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
IDEA Gui Right Side : Gralde Tab , YourProject -> Tasks -> jar
Find output jar file : YourProject -> build/libs : yourApp.jar
java -jar yourApp.jar
This method is create a fat jar, include dependencies class, only one jar.
No need other external jar files.
I'm using Intellij Idea, with gradlew version 6.8.
Whenever I point implementation keyword for dependencies in build.gradle - I get(example with gson dependency) this exception:
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
at com.epam.adnocove.search.job.EmailVerifier.<clinit>(EmailVerifier.java:19)
at com.epam.adnocove.search.job.UserIndexPipeline.<clinit>(UserIndexPipeline.java:31)
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:636)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:182)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519)
... 2 more
my build.gradle file:
plugins {
id 'java'
}
group 'com.epam.adnocove'
version '1.0'
repositories {
mavenCentral()
}
jar {
manifest {
attributes 'Main-Class': 'Program'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.2'
testImplementation 'junit:junit:4.12'
}
If I put compile instead of implementation - everything works as expected. But what if I don't want transitive dependency. Why gradle doesn't put my dependency to my jar?
The problem is that by default build along with java plugin only - Gradle doesn't pack dependencies into jar - therefore we get an exception.
The solution:
we can use fat jars(by separate task), or use java application plugin which will create OS-specific startup applications which can run built jar.
I am trying to run a jar from Android studio. After a long Workaround, the jar file run perfectly.
Now i need to export the jar file from the android studio. I got the Jar file from the build/libs folder.
But the problem is that the jar file shows a error.
no main manifest attribute, in "app.jar"
So i found this solution. Can't execute jar- file: "no main manifest attribute"
Then i read about MANIFEST.MF & added the mail class to that file.
jar {
manifest.attributes(
'Main-Class': "com.Remo.server.RemoServerApp"
)
}
After adding those in my gradle. My MANIFEST.MF contains the MainClass.
But im still getting the same error? How can i solve this ?
Note: The objective is that I want to Export a Runnable Jar file from the project.
UPDATE:
After Adding the MainClass in MANIFEST.MF. I got stuck with the below error.
Exception in thread "main" java.lang.NoClassDefFoundError: com/Remo/protocol/RemoConnection
at com.Remo.server.RemoServerApp.<init>(RemoServerApp.java:33)
at com.Remo.server.RemoServerApp.main(RemoServerApp.java:97)
Caused by: java.lang.ClassNotFoundException: com.Remo.protocol.RemoConnection
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
MANIFEST.MF
Manifest-Version: 1.0
Main-Class: com.Remo.server.RemoServerApp
UPDATE 2
From your solution what i understood is that we need to copy the remoprotocol jar file to the remoserver.
remoserver project gradle file
apply plugin: 'java'
sourceSets {
main {
resources.srcDirs = ['src/main/resources']
}
}
dependencies {
compile project(':remoprotocol')
compile files('libs/bluecove-2.1.1.jar')
}
jar {
manifest.attributes(
'Main-Class': "com.remo.server.remoServerApp"
)
manifest.attributes(
'Class-Path': configurations.runtime.files.collect { it.getName() }.join(' '))
}
task copyRTDependenciesToLib(type: Copy) {
into "$buildDir/output/lib"
from configurations.runtime
}
After running the gradle task also i am getting the same error.
First you want to copy all your runtime dependencies into the builddir/libs folder (or a different distribution folder if you so choose). Here is a custom task that would achieve this:
task copyRTDependenciesToLib(type: Copy) {
into "$buildDir/libs"
from configurations.runtime
}
Add your runtime dependency jars as a Class-Path attribute in your manifest file. The jars need to be in the same directory as your runnable jar - which the copy task above achieves. (alternatively, you can provide full relative path for your dependency jar location)
jar {
manifest {
attributes(
"Main-Class": "com.Remo.server.RemoServerApp",
"Class-Path": configurations.runtime.files.collect { it.getName() }.join(' '))
)
}
}
Some more things to consider:
The application plugin does the same thing; it adds a task installDist that produces a runnable set of jars along with any dependencies, any readme's, documentation you want to include.
If you want to produce a single runnable jar without having to bundle dependencies along with it, you should look into creating a "fatjar", for example:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': "com.Remo.server.RemoServerApp"
}
baseName = project.name
//collect all dependencies
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
I have no experience with Android Studio (or Gradle), but I have with Java. Aren't you trying to set main class instead?
Therefore I suggest changing Class-Path attribute to Main-Class as the manifest should contain Main-Class to be able to invoke something when "running" JAR.
I'm building a JAR file with Gradle. When I try to run it I get the following error
no main manifest attribute, in RxJavaDemo.jar
I tried manipulating the manifest property but I think I'm forgetting to add the dependencies or something to it. What exactly am I doing wrong?
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'demo.MainDashboard'
dependencies {
compile files ("H:/Processes/Development/libraries/hikari-cp/HikariCP-2.4.1.jar")
compile files ("H:/Processes/Development/libraries/controls-fx/controlsfx.jar")
compile files ("H:/Processes/Development/libraries/database_connections/sqlite-jdbc-3.8.6.jar")
compile files ("H:/Processes/Development/libraries/guava/guava-18.0.jar")
compile files ("H:/Processes/Development/libraries/rxjava/rxjava-1.0.12.jar")
compile files ("H:/Processes/Development/libraries/rxjava-extras/rxjava-extras-0.5.15.jar")
compile files ("H:/Processes/Development/libraries/rxjavafx/RxJavaFX-1.0.0-RC1-SNAPSHOT.jar")
compile files ("H:/Processes/Development/libraries/rxjavaguava/rxjava-guava-1.0.3.jar")
compile files ("H:/Processes/Development/libraries/rxjava-jdbc/rxjava-jdbc-0.6.3.jar")
compile files ("H:/Processes/Development/libraries/slf4j/slf4j-api-1.7.12.jar")
compile files ("H:/Processes/Development/libraries/tom-commons/tom-commons.jar")
}
sourceSets {
main.java.srcDir "src/main/java"
main.resources.srcDir "src/main/resources"
}
jar {
manifest {
attributes(
"Class-Path": configurations.compile.collect { it.getName() }.join(' '))
}
from configurations.compile.collect { entry -> zipTree(entry) }
}
Try to change your manifest attributes like:
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'hello.HelloWorld'
)
}
}
And then just change 'hello.helloWorld' to '<your packagename>.<the name of your Main class>' (where your Main class has a main method). In this case, you make in your manifest an attribute, which point to this class, then a jar is running.
To make the jar file executable (so that the java -jar command works), specify the Main-Class attribute in MANIFEST.MF.
In Gradle, you can do it by configuring the jar task.
for Groovy DSL see these answers ([1], [2])
for Kotlin DSL you can use the following code snippet:
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = "com.caco3.Main"
}
}
Why mainClassName does not work as expected?
Or why mainClassName does not specify the attribute in the manifest?
The mainClassName property comes from the application plugin. The plugin:
makes it easy to start the application locally during development, and to package the application as a TAR and/or ZIP including operating system specific start scripts.
So the application plugin does not aim at producing executable jars
When a mainClassName property set, then:
$ ./gradlew run will launch the main method in the class specified in the attribute
the zip/tar archive built using distZip/distTar tasks will contain a script, which will launch the main method of the specified previously class.
Here is the line of shell script setting the main class:
$ grep Main2 gradletest
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLETEST_OPTS -classpath "\"$CLASSPATH\"" com.caco3.gradletest.Main2 "$APP_ARGS"
To complement Denis Zavedeev answer, here are more ways for Kotlin DSL (build.gradle.kts):
tasks.jar {
manifest.attributes["Main-Class"] = "com.example.MyMainClass"
}
tasks.jar {
manifest {
attributes["Main-Class"] = "com.example.MyMainClass"
}
}
Side note: to create a runnable fat JAR (also called uber JAR), see this post.
FWIW - I used the following jar task to assemble all my compile dependencies into the jar file, and used the above recommendation to get the class-path properly set
apply plugin: 'java-library'
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'your.main.class.goes.here'
)
}
// You can reference any part of the dependency configurations,
// and you can have as many from statements as you need
from configurations.compile
// I just copied them into the top of the jar, so it looks like the eclipse exported
// runnable jar, but you could designate a lib directory, and reference that in the
// classpath as "lib/$it.name" instead of it.getName()
into ''
}