I have a gradle task written in Groovy
task packageFatJar(type: Jar) {
group 'build'
description 'package fat jar for migrations app with all dependencies'
baseName = 'app-fat'
zip64 = true
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
I want to change it to Groovy DSL
I have this code ready:
tasks.create<Jar>("packageFatJar") {
group = "build"
description = "package fat jar for group call common app with all dependencies"
baseName = "app-fat"
isZip64 = true
}
But, I don't know how to convert this part:
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
Can you please help me?
Related
I am creating a fat jar using gradle, build.gradle is as below:
...
dependencies {
compile files('local_path1')
compile files('local_path2')
runtime files('local_path3')
}
task customFatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'MyMainClass'
}
archiveName = 'my-jar'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Now, once I run the "customFatJar" task, the jar generated contains dependent jars in paths "local_path1" and "local_path2". But the jar generated does not contain dependent jar in path "local_path3".
Please let me know correct dependency configuration to achieve this.
As you defined the local_path3 as runtime, you would need to add them into the script, too. Currently it just collecting all the runtime libs. It may looks like:
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
You should have a look at the documentation around the configurations created by the Java plugin and how they relate to each other.
In order to not miss a single runtime dependency in your fat jar, you should rely on the runtimeClasspath configuration:
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
I'm using Gradle. Usually I'm build the FAT jar. There was no problem, but at this time, I also need to make NON-FAT jar.
I mean I want to exclude all depended library and run jar with -cp option like the following:
java -cp "/sample1/lib/myjar.jar:/sample2/lib/depended.jar" com.example.main.Runner
(In FAT jar, java -jar myjar.jar is the same thing and its contains depended.jar)
Here is my build.gradle.
apply plugin: 'java'
apply plugin: 'application'
jar.baseName = 'myjar'
version = ''
def mainClass = 'com.example.main.Runner'
mainClassName = mainClass
def defaultEncoding = 'UTF-8'
repositories {
flatDir dirs: "${projectDir}/libs"
}
dependencies {
compile ':commons-chain:1.2'
compile ':commons-io:2.4'
testCompile ':junit:4.12'
testCompile ':hamcrest-core:1.3'
}
jar {
manifest {
attributes 'Implementation-Version': version,
'Main-Class': mainClass
}
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
}
I still want to keep this for usual FAT jar creation.
So, I tried to append a task like the following:
TRY #1
task makeSlimJar {
jar.baseName = 'myjar.slim'
jar {
manifest {
// remove main class
attributes 'Implementation-Version': version
}
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
}
TRY #2
task makeSlimJar {
jar.baseName = 'myjar.slim'
jar {
manifest {
// remove main class
attributes 'Implementation-Version': version
}
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
tasks.Jar.execute()
}
TRY #3
task makeSlimJar {
jar.baseName = 'myjar.slim'
jar {
manifest {
// remove main class
attributes 'Implementation-Version': version
}
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
dependsOn Jar
}
After appended it, I ran the gradle makeSlimJar.
All of the above my tries were failed(programmatically, it were succeeded) and just created FAT jar with name myjar.slim.jar.
Is there way to live together FAT and NON-FAT jar on the same build.gradle file?
... Or am I something wrong?
I consider that removing apply plugin: 'application' for NON-FAT jar is my last resort.
Please help me, if you could.
Thanks,
the code which is actually adding the dependencies to your jar is this line:
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
your build script will normally build a 'slim jar' by default, except that you have added code to override this behaviour:
jar {
manifest {
attributes 'Implementation-Version': version,
'Main-Class': mainClass
}
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
}
I would recommend removing these lines. When you run gradle clean build this will then build a normal jar (with no dependencies).
You could then add an additional task to create your 'fatjar' like this:
task fatjar << {
jar.doFirst {
println "creating fatjar"
jar {
from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }}
}
}
}
You can use this task to build the fatjar by running gradle clean fatjar build.
Alternatively you could try looking at a framework such as springboot, which would do all this for you.
When I run this FatJar/UberJar task, I end up with a .jar file whose META-INF\ folder contains two MANIFEST.MF files. One is the correct one with the attributes I inserted into the task definition, and the other simply contains "Manifest-Version: 1.0". This causes a "Could not find or load main class" error when attempting to run the application (I assume it is solely reading the first one and can't identify a main-class)
task fatJar(type: Jar) {
baseName = project.name
manifest {
attributes 'Implementation-Title': 'Synchronizer',
'Main-Class': 'net.xxx.yyy.Main'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
MANIFEST.MF #1
Manifest-Version: 1.0
MANIFEST.MF #2:
Manifest-Version: 1.0
Implementation-Title: Synchronizer
Main-Class: net.xxx.yyy.Main
Whats the reason for the duplicate Manifest?
I've tried excluding the MANIFEST.MF using
it.isDirectory() ? it : zipTree(it).matching{exclude{it.path.contains == 'META-INF'}}
it.isDirectory() ? it : zipTree(it).matching{exclude{it.name.contains == 'MANIFEST'}}
*** These do exclude the child JAR META-INF folders and Manifest files, so I'm not sure where MANIFEST.MF #1 is coming from. It appears to be a default?
On my version of gradle, I'm not getting 2 manifests with your code - I only end up with a single manifest containing Manifest-Version: 1.0 as you described.
The problem appears to be that your manifest closure isn't actually associated with the jar closure. The Jar task type assignement and "with jar" keyword don't do this for you. Therefore, it isn't recognized as the manifest file for the jar task. You should be able to fix this through one of these options:
task fatJar(type: Jar) {
baseName = project.name
jar.manifest {
attributes 'Implementation-Title': 'Synchronizer',
'Main-Class': 'net.xxx.yyy.Main'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } with jar
}
Or, a cleaner way to write the same this would be to include the manifest and from closures in a jar closure:
task fatJar(type: Jar) {
baseName = project.name
jar{
manifest {
attributes 'Implementation-Title': 'Synchronizer',
'Main-Class': 'net.xxx.yyy.Main'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
I have a javafx project including css files. I want them directly in the main java src:
src/main/java/Foo.java
src/main/java/Foo.css
When I now use my gradle script to build a fat jar, it does not include the css files and running the jar ends up in a npe.
My gradle script looks like this:
apply plugin: 'java'
apply plugin: 'eclipse'
jar {
manifest {
attributes "Main-Class": "foo.Main"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.github.sarxos:webcam-capture:0.3.10'
}
What can I do to get a runnable jar file from gradle?
I tried already to explicitly include the css files - it did not work / I did it wrong ...
If you can't change your resource files to a resource directory, then you can use:
jar {
manifest {
attributes "Main-Class": "foo.Main"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
}
from('src/main/java') {
include '**/*.css'
}
}
I want to build an uberjar (AKA fatjar) that includes all the transitive dependencies of the project. What lines do I need to add to build.gradle?
This is what I currently have:
task uberjar(type: Jar) {
from files(sourceSets.main.output.classesDir)
manifest {
attributes 'Implementation-Title': 'Foobar',
'Implementation-Version': version,
'Built-By': System.getProperty('user.name'),
'Built-Date': new Date(),
'Built-JDK': System.getProperty('java.version'),
'Main-Class': mainClassName
}
}
I replaced the task uberjar(.. with the following:
jar {
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
manifest {
attributes 'Implementation-Title': 'Foobar',
'Implementation-Version': version,
'Built-By': System.getProperty('user.name'),
'Built-Date': new Date(),
'Built-JDK': System.getProperty('java.version'),
'Main-Class': mainClassName
}
}
The exclusions are needed because in their absence you will hit this issue.
Have you tried the fatjar example in the gradle cookbook?
What you're looking for is the shadow plugin for gradle
Simply add this to your java module's build.gradle.
mainClassName = "my.main.Class"
jar {
manifest {
attributes "Main-Class": "$mainClassName"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
This will result in [module_name]/build/libs/[module_name].jar file.
I found this project very useful. Using it as a reference, my Gradle uberjar task would be
task uberjar(type: Jar, dependsOn: [':compileJava', ':processResources']) {
from files(sourceSets.main.output.classesDir)
from configurations.runtime.asFileTree.files.collect { zipTree(it) }
manifest {
attributes 'Main-Class': 'SomeClass'
}
}