Project Layout of a Java Project
The default project layout of a Java project is following:
- The src/main/java directory contains the source code of our project.
- The src/main/resources directory contains the resources (such as properties files) of our project.
- The src/test/java directory contains the test classes.
- The src/test/resources directory contains the test resources.
All output files of our build are created under the build directory. This directory contains the following subdirectories which are relevant to this blog post (there are other subdirectories too, but we will talk about them in the future):
- The classes directory contains the compiled .class files.
- The libs directory contains the jar or war files created by the build.
Basic
plugins {
id 'java'
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
version = '1.2.1'
By applying the Java Plugin, you get a whole host of features:
A
compileJavatask that compiles all the Java source files under src/main/javaA
compileTestJavatask for source files under src/test/javaA
testtask that runs the tests from src/test/javaA
jartask that packages themaincompiled classes and resources from src/main/resources into a single JAR named <project>-<version>.jarA
javadoctask that generates Javadoc for themainclasses
Managing Dependencies
repositories {
mavenCentral()
}
dependencies {
implementation 'org.hibernate:hibernate-core:3.6.7.Final'
}
The Gradle terminology for the three elements is as follows:
Repository (ex:
mavenCentral()) — where to look for the modules you declare as dependenciesConfiguration (ex:
implementation) - a named collection of dependencies, grouped together for a specific goal such as compiling or running a module — a more flexible form of Maven scopesModule coordinate (ex:
org.hibernate:hibernate-core-3.6.7.Final) — the ID of the dependency, usually in the form '<group>:<module>:<version>' (or '<groupId>:<artifactId>:<version>' in Maven terminology)
You can find a more comprehensive glossary of dependency management terms here.
As far as configurations go, the main ones of interest are:
compileOnly— for dependencies that are necessary to compile your production code but shouldn’t be part of the runtime classpathimplementation(supersedescompile) — used for compilation and runtimeruntimeOnly(supersedesruntime) — only used at runtime, not for compilationtestCompileOnly— same ascompileOnlyexcept it’s for the teststestImplementation— test equivalent ofimplementationtestRuntimeOnly— test equivalent ofruntimeOnly
You can learn more about these and how they relate to one another in the plugin reference chapter.
Source Sets
Imagine you have a legacy project that uses an src directory for the production code and test for the test code. The conventional directory structure won’t work, so you need to tell Gradle where to find the source files. You do that via source set configuration.
Each source set defines where its source code resides, along with the resources and the output directory for the class files. You can override the convention values by using the following syntax:
sourceSets {
main {
java {
srcDirs = ['src']
}
}
test {
java {
srcDirs = ['test']
}
}
}
Samples
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.11
targetCompatibility = 1.11
repositories {
jcenter()
}
dependencies {
testCompile project(":cipher")
testCompile project(":is")
testCompile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
testCompile 'com.google.protobuf:protobuf-java:3.6.1'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile('org.testcontainers:testcontainers:1.10.5')
testCompile('org.assertj:assertj-core:3.8.0')
testCompile('io.rest-assured:rest-assured:3.0.3')
testCompile('io.rest-assured:json-schema-validator:3.0.3')
testCompile('io.rest-assured:json-path:3.0.3')
testCompile('ch.qos.logback:logback-classic:1.2.3')
testCompile('io.cucumber:cucumber-java8:4.7.1')
testCompile('io.cucumber:cucumber-junit:4.7.1')
testCompile('io.cucumber:cucumber-picocontainer:3.0.2')
testCompile('org.bouncycastle:bcprov-jdk15on:1.60')
testCompile('com.auth0:java-jwt:3.4.0')
testCompile('org.apache.commons:commons-lang3:3.7')
testCompile('org.mock-server:mockserver-client-java:5.5.1')
testCompile group: 'com.rabbitmq', name: 'amqp-client', version: '5.5.2'
testCompile group: 'org.json', name: 'json', version: '20180813'
testCompile group: 'commons-cli', name: 'commons-cli', version: '1.4'
}
task testJar(type: Jar) {
from { configurations.testCompile.collect { it.isDirectory() ? it : zipTree(it) } }
from sourceSets.test.output.classesDirs
from sourceSets.test.resources
jar
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
task copyBVTDockerfile(type: Copy) {
from 'src/main/docker'
into 'build/libs'
}
task buildBVTDockerImage(type: Exec) {
workingDir "build/libs"
commandLine "docker", "build", "--build-arg", "VERSION=${project.version}", "--tag", "${rootProject.name}/${project.name}:${project.version}", "./"
}
testJar.dependsOn(testClasses)
buildBVTDockerImage.dependsOn(copyBVTDockerfile,testJar)
build.dependsOn(buildBVTDockerImage)
References
| Reference | URL |
|---|---|
| Building Java & JVM projects | https://docs.gradle.org/current/userguide/building_java_projects.html |