Java Gradle
O Gradle faz o mesmo trabalho que o Maven: baixa as bibliotecas, compila, roda os testes e empacota. A diferença está na receita: em vez de um XML, você escreve um pequeno programa em Kotlin, o build.gradle.kts. É a ferramenta padrão dos aplicativos Android e muito usada em projetos Java novos.
- Criar um projeto com
gradle init, sem perguntas. - O que é cada arquivo gerado, e o
build.gradle.ktslinha por linha. - O que é o wrapper (
./gradlew) e por que usá-lo. ./gradlew build,runetest, com as saídas reais (e uma falha).- Adicionar uma dependência e o que acontece quando ela não existe.
- O que é o daemon do Gradle.
- Quando escolher Maven ou Gradle.
Esta aula supõe que você já leu a de Maven: as ideias de dependência, repositório e estrutura src/main/java são as mesmas. Os exemplos rodam na máquina fictícia da Ana, com Gradle 9.8.1 e JDK 25.
A ideia: a mesma cozinha, outra receita
Se o Maven é uma cozinha padronizada com uma receita em formulário (você preenche os campos do pom.xml), o Gradle é a mesma cozinha, mas a receita é escrita como um roteiro: dá para pôr "se", "repita", criar tarefas novas. Para projetos simples, as duas receitas têm quase o mesmo tamanho. Para projetos enormes e cheios de particularidades, o roteiro do Gradle é mais flexível.
O Gradle trabalha com tarefas (tasks): compileJava, test, jar, build… Cada tarefa depende de outras, e o Gradle roda só as que precisam (se nada mudou, ele pula).
1. Conferir a instalação
No laboratório, o Gradle já está em /opt/gradle (para instalar no seu computador, baixe o zip de gradle.org e ponha a pasta bin no PATH; ou use o SDKMAN!). Na primeira vez, ele dá boas-vindas:
$ gradle --version Welcome to Gradle 9.8.1! Here are the highlights of this release: - Java 27 support - Maven mirror settings reuse - Linked problem locations in build output For more details see https://docs.gradle.org/9.8.1/release-notes.html ------------------------------------------------------------ Gradle 9.8.1 ------------------------------------------------------------ Build time: 2026-10-07 16:57:46 UTC Revision: 39daf39feb60a18b1b6ddccde53366522fef516f Kotlin: 2.4.10 Groovy: 4.0.33 Ant: Apache Ant(TM) version 1.10.17 compiled on April 6 2026 Launcher JVM: 25.0.4.1 (Eclipse Adoptium 25.0.4.1+1-LTS) Daemon JVM: /opt/jdk-25 (no Daemon JVM specified, using current Java home) OS: Linux 7.0.0-38-generic amd64
O Gradle é escrito em Java e roda numa JVM (Launcher JVM: 25.0.4.1). As linhas Kotlin e Groovy são as duas linguagens em que se escreve a receita: Kotlin (arquivos .gradle.kts, o padrão atual) ou Groovy (arquivos .gradle, comuns em projetos mais antigos).
2. Criar o projeto: gradle init
Sem opções, o gradle init faz uma série de perguntas (tipo de projeto, linguagem, pacote…). Dando todas as respostas na linha de comando, ele não pergunta nada:
$ mkdir mercado && cd mercado $ gradle init --type java-application --dsl kotlin --test-framework junit-jupiter --package br.com.ana.mercado --project-name mercado --java-version 25 --no-split-project --no-incubating Starting a Gradle Daemon, 1 stopped Daemon could not be reused, use --status for details > Task :init Learn more about Gradle by exploring our Samples at https://docs.gradle.org/9.8.1/samples/sample_building_java_applications.html BUILD SUCCESSFUL in 6s 1 actionable task: 1 executed
- --type java-application
- Um programa Java com
main(a outra opção comum éjava-library, uma biblioteca). - --dsl kotlin
- A receita em Kotlin (
build.gradle.kts). DSL = domain-specific language, "linguagem para um assunto específico". - --test-framework junit-jupiter
- Testes com o JUnit (veja Testes com JUnit).
- --package br.com.ana.mercado
- O pacote das classes.
- --project-name mercado
- O nome do projeto.
- --java-version 25
- A versão do Java.
- --no-split-project
- Um projeto só (e não vários subprojetos).
- --no-incubating
- Não usar recursos ainda experimentais do Gradle.
Se faltar alguma opção, você pode pôr --use-defaults para ele escolher o padrão em vez de perguntar.
O que foi criado
$ find . -type f | sort ./app/build.gradle.kts ./app/src/main/java/br/com/ana/mercado/App.java ./app/src/test/java/br/com/ana/mercado/AppTest.java ./.gitattributes ./.gitignore ./gradle/libs.versions.toml ./gradle.properties ./gradlew ./gradlew.bat ./gradle/wrapper/gradle-wrapper.jar ./gradle/wrapper/gradle-wrapper.properties ./settings.gradle.kts
| Arquivo | Para que serve |
|---|---|
settings.gradle.kts | O "índice" do projeto: nome e quais subprojetos existem (aqui, um: app) |
app/build.gradle.kts | A receita do subprojeto app: plugins, dependências, versão do Java, classe principal |
app/src/main/java/…, app/src/test/java/… | Código e testes, na mesma estrutura do Maven |
gradle/libs.versions.toml | O catálogo de versões: um lugar só para as versões das bibliotecas |
gradle.properties | Opções do Gradle (aqui, liga o configuration cache, que deixa os builds seguintes mais rápidos) |
gradlew, gradlew.bat, gradle/wrapper/* | O wrapper (seção 4) |
.gitignore, .gitattributes | Configuração para o Git (ignorar a pasta build, por exemplo) |
Repare na diferença do Maven: o código fica dentro de app/. O Gradle já cria o projeto preparado para ter várias partes (um app, uma biblioteca…), cada uma com o seu build.gradle.kts.
3. A receita: build.gradle.kts
O arquivo gerado tem comentários em inglês explicando cada bloco. Sem os comentários, e depois de duas mudanças da Ana (ela tirou a biblioteca de exemplo Guava, que o modelo inclui, e acrescentou a Gson, que você vai ver adiante), ficou assim:
plugins {
application
}
repositories {
mavenCentral()
}
dependencies {
testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation("com.google.code.gson:gson:2.13.1")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(25)
}
}
application {
mainClass = "br.com.ana.mercado.App"
}
tasks.named<Test>("test") {
useJUnitPlatform()
}
| Trecho | O que faz |
|---|---|
plugins { application } | Liga o plugin application: compilar Java, criar o JAR e, além disso, a tarefa run e scripts para executar o programa. |
repositories { mavenCentral() } | Onde buscar bibliotecas: no mesmo Maven Central que o Maven usa. |
dependencies { … } | As bibliotecas. A palavra antes dos parênteses diz para que serve cada uma: |
implementation("grupo:nome:versão") | Usada pelo programa (como a dependência sem scope do Maven). As coordenadas vão numa linha só, separadas por :. |
testImplementation(libs.junit.jupiter) | Usada só nos testes (como <scope>test</scope>). libs.junit.jupiter aponta para o catálogo libs.versions.toml, que diz org.junit.jupiter:junit-jupiter, versão 6.0.1. |
testRuntimeOnly(…) | Necessária só para rodar os testes (o "lançador" do JUnit). |
java { toolchain { languageVersion = … 25 } } | Compilar e rodar com um JDK 25. O Gradle procura um JDK 25 instalado (e, se não achar, pode baixar um, graças ao plugin foojay-resolver declarado no settings.gradle.kts). |
application { mainClass = "…" } | A classe principal, para o ./gradlew run. |
tasks.named<Test>("test") { useJUnitPlatform() } | Configura a tarefa test para usar o JUnit 5/6 (a "plataforma JUnit"). |
Compare com o pom.xml: a dependência da Gson, que no Maven ocupa 5 linhas de XML, aqui é uma linha. Como o arquivo é código Kotlin, o editor (como o IntelliJ) completa e confere enquanto você digita.
A classe gerada, App.java, tem um método que devolve a saudação, e um teste para ele. A Ana trocou o texto para português:
package br.com.ana.mercado;
public class App {
public String getGreeting() {
return "Bem-vinda ao mercado da Ana!";
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}
Missão: o teste do projeto confere se getGreeting() devolve exatamente Bem-vinda ao mercado da Ana!. O main abaixo imita esse teste e mostra PASSED ou FAILED. O método está com um erro de digitação: conserte-o (sem mexer no main) até aparecer PASSED.
public class Main {
public String getGreeting() {
return "Bem-vindo ao mercado da Ana!";
}
public static void main(String[] args) {
String esperado = "Bem-vinda ao mercado da Ana!";
String obtido = new Main().getGreeting();
if (esperado.equals(obtido)) {
System.out.println("PASSED");
} else {
System.out.println("FAILED: expected: <" + esperado + "> but was: <" + obtido + ">");
}
}
}
public class Main {
public String getGreeting() {
return "Bem-vinda ao mercado da Ana!";
}
public static void main(String[] args) {
String esperado = "Bem-vinda ao mercado da Ana!";
String obtido = new Main().getGreeting();
if (esperado.equals(obtido)) {
System.out.println("PASSED");
} else {
System.out.println("FAILED: expected: <" + esperado + "> but was: <" + obtido + ">");
}
}
}
4. O wrapper: ./gradlew
O gradle init criou um script chamado gradlew (Gradle wrapper, "embrulho do Gradle"). Ele é um pequeno programa que baixa a versão certa do Gradle para este projeto e a usa. A versão está anotada em gradle/wrapper/gradle-wrapper.properties:
$ cat gradle/wrapper/gradle-wrapper.properties distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists
A linha que importa é distributionUrl: "este projeto usa o Gradle 9.8.1, baixado deste endereço". Por que isso é bom? Porque o Gradle muda bastante entre versões. Com o wrapper, quem baixar o seu projeto (um colega, o servidor que gera as versões) roda ./gradlew build e usa exatamente o mesmo Gradle, mesmo sem ter nenhum Gradle instalado. Por isso a regra é: use sempre ./gradlew num projeto que tem wrapper, e guarde os arquivos do wrapper junto com o código (no Git).
Num terminal de verdade, o Gradle mostra uma barra de progresso animada enquanto trabalha e, no fim, deixa na tela só o resultado (BUILD SUCCESSFUL in 8s e mais duas linhas). Para ver a lista das tarefas que rodaram, como nesta aula, acrescente --console=plain ("console simples") ao comando.
O primeiro ./gradlew build
$ ./gradlew build --console=plain Fetching distribution. Downloading https://services.gradle.org/distributions/gradle-9.8.1-bin.zip ..............10%..............20%...............30%..............40%...............50%..............60%...............70%..............80%...............90%..............100% Starting a Gradle Daemon, 2 stopped Daemons could not be reused, use --status for details Calculating task graph as no cached configuration is available for tasks: build > Task :app:processTestResources NO-SOURCE > Task :app:processResources NO-SOURCE > Task :app:compileJava > Task :app:classes > Task :app:jar > Task :app:compileTestJava > Task :app:testClasses > Task :app:startScripts > Task :app:distZip > Task :app:distTar > Task :app:assemble > Task :app:test > Task :app:check > Task :app:build BUILD SUCCESSFUL in 1m 54s 7 actionable tasks: 7 executed Configuration cache entry stored.
- Downloading … gradle-9.8.1-bin.zip
- Só na primeira vez: o wrapper baixou o Gradle inteiro (ele fica em
~/.gradle/wrapper, 165 MB). - Starting a Gradle Daemon
- O Gradle começou um daemon (veja abaixo).
- > Task :app:compileJava
- Cada linha é uma tarefa do subprojeto
app.NO-SOURCE= não havia arquivos para ela (não existesrc/main/resources). - :app:jar
- Criou o JAR.
- :app:distZip, :app:distTar
- Criaram um
.zipe um.tarprontos para distribuir o programa (com scripts e bibliotecas). - :app:test, :app:check
- Rodaram os testes.
- BUILD SUCCESSFUL in 1m 54s
- Deu certo. Lento por causa dos downloads.
- 7 actionable tasks: 7 executed
- Sete tarefas tinham trabalho a fazer, e todas foram executadas.
Rodando de novo, sem mudar nada:
$ ./gradlew build --console=plain Reusing configuration cache. > Task :app:processResources NO-SOURCE > Task :app:processTestResources NO-SOURCE > Task :app:compileJava UP-TO-DATE > Task :app:classes UP-TO-DATE > Task :app:jar UP-TO-DATE > Task :app:compileTestJava UP-TO-DATE > Task :app:testClasses UP-TO-DATE > Task :app:startScripts UP-TO-DATE > Task :app:distTar UP-TO-DATE > Task :app:distZip UP-TO-DATE > Task :app:assemble UP-TO-DATE > Task :app:test UP-TO-DATE > Task :app:check UP-TO-DATE > Task :app:build UP-TO-DATE BUILD SUCCESSFUL in 1s 7 actionable tasks: 7 up-to-date Configuration cache entry reused.
UP-TO-DATE = "já está em dia": nada mudou desde a última vez, então o Gradle não refez nada. Um segundo, em vez de dois minutos. Essa é uma das forças do Gradle: ele lembra o que já fez, até os testes.
A pasta build/
No Gradle, o que é gerado vai para app/build (no Maven era target):
$ ls app/build/libs app/build/distributions app/build/distributions: app.tar app.zip app/build/libs: app.jar
Para apagar tudo o que foi gerado: ./gradlew clean.
O daemon
Iniciar uma JVM e carregar o Gradle leva vários segundos. Para não pagar isso a cada comando, o Gradle deixa um processo rodando em segundo plano, o daemon (palavra antiga da informática para "processo que trabalha nos bastidores"). Os comandos seguintes conversam com ele e ficam bem mais rápidos. Ele se desliga sozinho depois de um tempo parado, ou com:
$ ./gradlew --stop Stopping Daemon(s) 1 Daemon stopped
A mensagem Starting a Gradle Daemon, 2 stopped Daemons could not be reused só quer dizer que havia daemons parados (a Ana parou o daemon depois de cada exemplo) e um novo foi iniciado. O daemon ocupa memória; num computador modesto, vale parar quando terminar de trabalhar.
5. Rodar: ./gradlew run
$ ./gradlew run --console=plain Calculating task graph as no cached configuration is available for tasks: run > Task :app:processResources NO-SOURCE > Task :app:compileJava UP-TO-DATE > Task :app:classes UP-TO-DATE > Task :app:run Hello World! BUILD SUCCESSFUL in 18s 2 actionable tasks: 1 executed, 1 up-to-date Configuration cache entry stored.
A saída do seu programa aparece logo depois de > Task :app:run (este foi o run antes de a Ana traduzir a saudação). Para passar argumentos ao main: ./gradlew run --args="Ana 29".
6. Testar: ./gradlew test
O teste gerado foi adaptado pela Ana para conferir a saudação:
package br.com.ana.mercado;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AppTest {
@Test void saudacaoDoMercado() {
App app = new App();
assertEquals("Bem-vinda ao mercado da Ana!", app.getGreeting());
}
}
O que cada parte faz (@Test, assertEquals) é o assunto de Testes com JUnit; aqui interessa como o Gradle mostra o resultado. A Ana tinha digitado Bem-vindo (com o) no App.java:
$ ./gradlew test --console=plain
Reusing configuration cache.
> Task :app:processTestResources NO-SOURCE
> Task :app:processResources NO-SOURCE
> Task :app:compileJava
> Task :app:classes
> Task :app:compileTestJava
> Task :app:testClasses
> Task :app:test FAILED
AppTest > saudacaoDoMercado() FAILED
org.opentest4j.AssertionFailedError at AppTest.java:9
1 test completed, 1 failed
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:test'.
> There were failing tests. See the report at: file:///home/ana/mercado/app/build/reports/tests/test/index.html
* Try:
> Run with --scan to get full insights from a Build Scan (powered by Develocity).
BUILD FAILED in 8s
3 actionable tasks: 3 executed
Configuration cache entry reused.
O Gradle diz qual teste falhou (saudacaoDoMercado()) e em que linha (AppTest.java:9), mas não por quê. O detalhe está no relatório em HTML (abra o index.html no navegador). Para ver o motivo direto no terminal, a Ana acrescentou um bloco testLogging à tarefa test:
tasks.named<Test>("test") {
useJUnitPlatform()
testLogging {
events("passed", "failed")
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}
- events("passed", "failed")
- Mostrar uma linha para cada teste que passou ou falhou.
- exceptionFormat = … FULL
- Mostrar a mensagem completa do erro, com o stack trace.
$ ./gradlew test --console=plain
…
> Task :app:test FAILED
AppTest > saudacaoDoMercado() FAILED
org.opentest4j.AssertionFailedError: expected: <Bem-vinda ao mercado da Ana!> but was: <Bem-vindo ao mercado da Ana!>
at app//org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:158)
at app//org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:139)
at app//org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:201)
at app//org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:184)
at app//org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:179)
at app//org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1188)
at app//br.com.ana.mercado.AppTest.saudacaoDoMercado(AppTest.java:9)
1 test completed, 1 failed
…
BUILD FAILED in 19s
Agora está claro: esperava (expected) Bem-vinda, recebeu (but was) Bem-vindo. Depois de corrigir o App.java:
$ ./gradlew test --console=plain Reusing configuration cache. > Task :app:processResources NO-SOURCE > Task :app:processTestResources NO-SOURCE > Task :app:compileJava > Task :app:classes > Task :app:compileTestJava UP-TO-DATE > Task :app:testClasses UP-TO-DATE > Task :app:test AppTest > saudacaoDoMercado() PASSED BUILD SUCCESSFUL in 2s 3 actionable tasks: 2 executed, 1 up-to-date Configuration cache entry reused.
7. Uma dependência: a Gson
Como na aula de Maven, a Ana quer mostrar a lista de compras em JSON com a Gson. Ela mudou o main:
package br.com.ana.mercado;
import com.google.gson.Gson;
import java.util.List;
public class App {
record Item(String nome, double preco) {}
public String getGreeting() {
return "Bem-vinda ao mercado da Ana!";
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
List<Item> itens = List.of(new Item("arroz", 25.9), new Item("feijão", 8.75));
System.out.println(new Gson().toJson(itens));
}
}
Sem a linha implementation("com.google.code.gson:gson:2.13.1") no build.gradle.kts, a compilação falha com a mensagem do javac:
$ ./gradlew run --console=plain
…
> Task :app:compileJava FAILED
/home/ana/mercado/app/src/main/java/br/com/ana/mercado/App.java:3: error: package com.google.gson does not exist
import com.google.gson.Gson;
^
/home/ana/mercado/app/src/main/java/br/com/ana/mercado/App.java:16: error: cannot find symbol
System.out.println(new Gson().toJson(itens));
^
symbol: class Gson
location: class App
2 errors
[Incubating] Problems report is available at: file:///home/ana/mercado/build/reports/problems/problems-report.html
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileJava' (registered by plugin class 'org.gradle.api.plugins.JavaBasePlugin').
> Compilation failed; see the compiler output below.
… « os mesmos 2 erros, repetidos
* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to get full insights from a Build Scan (powered by Develocity).
BUILD FAILED in 9s
1 actionable task: 1 executed
Com a dependência no lugar:
$ ./gradlew run --console=plain
Calculating task graph as configuration cache cannot be reused because file 'app/build.gradle.kts' has changed.
> Task :app:processResources NO-SOURCE
> Task :app:compileJava
> Task :app:classes
> Task :app:run
Bem-vinda ao mercado da Ana!
[{"nome":"arroz","preco":25.9},{"nome":"feijão","preco":8.75}]
BUILD SUCCESSFUL in 4s
2 actionable tasks: 2 executed
Configuration cache entry stored.
Repare: o run do Gradle já põe a Gson (e a dependência dela) no classpath. No Maven, a Ana teve de montar o -cp à mão. As bibliotecas baixadas pelo Gradle ficam em ~/.gradle/caches (o Gradle não usa o ~/.m2 do Maven).
Entregar o programa com as bibliotecas
O app.jar sozinho não tem Main-Class nem a Gson. A tarefa installDist monta uma pasta com tudo, e um script para rodar:
$ ./gradlew installDist --console=plain
…
> Task :app:jar
> Task :app:startScripts
> Task :app:installDist
BUILD SUCCESSFUL in 9s
4 actionable tasks: 3 executed, 1 up-to-date
Configuration cache entry stored.
$ find app/build/install -type f
app/build/install/app/lib/gson-2.13.1.jar
app/build/install/app/lib/app.jar
app/build/install/app/lib/error_prone_annotations-2.38.0.jar
app/build/install/app/bin/app « script para Linux e macOS
app/build/install/app/bin/app.bat « script para Windows
$ app/build/install/app/bin/app
Bem-vinda ao mercado da Ana!
[{"nome":"arroz","preco":25.9},{"nome":"feijão","preco":8.75}]
$ java -jar app/build/libs/app.jar
nenhum atributo de manifesto principal em app/build/libs/app.jar
O script bin/app monta o classpath com os três JARs da pasta lib e chama a classe principal. O app.zip que o build gerou é essa mesma pasta, compactada. (Se você quiser mesmo um java -jar, precisa configurar o manifesto da tarefa jar; veja a aula de JAR para entender o porquê.)
Missão: o mercado da Ana precisa do total da compra. Use o record Item e a lista abaixo para somar os preços num laço e mostrar Total: R$ 34,65 com printf e %.2f.
import java.util.List;
public class Main {
record Item(String nome, double preco) {}
public static void main(String[] args) {
List<Item> itens = List.of(new Item("arroz", 25.9), new Item("feijão", 8.75));
double total = 0;
// some os preços aqui
System.out.printf("Total: R$ %.2f%n", total);
}
}
import java.util.List;
public class Main {
record Item(String nome, double preco) {}
public static void main(String[] args) {
List<Item> itens = List.of(new Item("arroz", 25.9), new Item("feijão", 8.75));
double total = 0;
for (Item i : itens) {
total += i.preco();
}
System.out.printf("Total: R$ %.2f%n", total);
}
}
8. Maven × Gradle
| Maven | Gradle | |
|---|---|---|
| Receita | pom.xml (XML, declarativo) | build.gradle.kts (código Kotlin) ou build.gradle (Groovy) |
| Criar projeto | mvn archetype:generate | gradle init |
| Compilar | mvn compile | ./gradlew compileJava |
| Testar | mvn test | ./gradlew test |
| Gerar o JAR | mvn package | ./gradlew build (ou jar) |
| Rodar o programa | plugin extra (exec:java) ou java -cp … | ./gradlew run (plugin application) |
| Apagar o gerado | mvn clean (pasta target/) | ./gradlew clean (pasta build/) |
| Dependência | 5 linhas de <dependency> | implementation("g:a:v") |
| Bibliotecas baixadas | ~/.m2/repository | ~/.gradle/caches |
| Versão da ferramenta | A instalada (existe o mvnw, opcional) | O wrapper ./gradlew, gerado sempre |
| Velocidade | Refaz fases inteiras | Pula tarefas em dia, daemon, cache |
| Saída | Longa e detalhada | Curta (barra de progresso) |
| Onde aparece mais | Empresas, sistemas Java tradicionais, Spring | Android, projetos Kotlin, projetos grandes com muitas partes |
| Curva de aprendizado | Mais fácil: há um jeito de fazer cada coisa | Mais flexível, e por isso há mais jeitos de errar |
Qual usar? Num projeto que já existe, a que ele usa. Num projeto novo seu, qualquer uma serve; se a equipe ou o tutorial que você segue usa uma, fique com ela. As duas usam o mesmo Maven Central, a mesma estrutura src/main/java e o mesmo JUnit, então mudar de uma para outra é tranquilo.
Quando dá errado
Could not find com.google.code.gson:gson:2.99.0
$ ./gradlew run --console=plain
…
FAILURE: Build failed with an exception.
* What went wrong:
Configuration cache state could not be cached: field `classpath` of task `:app:compileJava` of type `org.gradle.api.tasks.compile.JavaCompile`: error writing value of type 'org.gradle.api.internal.artifacts.configurations.DefaultResolvableConfiguration'
> Could not resolve all files for configuration ':app:compileClasspath'.
> Could not find com.google.code.gson:gson:2.99.0.
Searched in the following locations:
- https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.99.0/gson-2.99.0.pom
Required by:
project ':app'
…
BUILD FAILED in 16s
O que aconteceu: a versão 2.99.0 não existe. A primeira frase (sobre configuration cache) assusta, mas é consequência; a causa está mais abaixo: Could not find …, com o endereço onde o Gradle procurou. Como resolver: corrija as coordenadas (procure em central.sonatype.com).
bash: ./gradlew: Permissão negada
$ ./gradlew build bash: ./gradlew: Permissão negada
O que aconteceu: o script perdeu a permissão de execução (acontece ao copiar o projeto de um zip ou do Windows). Como resolver: chmod +x gradlew. Para rodar uma vez sem mudar a permissão: sh gradlew build.
Directory '/home/ana' does not contain a Gradle build.
$ gradle build … * What went wrong: Directory '/home/ana' does not contain a Gradle build. A Gradle build's root directory should contain one of the possible settings files: settings.gradle, settings.gradle.kts, settings.gradle.dcl. It may also contain one of the possible build files: build.gradle, build.gradle.kts, build.gradle.dcl. To create a new Gradle build in this directory run 'gradle init' … BUILD FAILED in 2s
O que aconteceu: você está fora da pasta do projeto. Como resolver: cd para a pasta que tem o settings.gradle.kts (a raiz, não a app).
There were failing tests
O que aconteceu: pelo menos um teste falhou, e o Gradle para o build (não gera o JAR). Como resolver: veja o motivo no relatório app/build/reports/tests/test/index.html ou ligue o testLogging com exceptionFormat = FULL, como na seção 6. Depois corrija o código (ou o teste, se o teste estiver errado).
Referência
| Comando | O que faz |
|---|---|
gradle init --type java-application --dsl kotlin … | Cria um projeto (com --use-defaults, não pergunta nada) |
./gradlew build | Compila, testa e empacota (JAR, zip, tar) |
./gradlew run / run --args="a b" | Roda a mainClass com as dependências no classpath |
./gradlew test | Roda os testes |
./gradlew clean | Apaga a pasta build |
./gradlew installDist | Monta build/install/… com bin/ e lib/ |
./gradlew tasks | Lista as tarefas disponíveis |
./gradlew --stop | Para o daemon |
./gradlew --version | Versão do Gradle do wrapper |
… --console=plain | Saída em texto simples, uma linha por tarefa |
Exercícios
1. Rodar o programa
Complete o comando que roda o programa usando o wrapper:
2. Uma dependência
Complete a linha do build.gradle.kts que adiciona a biblioteca org.apache.commons:commons-lang3:3.17.0 para o programa:
3. Só para os testes
E se a biblioteca fosse usada só nos testes?
4. Por que usar ./gradlew em vez de gradle?
5. O que quer dizer > Task :app:compileJava UP-TO-DATE?
6. Onde ficam o JAR e os relatórios gerados pelo Gradle neste projeto?
Resumo
- O Gradle faz o mesmo que o Maven (dependências e build), com a receita em código:
build.gradle.kts. gradle init --type java-application --dsl kotlin …cria o projeto; o código fica emapp/src/main/java.- Dependências:
implementation("grupo:nome:versão"); só para testes:testImplementation(…). - Use sempre o wrapper
./gradlew: ele baixa e usa a versão certa do Gradle. ./gradlew build,run,test,clean; o gerado vai paraapp/build/.UP-TO-DATE= tarefa pulada porque nada mudou. O daemon deixa os comandos seguintes rápidos;--stopo desliga.- Num
BUILD FAILED, procure a causa emWhat went wronge nas linhas dojavacou do teste.