Execute the clean
and build
taks of the Java plugin. "build" is calling the compileJava
task. The IDE plugin show the all lifecycle and the elapsing time of each task.
The task jar
, of the Java plugin, actually build a JAR file that contains our application. The JAR file itself lives in the build/libs
directory and its part of the Gradle standard. The Java files contained in the JAR are inspectable.
As well the tests are created by the Gradle Java tasks in the build/reports/tests/test
directory.
Gradle is very fast on some task's calls because is an Incremental Build System that means it checks that the task has been already executed before actually execute it. So it creates a cache by checking the inputs and the ouputs of a task.
In the compile task: if the source code hasn't changed and the output hasn't been deleted, then Gradle considers the task up-to-date and do not execute it. This allow to save a lot of build time, especially in large projects.
The clean
task deletes the out directory, so the build will be much longer beceause all the tasks will be re-executed.
Gradle takes care of documentation trough the task javadoc
. So we can run that task that generates the folder docs in the output on which documentation in the HTML format is produced.
Compared to a POM file the build.gradle file is much more lighter.
The objective is to build up a standalone executable such that by executing
java -jar gradlejava1-complete-all-0.0.1-SNAPSHOT.jar
we can run our application by using just one line, because all the dependencies are included.
The JAR will contain the application AND the dependencies. The MANIFEST file is different as well: it can contains the main class that has to be executed.
Gradle provides an out-of-the-box solution for this. See the Jar task documentation.
By changing the property baseName
we will change the name of the Jar file. To manipulate the Manifest: manifest(configureClosure)
.
So we need to edit the jar
task itself in the build.gradle:
jar {
baseName = "$project.name-all"
println ">>>> basename: $baseName"
}
and editing the Manifest using the map attribute attributes
:
project.version = '0.0.1-SNAPSHOT'
project.group = 'com.package'
jar {
baseName = "$project.name-all"
manifest {
attributes 'Implementation-Title': 'Gradle all inclusive jar',
'Implementation-Version': project.version,
'Created-By': 'michele.salvucci',
'Main-Class': 'com.package.random.App'
}
println ">>>> basename: $baseName"
println ">>>> manifest.attributes: $manifest.attributes"
}
One method of the jar task is called from
that takes a source file. So we can copy file in the Jar file.
The project contains a configuration container and that container contains all the information we need, in particular the dependencies we need (ConfigurationContainer
). The example in the documentation page of the ConfigurationContainer shows how to copy all dependencies attached to compile into a particular folder.
apply plugin: 'java'
task copyAllDependencies(type: Copy) {
from configurations.compile
into 'allLibs'
}
We can use configuration.compile to return us all the dependency files.
project.configurations.compile
By running the dependencies
task within the help
task it outputs to the console all the dependencies the project has. For some dependencies we need to use runtimeClasspath
instead of implementation
or compile
. So
project.configurations.runtimeClasspath
that is iterable through the method collect
:
project.configurations.runtimeClasspath.collect {File file -> project.zipTree(file)}
We unzip the dependency (sing zipTree()
) file and include that into our own Jar file.
jar {
baseName = "$project.name-all"
manifest {
attributes 'Implementation-Title': 'Gradle all inclusive jar',
'Implementation-Version': project.version,
'Created-By': 'michele.salvucci',
'Main-Class': 'com.package.random.App'
}
from {
project.configurations.runtimeClasspath.collect {File file -> project.zipTree(file)}
}
}
By running the jar
task we can test it and see if works.
java -jar gradlejava1-initial-all-0.0.1-SNAPSHOT.jar
Gradle dependencies are grouped into sets called configurations. Different configurations are used for building classpath for the major two tasks — compile classpath is used for compilation and runtime classpath is used for running the application.
We use implementation configuration in Gradle to hide the internals of our project. Typically, if some classes from a library are only used within the method body then we can use implementation configuration. They are required to compile the project but they are not exposed for the compilation to the depending projects.
Runtime: the dependencies that are only used in runtime when serving the application to either run it or to enhance it.