Java Essencial: Maven para projetos Java (dependências, build e execução)

Capítulo 16

Tempo estimado de leitura: 9 minutos

+ Exercício

O que é o Maven e por que usar em projetos Java

O Apache Maven é uma ferramenta de automação de build e gerenciamento de dependências. Em vez de você baixar bibliotecas manualmente, configurar classpath “na mão” e criar scripts de compilação, o Maven padroniza a estrutura do projeto e descreve tudo em um arquivo central: o pom.xml. Com isso, você consegue:

  • Baixar e versionar dependências automaticamente (e suas dependências transitivas).
  • Executar fases de build padronizadas (test, package, etc.).
  • Gerar artefatos como .jar de forma reproduzível.
  • Manter um padrão de pastas que facilita integração com IDEs e CI.

Estrutura padrão de um projeto Maven

Um projeto Maven segue uma convenção de diretórios. A estrutura mais comum é:

meu-projeto/  pom.xml  src/    main/      java/        (código fonte da aplicação)      resources/        (arquivos de configuração, templates, etc.)    test/      java/        (testes automatizados)      resources/        (recursos usados em testes)

O Maven compila automaticamente o que está em src/main/java e executa testes em src/test/java (normalmente com JUnit). Recursos em resources são copiados para o classpath do artefato final.

O papel do pom.xml

O pom.xml (Project Object Model) descreve o projeto: suas coordenadas, dependências, plugins de build e configurações. É o “contrato” que permite a qualquer pessoa (ou servidor) construir o projeto do zero com os mesmos resultados.

Coordenadas: groupId, artifactId, version

As coordenadas identificam unicamente um artefato Maven:

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

  • groupId: geralmente o domínio invertido da organização (ex.: br.com.suaempresa).
  • artifactId: nome do projeto/módulo (ex.: app-console).
  • version: versão do artefato (ex.: 1.0.0 ou 1.0.0-SNAPSHOT).

Exemplo mínimo de pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>br.com.exemplo</groupId>  <artifactId>app-console</artifactId>  <version>1.0.0</version></project>

Repositórios Maven e como as dependências são resolvidas

Quando você declara uma dependência, o Maven procura o artefato em repositórios remotos (por padrão, o Maven Central) e armazena uma cópia local no seu computador (repositório local, tipicamente em ~/.m2/repository). Isso acelera builds futuros e permite reuso entre projetos.

Quando declarar repositórios adicionais

Na maioria dos casos, o Maven Central é suficiente. Você declara repositórios adicionais quando uma biblioteca não está no Central (por exemplo, repositórios internos da empresa). Exemplo:

<repositories>  <repository>    <id>repo-interno</id>    <url>https://repo.suaempresa.com/maven2</url>  </repository></repositories>

Use com critério: adicionar muitos repositórios pode tornar o build mais lento e menos previsível.

Dependências e escopos (scope)

Dependências são bibliotecas externas que seu projeto usa. No pom.xml, você declara cada dependência com suas coordenadas. Exemplo (JUnit para testes):

<dependencies>  <dependency>    <groupId>org.junit.jupiter</groupId>    <artifactId>junit-jupiter</artifactId>    <version>5.10.2</version>    <scope>test</scope>  </dependency></dependencies>

Principais escopos

ScopeQuando usarEntra no classpath de compilação?Entra no classpath de testes?Vai para o artefato final?
compile (padrão)Dependência necessária para compilar e rodarSimSimNão “embutida” automaticamente no JAR (fica como dependência externa)
testSomente para testesNãoSimNão
providedDisponível no ambiente de execução (ex.: servidor)SimSimNão
runtimeNecessária apenas em tempo de execuçãoNãoSimNão

Observação importante: por padrão, o Maven gera um JAR “magro” (sem dependências dentro). Para um JAR executável com dependências embutidas (fat/uber jar), você usa plugins específicos (veremos mais adiante).

Comandos essenciais do Maven (ciclo de vida)

O Maven organiza o build em fases. Você executa fases com mvn <fase>. As mais usadas:

  • mvn clean: limpa o diretório target/ (saídas de builds anteriores).
  • mvn test: compila e executa testes.
  • mvn package: gera o artefato (geralmente um .jar) em target/.

Exemplo de fluxo típico:

mvn clean test mvn clean package

Você também pode combinar em um único comando:

mvn clean package

Isso executa clean e, em seguida, todas as fases necessárias até package (incluindo compilação e testes).

Projeto prático: transformar um programa anterior em projeto Maven

A seguir, você vai pegar um programa simples de console (com uma classe com main) e organizá-lo como um projeto Maven, adicionando testes e empacotando um JAR.

Passo 1: criar a estrutura de pastas

Crie uma pasta para o projeto e a estrutura padrão:

app-console/  pom.xml  src/    main/      java/    test/      java/

Passo 2: definir o pacote e mover o código para src/main/java

Escolha um pacote (por exemplo, br.com.exemplo.app). Crie as pastas correspondentes e coloque sua classe principal lá:

app-console/src/main/java/br/com/exemplo/app/App.java

Exemplo de App.java:

package br.com.exemplo.app; public class App {    public static void main(String[] args) {        System.out.println("Olá, Maven!");    } }

Passo 3: criar o pom.xml com configurações básicas

Agora crie o pom.xml na raiz. Além das coordenadas, é uma boa prática definir a versão do Java usada na compilação. Exemplo:

<project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>br.com.exemplo</groupId>  <artifactId>app-console</artifactId>  <version>1.0.0</version>  <properties>    <maven.compiler.release>17</maven.compiler.release>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>    <dependency>      <groupId>org.junit.jupiter</groupId>      <artifactId>junit-jupiter</artifactId>      <version>5.10.2</version>      <scope>test</scope>    </dependency>  </dependencies>  <build>    <plugins>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-surefire-plugin</artifactId>        <version>3.2.5</version>      </plugin>    </plugins>  </build></project>

O maven.compiler.release define a versão alvo do Java (compilação e bytecode). Ajuste para a versão do seu JDK.

Passo 4: adicionar uma classe de lógica testável (exemplo) e criar testes

Para testar algo de forma útil, crie uma classe simples com um método e teste com JUnit.

Crie:

app-console/src/main/java/br/com/exemplo/app/SaudacaoService.java

Conteúdo:

package br.com.exemplo.app; public class SaudacaoService {    public String saudar(String nome) {        if (nome == null || nome.isBlank()) {            return "Olá!";        }        return "Olá, " + nome.trim() + "!";    } }

Agora crie o teste em:

app-console/src/test/java/br/com/exemplo/app/SaudacaoServiceTest.java

Conteúdo:

package br.com.exemplo.app; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class SaudacaoServiceTest {    @Test    void deveSaudarComNome() {        SaudacaoService service = new SaudacaoService();        assertEquals("Olá, Ana!", service.saudar("Ana"));    }    @Test    void deveSaudarSemNomeQuandoNuloOuVazio() {        SaudacaoService service = new SaudacaoService();        assertEquals("Olá!", service.saudar(null));        assertEquals("Olá!", service.saudar("   "));    } }

Se quiser usar o serviço no main, atualize o App:

package br.com.exemplo.app; public class App {    public static void main(String[] args) {        SaudacaoService service = new SaudacaoService();        String nome = (args.length > 0) ? args[0] : "";        System.out.println(service.saudar(nome));    } }

Passo 5: executar os comandos Maven (clean, test, package)

No terminal, dentro da pasta app-console:

  • Limpar saídas anteriores:
mvn clean
  • Rodar testes:
mvn test
  • Gerar o JAR:
mvn package

Após mvn package, verifique a pasta target/. Você deve ver algo como:

target/  app-console-1.0.0.jar  classes/  test-classes/  surefire-reports/

Como executar a aplicação empacotada

Opção A: executar via classpath (sem configurar Main-Class no manifesto)

Se você ainda não configurou o JAR como executável (com Main-Class), pode rodar assim:

java -cp target/app-console-1.0.0.jar br.com.exemplo.app.App

Passando argumento:

java -cp target/app-console-1.0.0.jar br.com.exemplo.app.App Ana

Opção B: gerar um JAR executável (com Main-Class)

Para permitir java -jar ..., configure o plugin de JAR para incluir o atributo Main-Class no manifesto.

No pom.xml, dentro de <build><plugins>, adicione:

<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-jar-plugin</artifactId>  <version>3.4.2</version>  <configuration>    <archive>      <manifest>        <mainClass>br.com.exemplo.app.App</mainClass>      </manifest>    </archive>  </configuration></plugin>

Reempacote:

mvn clean package

Agora execute:

java -jar target/app-console-1.0.0.jar

Com argumento:

java -jar target/app-console-1.0.0.jar Ana

Entendendo o que acontece no build

  • mvn test compila o código principal e o de teste, e executa os testes (relatórios em target/surefire-reports).
  • mvn package gera o artefato em target/. Em projetos Java padrão, isso é um JAR.
  • Dependências baixadas ficam no repositório local (~/.m2/repository), evitando downloads repetidos.

Checklist rápido de problemas comuns

  • Erro de versão do Java: ajuste <maven.compiler.release> para a versão do seu JDK instalado.
  • Testes não rodam: confirme que os testes estão em src/test/java e que a dependência do JUnit está com scope test.
  • Classe principal não encontrada: verifique o pacote e o nome completo (br.com.exemplo.app.App) e, se usar java -jar, confirme a configuração do maven-jar-plugin.

Agora responda o exercício sobre o conteúdo:

Em um projeto Maven, qual configuração é necessária para permitir a execução do JAR com o comando java -jar?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Para usar java -jar, o JAR precisa ter o atributo Main-Class no manifesto. No Maven, isso é feito configurando o maven-jar-plugin com a classe principal.

Próximo capitúlo

Java Essencial: Noções de Gradle e comparação prática com Maven

Arrow Right Icon
Capa do Ebook gratuito Java Essencial: Fundamentos da Linguagem e do Ecossistema (JDK, IDE, Maven)
89%

Java Essencial: Fundamentos da Linguagem e do Ecossistema (JDK, IDE, Maven)

Novo curso

18 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.