Cheats or Frequently used

Gradle Command Description
gradle projects List Gradle projects
gradle tasks –all List all of the tasks that can be run
gradle dependencies Like mvn depeendency:tree
gradle clean build Like mvn clean install
gradle helmInstall Build docker image and deploy it to K8S (custom task)
gradle publishToMavenLocal Copy artifacts (jar) to maven .m2/repository directory

How multi-projects basics

Every gradle project (or subproject) has a build.gradle file. They can optionally have a gradle.properties file. See https://docs.gradle.org/current/userguide/multi_project_builds.html for the Gradle documentation on a Multi-Project Layout.

Gradle calls the arguments tasks. Some built in tasks are: help, projects, tasks, properties. Other tasks are defined in the build.gradle file or via gradle plugins that are included.

In this example, there are three directories the root directory and two sub-projects.

Root Project
  - settings.gradle
  - build.gradle
  - gradle.properties
  + subProject1
    - build.gradle
  + subProject2
    - build.gradle

The settings.gradle file defines the project name and sub-projects.

rootProject.name = "Pats sample Gradle multi-directory layout"
project.group = "com.steranka.play"
version = "0.0.1"

include 'subProject1'
include 'subProject2'

When gradle clean is run, it runs in the Root and in the two subProjects. Gradle executes clean on the root and every subproject, because clean is a task that exists in every project and follows Gradle’s task execution model The clean task is a lifecycle task defined in the base plugin, which is applied automatically in Java projects.

On the other hand, gradle dependencies only runs on the Root directory. This is because the dependencies task is not a global task—it belongs to each project separately.

Testing

How can I run a single test in Gradle (from command line)?

# Specific Test File (all tests in this file are run)
gradle subproject:test --tests com.example.play.MySampleTest

# Specific Test doItTest() File (only this exact test is run)
gradle subproject:test --tests com.example.play.MySampleTest#doItTest

# Run all Tests whos filename matches 'Base*Test'
gradle subproject:test --tests "Base*Test"

How can I skip over tests

By appending -x test you can skip over tests.

gradle build -x test

Where is log file output

./gradlew test --info
./gradlew test --debug

Will show you the output that you normally don’t see

ls -l subproject/build/test-results/test
less subproject/build/test-results/test/TEST-com.example.play.MySampleTest.xml
  <system.out><![CDATA[
... this is where you'll see the log output
]]></system-out>
  <system-err><![CDATA[]]><system-err>

The XML file contains the log output including a stack trace if one exists. It also has the success/failure of the test.

Tip: If you just want everything (logs, test outputs) nicely in console while developing, add this once to your build.gradle:

test {
    testLogging {
        events "passed", "skipped", "failed", "standard_out", "standard_error"
        showStandardStreams = true
    }
}

How do I setup publishToMavenLocal? How does it work?

KWS: gradle equivalent to mvn install

Add the following to your build.gradle file

plugins {
    id 'maven-publish'
}

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
            // This uses artifactId, groupId, version to be set 

            // Add additional artifacts if needed
            artifact sourcesJar
            artifact javadocJar
            
            // Add POM customizations if needed
            pom {
                name = 'Your Project Name'
                description = 'Description of artifact being published'
            }
        }
    }
    repositories {
        mavenLocal()
    }
}

After this is installed, you can use it

./gradlew publishToMavenLocal
./gradlew publishMyLibraryPublicationToMavenLocal

The plugin creates publish<PublicationName>PublicationTo<RepositoryName> so that is why the 2nd version of the command is shown

If you don’t override anything inside the MavenPublication, the maven-plugin uses the project-level values. Gradle will:

  • Use project.group as the groupId
  • Use project.name as the artifactId
  • Use project.version as the version

NOTE: One way to set the groupId (aka project.group) is using a gradle.properties file such as

publishRepository = release
javaVersion = 17
groupId = com.steranka.play
// group = 

Downloading artifacts - checking versions of artifacts

(Q) How can force an aritfact to be downloaded?

The easiest way is to run

./gradlew build --refresh-dependencies

(Q) Where does gradle keep it’s cache?

du -sh ~/.gradle/caches

This directory includes

  • All downloaded dependencies
  • Gradle wrapper files
  • Task history, etc.

The downloaded dependencies are stored under the modules-2 directory the command equivalent to the maven command which deletes all downloaded dependencies is shown below.

# Maven
rm -rf ~/.m2/repository
# Gradle
rm -rf ~/.gradle/caches/modules-2

The downloaded JAR files are stored under the directory

~/.gradle/caches/modules-2/files-2.1

So to find the versions of guava downloaded you can use

(Q) How can I grep for the version of an artifact in my gradle cache?

Problem: I just ran a build and it failed because it isn’t using the latest SNAPSHOT version that was built and published to NEXUS, how can I fix this?

To manually grep for it, you can use:

find ~/.gradle/caches/modules-2/files-2.1 -name '*guava*.jar'
~/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/32.1.2-jre/<hash>/guava-32.1.2-jre.jar

(Q) What gradle command exists to show me the version of an artifact in the cache?

To see what version is stored in the cache you can use the dependencyInsight command

./gradlew dependencyInsight --dependency <artifact-name> --configuration <conf>
./gradlew :subproject:dependencyInsight --dependency guava --configuration runtimeClasspath
com.google.guava:guava:32.1.2-jre (selected)
   variant "runtime" [
       org.gradle.status = release
   ]

NOTE: In this example, I used the string :subproject: because often you’ll be working with gradle builds that have multiple directories, and running the dependencyInsight command at the root directory produces an error like:

Configuration 'runtimeClasspath' not found in configuration container.

NOTE: The --dependency argument matches any artifact with that name. For example, com.google.guava:guava:32.1.2-jre or org.wso2.orbit.com.google.guava:guava:27.0.0.wso2v1

Below is a custom task for build.gradle that prints the versions used for each artifact used

cat <<EOF >> build.gradle

task showVersions {
    doLast {
        configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.each {
            println "Dependency: ${it.moduleVersion.id}"
        }
    }
}
EOF

# To use it run the command
./gradlew showVersions

Another way is to setup a command to be used in any gradle project. This is done by adding a command to your ~/.gradle/init.gradle file.

allprojects {
    afterEvaluate {
        tasks.register("showVersions") {
            doLast {
                def confNames = configurations.findAll { it.canBeResolved }*.name
                println "Resolved dependencies (by configuration):"
                confNames.each { confName ->
                    println "\nConfiguration: $confName"
                    try {
                        configurations[confName].resolvedConfiguration.resolvedArtifacts.each {
                            println "  -> ${it.moduleVersion.id}"
                        }
                    } catch (Exception e) {
                        println "  (Could not resolve: $e.message)"
                    }
                }
            }
        }
    }
}

After that you can run ./gradlew show-versions in any gradle project.

Misc

How can I run a command in build.gradle?

task buildDockerImage(type:Exec, dependsOn: docker) {
    commandLine "docker"
    args = ["build"]
}

task pushDockerImage(type:Exec, dependsOn: docker) {
    commandLine "docker"
    args = ["push", "harbor.example.com/myproj/myapp:latest"]
}

How can I define a task to be used in any directory?

The file $HOME/.gradle/init.gradle is processed on every gradle command. By defining a task in this file, you can use the task anywhere in any gradle project.

allprojects {
    task.register('hello-world'){
        println "Hello from directory ${project.projectDir}"
    }
    
    task.register('list-configurations'){
        configurations
            // .findAll { it.canBeResolved || it.canBeConsumed }
             .findAll { it.canBeResolved }
             .each { println "$it.name} - ${it.description? 'No description'}" } 
    }
    
//     repositories {
//         mavenLocal()
//         maven { url "https://nexus.example.com/repository/public" }
//     }
//     
//     gradle.beforeProject {
//         System.setProperty("com.redhat.fips", "false")
//  __   }
}

<
Previous Post
When copy/paste has invisible characters, how do I get rid of them?
>
Next Post
How can I find files updated in last 5 minutes