gradle to bundle nested jar dependencies into module output jar - gradle

How to make gradle to included some dependencies into module resulted jar as jar? i.e. to make jar with nested jar's e.g. in lib folder ?
This is not Android project, and this should be done for many modules in multi-module project, so fatJar, uberJar, shadowJar alike solutions seem not to fit.

You just need to add an additional from directive to include dependencies in your jar:
task jarJar(type: Jar) {
baseName = project.name + '-jarjar'
from { configurations.compile }
with jar
}

Related

War task of Gradle build adding extra jars than those from dependencies in build.gradle

We have recently migrated to Gradle build and I have added a war that task that has web.xml and dependent jars along with jar created in the jar task.
task testWar(type: War)
{
archiveName 'test.war'
webXml = file('WebContent/WEB-INF/web.xml')
into ('WEB-INF/lib')
{
from configurations.compile
from jar
}
}
This creates the war but the size of WEB-INF/lib is double the size of the libs actually given in dependencies. It might be adding the jars that the dependent jars depend on. But Ant build just works fine with just the dependent jars.
Is there any way to create war with just the jars provided in dependencies?
Note: https://docs.gradle.org/current/userguide/war_plugin.html didnt help as I need all the jars in dependencies, just want to avoid extra dependent jars
You can use gradle dependencies to know which libraries are causing the inclusion of these additional dependencies.
Once you have that then simply exclude the dependency you want to remove from your package.
dependencies {
compile (group: 'org.quartz-scheduler', name: 'quartz', version: '2.3.0') {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
}

How to build a jar from a multi-module project when using Gradle?

I'm working on a multi-module library project which I build with Gradle. I have a dependency to another module of this project in my dependencies section:
dependencies {
compile project(':my-other-module')
}
My problem is that I want to build a .jar file which only contains the local modules in the final file, not its transitive dependencies. I tried this:
jar {
from project(':my-other-module').configurations.compile.collect { zipTree it }
}
but this added all the transitive dependencies as well. I want to create a .jar which only contains my own files, so the users of this library can have their own versions of transitive dependencies. How can I do so?
Further clarification:
I have dependencies declared in my project to external jars like apache-commons. I want these not to be in my resulting .jar file but I want the users of my library to be able to just add my library as a dependency and let Maven/Gradle download the transitive dependencies. I don't want these transitive dependencies to be in the .jar file I deploy to Maven Central. compileOnly is not an option since the dependencies I use like apache-commons are not provided by a framework or a container. They need to be present as compile dependencies. I just want to build and deploy a .jar file which has all the files in my project which has multiple modules.
I am not sure it'll help you or not but, you can try this.
In your build.gradle file, customize your jar task as follows:
// This closure will return the full directory path of folder where your classes are built
ext.moduleClassPath = { moduleName ->
def classOutputDirConst = "/classes/java/main"
return "${project(":${moduleName}").buildDir}${classOutputDirConst}"
}
// Now jar task will include only the built file of specified project
jar {
from(moduleClassPath("projectName1"), moduleClassPath("projectName2"))
}
Check the reference for the from(SourcePaths) method here: Reference: https://docs.gradle.org/current/dsl/org.gradle.jvm.tasks.Jar.html#org.gradle.jvm.tasks.Jar:from(java.lang.Object[])
Gradle has a compile-only dependency concept, similar to Maven's provided scope:
Compile-only dependencies are distinctly different than regular compile dependencies. They are not included on the runtime classpath and they are non-transitive, meaning they are not included in dependent projects.
The dependencies you don't want can be declared in the compileOnly configuration, rather than compile, eg:
dependencies {
compileOnly 'javax.servlet:servlet-api:2.5'
}
compileOnly is not even visible to unit tests, by default. We change this in a common gradle snippet which we include in each build:
// compileOnly isn't visible to tests by default, add it
plugins.withType(JavaPlugin).whenPluginAdded {
sourceSets {
test.compileClasspath += configurations.compileOnly
test.runtimeClasspath += configurations.compileOnly
}
}
For the second part, for which I believe you want to create a single "fat" jar,
I would suggest creating your jar using the very good Shadow Plugin, rather than manually extending the jar task. By default, the shadow plugin will not include anything in the compileOnly configuration in the resulting jar.

gradle war: how to build jar, not classes

Gradle war plugin: how to build a jar and add it to war?
projectRoot/
src/main/java
src/main/resources
src/main/webapp
build a jar (foo.jar) from the java source code and resources.
add the jar under the WEB-INF/lib of the war.
WEB-INF/lib/foo.jar
The war task will not build a jar by default, and add all java classes and resources under WEB-INF/classes.
UPDATE
The War plugin extends the Java plugin to add support for assembling web
application WAR files. It disables the default JAR archive generation of the
Java plugin and adds a default WAR archive task.
There is a way to enable the Jar generation and let task war depends on task jar?
not sure if eastwater still needs the answer, hope others with the same problem will find this helpful
you can add/configure the war task in build.gradle
war {
classpath = classpath - sourceSets.main.output
from (jar) {
into 'WEB-INF/lib'
}
}
once build succeed, in build/libs folder you'll see the generated jar and the war containing the generated jar instead of classes
Add those into your root build.gradle
plugins {
id 'java'
id 'idea'
}
jar{
String somestr=''
configurations.runtime.each{somestr=somestr+" lib\\"+it.name}
manifest{
attributes 'Main-Class':'your_class_name'
attributes 'Class-Path':somestr
}
}
task copyJar(type:Copy){
from configurations.runtime
into ('build/libs/lib')
}
task release(type: Copy,dependsOn:[build,copyJar]){
}
add finally run this command
gradle release

Why does my jar file not not contain any class files?

I'm trying to add a task (gen or gen2) to my build.gradle that does exactly the same as the Jar-task:
version = "0.0.1"
apply plugin: 'java'
task('gen', type: Jar) {
}
task gen2(type: Jar)
Running
gradle jar
generates a JAR-file that contains .class-files, while running
gradle gen
or
gradle gen2
generate a JAR-file that does NOT contain any .class-files.
Whats wrong with my class definition?
To build a jar with all the classes from main, as a default jar task would, do this:
task gen2(type: Jar){
baseName = 'gen2Jar'
from sourceSets.main.output
}
You can also do from(sourceSets.main.output){ include "package" } to customize what packages are included.
Alternatively, to copy settings from the default jar task:
task gen(type: Jar){
baseName = 'genJar'
with jar
}
Infact you can have both of these in the same build.gradle. Running gradle jar builds default jar. gradle gen builds genJar.jar and gradle gen2 builds gen2Jar.jar, all of which contain all the classes from java.main

How to include the guava libraries to my output jar?

I have the following dependencies in my build.gradle:
dependencies {
compile 'com.google.guava:guava:18.0'
}
It works during compile time and the output jar is generated for my source code (which uses classes like com.google.common.collect.Maps from the guava libraries).
I have a dex task which converts the output jar into a dex file:
task dex(dependsOn: jar, type:Exec) {
project.dexDir.mkdirs()
commandLine 'dx', '--dex', '--no-strict', '--output=' + buildDir +'/dex/' + project.name + '.jar', jar.archivePath
}
The problem is that the output jar doesn't have the guava dependencies, so when it's converted to dex, pushed to an android device and run there, I am getting java.lang.ClassNotFoundException: Didn't find class com.google.common.collect.Maps
Is there a way to get the guava dependencies to be included in the output jar for the javaCompile task that generates the output jar from my other source code? Thank you very much in advance!
This is usually called a "jar with dependencies" or sometimes, a "fat" jar. This solution is probably what you need:

Resources