I need to distribute one of our integration tests, it lives under src/test. So I'm using gradle to build a jar pointing to this class.
I figured this out from poking around the net:
task fatJar(type: Jar) {
zip64 = true
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': 1.3,
'Main-Class': 'org.example.AnIntegrationTest'
}
from sourceSets.test.output
}
When I try running this I get the:
Error: Could not find or load main class org.example.AnIntegrationTest
The main method is there, and 'jar tf' does show me the class in the package.
What am I missing here?
Your jar file is missing test-runtime dependencies. One possible solution is to package all required dependencies into your jar as well. Note that this will increase the size of your distributable jar.
Add an additional from clause to your jar task:
task fatJar(type: Jar) {
zip64 = true
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': 1.3,
'Main-Class': 'org.example.AnIntegrationTest'
}
from sourceSets.test.output
//collect all dependencies
from { configurations.testRuntime.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Related
I'm building a jar file with Gradle. This jar file is being used as a library in another project. But when the project tries to use the jar file, a ClassNotFoundException is returned.
Caused by: java.lang.NoClassDefFoundError: com/auth0/jwt/JWT
I've included the jwt library in the gradle file building the jar:
compile group: 'com.auth0', name: 'java-jwt', version: '3.4.0'
The project using the jar can't seem to find this jar dependency in the jar.
I built the jar with the gradle command:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Jar File creation',
'Implementation-Version': version,
'Main-Class': 'com.group.me.name.MyJarClass'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
How do I include the missing dependency in the jar?
You, generally, should not pack the dependencies inside a published JAR. It's better to declare them as dependencies in pom.xml and let the user of you JAR fetch them. It's just a good practice that should be enough.
If it's not enough, use Gradle Shadow:
plugins {
id 'com.github.johnrengelman.shadow' version '4.0.2'
}
Fat JAR is produced with shadowJar task in this case. Publishing is easy as well:
publishing {
publications {
shadow(MavenPublication) { publication ->
project.shadow.component(publication)
}
}
repositories {
maven {
url "http://your.repo"
}
}
}
I have a a fatjar, which is a deployable jar with main method defined, and which depedencies are copied via gradle.
This works fine.
I want to obsufucate/encrypt my jar.
Using proguard I can obsufucate myJar, and specify libraryjars. How do I get a farJar created from the obsufucated jar and its dependencies ?
So far I can only obsufucate the original jar, not obsufucate and bundle as fat jar.
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Metriculous',
'Implementation-Version': version,
'Main-Class': 'au.com.metriculous.MetriculousServer'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
my proguard task looks pretty much the same as the samples, the library jars don't get added to jar as fatJar. And I don't want to define lots of rules for not obsufucating injars, which I could do if I simply obsufucate the whole fatjar ?
In a build.gradle script, I would perform the following task to include dependencies into a runnable application JAR file.
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'org.somepackage.MyMainClass'
)
}
from configurations.compile.collect { entry -> zipTree(entry) }
}
However, in multi-project setups I was missing some dependencies in the JAR file. I ultimately discovered any dependencies specified in other project build.gradle scripts were not being included, unless the parent project had those dependencies too.
For example, Project A depends on Project B. Project B uses Google Guava. When I deployed Project A to a runnable JAR file, Google Guava would not be included and there would be runtime errors. If Project A redundantly specified Google Guava in its build.gradle script, then it runs just fine.
How can I modify my jar task above to include dependencies in multi-project setups?
I got some ideas from this post that seemed to work.
jar {
manifest {
attributes(
'Main-Class': 'com.swa.rm.pricing.reporting.ux.SaleMxReportingUI'
)
}
}
task fatJar(type: Jar) {
manifest.from jar.manifest
classifier = 'all'
from {
configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
with jar
}
I am using Gradle for my Java project and I was wondering if it's possible to prevent gradle build from creating a jar file each time executed.
Also, is it possible to have a custom task for creating the Jar with dependencies at a specific location build/myAppJar/.
Here's what I have so far for the custom task:
task toJar (type: Jar) {
from configurations.compile.collect { zipTree it }
manifest {
attributes 'Implementation-Title': 'myApp',
'Implementation-Version': 1.0,
'Main-Class': mainClassName
}
}
The above code will create the jar file under build/libs, and the file does not contain the compiled files, only the dependencies.
Thank you!
The build task comes from the java plugin. You can control when a jar is built with something like this:
jar {
onlyIf { condition }
}
You can set jar to be built when you declare something else to be true, or hard set it to false to never build a jar.
You can include sourcesets in your toJar custom task, to include compiled files into your jar.
task toJar (type: Jar) {
from sourceSets.all
}
You are explicitly calling for all compile time dependencies to be included in the jar here: from configurations.compile.collect
ref: Gradle java plugin
i want to build the war file and include an empty folders like "classes" and "META-INF". I have the following code:
task buildWar(type: Zip){
archiveName = 'myproject.war'
includeEmptyDirs = true
destinationDir = file("$targetDir/project")
from("$root/grab/lib"){
include "*.jar"
into "WEB-INF/lib"
}
}
I need to create "classes" and "META-INF". How i can do it inside buildWar task?
I use the following script to create a fat JAR, probably you could modify it to create WAR file:
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Project Name',
'Implementation-Version': version,
'Main-Class': 'org.foo.Bar'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
The manifest part above will generate your META-INF subfolder (where the manifest sits).
The classes folder will be auto-created by Gradle, if the project has Java files.