W3docs

Java Maven pom.xml

O Project Object Model do Maven — estrutura do pom.xml, coordenadas, propriedades e herança explicadas.

O pom.xml é o coração de qualquer projeto Maven. POM significa Project Object Model — um único arquivo XML que declara o que é o seu projeto (sua identidade), o que ele precisa (suas dependências) e como construí-lo (plugins e configuração). O Maven lê esse arquivo, baixa tudo o que ele referencia de um repositório e executa o build. Enquanto um projeto improvisado espalha esse conhecimento por scripts shell e uma pasta lib/ com JARs copiados manualmente, o Maven coloca tudo em um documento declarativo e versionado.

Este capítulo percorre a estrutura do POM parte a parte: o esqueleto mínimo, as coordenadas GAV que nomeiam cada artefato, como dependências e escopos funcionam, propriedades para eliminar duplicação de versões e herança por meio de um POM pai. Se você é novo no Maven, comece pela introdução ao Maven; para as fases de build que o POM conduz, consulte o ciclo de vida de build do Maven.

O POM mínimo

Todo POM é um documento XML com raiz em um elemento <project> e o esquema Maven 4.0.0. O menor POM útil declara sua versão de modelo e suas coordenadas — os quatro valores que nomeiam o artefato:

<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>com.w3docs</groupId>
  <artifactId>shop-api</artifactId>
  <version>1.4.0</version>
  <packaging>jar</packaging>
</project>

<modelVersion> é sempre 4.0.0 — é a versão do formato do POM, não do seu código. Deixe exatamente como mostrado.

Coordenadas: groupId, artifactId, version

Um artefato Maven é identificado por suas coordenadas GAV. Toda dependência que você adicionar é nomeada pelos mesmos três (às vezes quatro) valores, por isso vale aprendê-los com precisão:

ElementoSignificadoConvenção
groupIdA organização ou namespaceDNS reverso, ex.: com.google.code.gson
artifactIdO nome do projeto dentro do grupoMinúsculas com hífens, ex.: shop-api
versionA versão deste artefatoSemântica, ex.: 1.4.0; -SNAPSHOT para builds em andamento
packagingO tipo de saídajar (padrão), war, pom

Juntos, groupId:artifactId:version é globalmente único. É o que o Maven usa para localizar um JAR em um repositório e para nomear o artefato que o seu build produz. Uma versão terminada em -SNAPSHOT (ex.: 1.5.0-SNAPSHOT) é um build mutável em desenvolvimento que o Maven pode re-baixar; uma versão simples é tratada como imutável.

Declarando dependências

As dependências são listadas em <dependencies>, cada uma sendo um bloco <dependency> com as coordenadas de uma biblioteca necessária. O Maven as resolve — e as dependências delas, transitivamente — a partir de um repositório (Maven Central por padrão):

<dependencies>
  <dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
  </dependency>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.2</version>
    <scope>test</scope>
  </dependency>
</dependencies>

O <scope> controla quando uma dependência está no classpath. compile (o padrão) significa em todos os lugares; test significa apenas durante a compilação e execução de testes, então o JUnit nunca vai dentro do seu JAR. Outros escopos incluem provided (fornecido pelo ambiente de execução, ex.: uma API de servlet) e runtime (necessário para executar, mas não para compilar, ex.: um driver JDBC). A resolução transitiva, conflitos de versão e regras de escopo são abordados em profundidade em dependências Maven.

Propriedades: não repita versões

O elemento <properties> define variáveis reutilizáveis, referenciadas em outros lugares com a sintaxe ${nome}. O idioma é fixar cada versão de biblioteca uma vez no topo para que atualizações ocorram em um único lugar:

<properties>
  <maven.compiler.release>21</maven.compiler.release>
  <junit.version>5.10.2</junit.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
  </dependency>
</dependencies>

maven.compiler.release é uma propriedade bem conhecida que informa ao plugin compilador qual versão do Java deve ser o alvo — mais limpo do que configurar o plugin manualmente. Quando o Maven lê o POM ele interpola cada marcador ${...}, substituindo o valor da propriedade antes de resolver qualquer coisa.

Herança com um POM pai

Os POMs formam uma hierarquia. Um elemento <parent> faz um projeto herdar coordenadas, propriedades e gerenciamento de dependências de outro POM. O parent starter do Spring Boot é o exemplo clássico — ele fixa um conjunto consistente de versões de bibliotecas para que você possa omitir <version> nas dependências gerenciadas:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.3.2</version>
</parent>

<dependencies>
  <dependency>
    <!-- version omitted: inherited from the parent's dependencyManagement -->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
</dependencies>

Um build multi-módulo usa o mesmo mecanismo de forma inversa: um POM agregador com <packaging>pom</packaging> lista os <modules>, e cada filho o nomeia como <parent>. A configuração compartilhada fica em um lugar; os filhos permanecem pequenos.

Um exemplo trabalhado: lendo um POM como o Maven faz

Um pom.xml é apenas XML, então podemos analisar um com a API DOM nativa do JDK e percorrer sua estrutura exatamente como o Maven faria — lendo as coordenadas, as propriedades e cada dependência, enquanto interpolamos um marcador ${...} manualmente. (O Maven em si é uma ferramenta de build, não uma biblioteca no classpath aqui, mas isso mostra o modelo sobre o qual ele opera.)

java— editable, runs on the server

O que extrair da execução:

  • O modelVersion foi impresso como 4.0.0 — a constante que todo POM carrega. Ela identifica o formato do POM, não o seu projeto, e o Maven rejeitaria um POM que a omitisse.
  • As coordenadas saíram como com.w3docs:shop-api:1.4.0, o triplo GAV na sua forma canônica groupId:artifactId:version. Essa única string é como o Maven nomeia tanto o artefato que este build produz quanto cada dependência que ele resolve.
  • O packaging foi lido de volta como jar, o tipo de saída padrão. Se fosse pom, este seria um projeto agregador/pai que não produz nenhum JAR próprio.
  • A propriedade junit.version resolveu para 5.10.2, e o marcador ${junit.version} da dependência do JUnit foi interpolado para esse mesmo valor — exatamente a substituição que o Maven realiza para que uma versão seja declarada em um lugar e reutilizada.
  • A varredura de dependências reportou duas dependências e imprimiu cada uma com seu escopo: Gson teve como padrão compile (sem elemento <scope>, portanto está em todo classpath), enquanto o JUnit mostrou scope=test, mantendo-o fora do artefato distribuído.

Prática

Prática
Em um pom.xml, qual é o propósito dos três elementos groupId, artifactId e version juntos?
Em um pom.xml, qual é o propósito dos três elementos groupId, artifactId e version juntos?
Was this page helpful?