Maven 🧰

O Maven é uma ferramenta de automação e gerenciamento de projetos, bastante utilizada no ecossistema Java. Foi criada pela Apache Software Foundation no ano de 2002 e é uma das ferramentas mais utilizadas para construir projetos Java. O Maven permite que você compile, teste, empacote, instale e implante projetos. Além disso, o Maven fornece maneiras de gerenciar dependências que são baixadas automaticamente da internet.

Principais conceitos 📚

Para automatizar a construção de um projeto, o Maven utiliza um conceito de ciclo de vida. Um ciclo de vida é uma sequência de fases que são executadas em ordem determinada. Cada fase é responsável pela execução de uma ou mais tarefas específica.

Os principais ciclos de vida com suas respectivas fases no Maven são: default, clean e site.

  • O ciclo de vida default compreende as fases: validate, compile, test, package, verify, install e deploy.
  • Já o ciclo de vida clean inclui as fases pre-clean, clean e post-clean.
  • Finalmente, o ciclo de vida site inclui as fases pre-site, site e post-site.

A Figura 1 a seguir mostra um mapa conceitual sobre os ciclos de vidas e as fases do Maven.

Maven
Figura 1 - Mapa conceitual sobre os ciclos de vidas e as fases do Maven

O ciclo de default é o mais utilizado e é o que será abordado neste material.

  • validade: valida o projeto, como por exemplo, verificar se os recursos necessários estão disponíveis.
  • compile: compila o código fonte do projeto.
  • test: executa os testes unitários do projeto.
  • package: empacota o código compilado em um formato específico, como por exemplo, um JAR (Java Archive) ou WAR (Web Archive).
  • verify: executa uma análise de qualidade no projeto, como por exemplo, inspeções de código, teste de integração e cobertura.
  • install: instala o pacote no repositório local, para que ele possa ser utilizado como dependência em outros projetos.
  • deploy: implanta o projeto.

Cada fase pode utilizar um ou mais plugins. Um plugin do Maven adiciona funcionalidades na fase em que é executado. Por exemplo, o plugin maven-pmd-plugin adiciona a funcionalidade de análise estática de código na fase verify do ciclo de vida default

Um plugin pode ter um conjunto de goals. Um goal é uma tarefa específica que um plugin executa. Por exemplo, o plugin maven-pmd-plugin tem o goal pmd que executa a análise estática de código. Porém, esse mesmo plugin possui outros goals como check e cpd. Todos esses goals podem ser executados na fase verify do ciclo de vida default.

Configuração 🖥️

Para configurar o Maven em um projeto, é necessário criar um arquivo pom.xml (Projeto Object Model) na raiz do projeto. O arquivo pom.xml é um arquivo de configuração do Maven que contém informações sobre o projeto, como por exemplo, o nome do projeto, a versão, a descrição, as dependências, os plugins, entre outras informações.

Podemos personalizar o ciclo existente conectando plugins às fases ou criando metas específicas. Por exemplo, se quisermos adicionar o analisador estático PMD ao nosso projeto, podemos fazer isso usando o Maven:

<!-- Analisador estático PMD -->
<plugin>
  <!-- Declaração do plugin -->
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-pmd-plugin</artifactId>
  <version>3.21.2</version>
	<executions>
    <execution>
      <id>pmd-verify</id>  <!-- Identificador interno -->
      <phase>verify</phase> <!-- Fase que irá ser executado -->
      <goals>
      <goal>check</goal> <!-- Goal ou ferramenta que será executado -->
      </goals>
    </execution>
  </executions>
  <!-- Configurações do plugin -->
  <configuration>
    <failOnViolation>true</failOnViolation>
    <printFailingErrors>true</printFailingErrors>
    </configuration>
</plugin>

Da mesma forma, podemos adicionar o plugin Checkstyle ao nosso projeto:

<plugin>
  <!-- Declaração do plugin -->
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>3.3.1</version>
  <executions>
    <execution>
      <id>checkstyle-verify</id>
      <phase>verify</phase> <!-- Fase que irá ser executado -->
      <goals>
        <goal>check</goal> <!-- Ferramenta -->
      </goals>
    </execution>
  </executions>
  <configuration>
    <encoding>UTF-8</encoding>
    <consoleOutput>true</consoleOutput>
    <failsOnError>true</failsOnError>
  </configuration>
</plugin>

Exercício 🏋️

  1. Crie um projeto Java usando o Maven (pode ser um projeto Quarkus).
  2. Adicione o PMD e o Checkstyle ao projeto.
  3. Inclua as três classes abaixo no projeto.
  4. Execute a fase verify do Maven para identificar possíveis problemas no código.
package br.com.exemplo.modelo;

import java.util.Date;

public class Cliente {
    public String nome;
    public String email;
    public int idade;
    private String codigoInterno;
    private Date cadastro;

    public Cliente(String n, String e, int i) {
        this.nome = n;
        this.email = e;
        this.idade = i;
        cadastro = new Date();
        String temporariaQueNaoUsa = "xxx";
    }

    public boolean valida() {
        if (nome == null || email == null) {
            System.out.println("Dados inválidos");
            return false;
        }
        if (nome == "") {
            System.out.println("Nome vazio");
        }
        if (idade < 0 || idade > 200) {
            System.out.println("Idade estranha");
        }
        return true;
    }

    public String getEmail() {
        if (email == null) {
            email = "";
        }
        return email.trim();
    }

    @Override
    public boolean equals(Object o){
        if (o instanceof Cliente) {
            Cliente c = (Cliente) o;
            return this.email == c.email;
        }
        return false;
    }

    @Override
    public int hashCode(){
        return 42;
    }

    public void Atualiza(){ }
}
package br.com.exemplo.modelo;

import java.util.ArrayList;
import java.util.List;

public class Pedido {
    public List<String> itens = new ArrayList<>();
    public double valorTotal;
    private String status = "NOVO";

    public void adicionarItem(String nome, double preco){
        if (nome == null || nome.length() == 0) {
            System.out.println("Item sem nome");
        }
        itens.add(nome);
        valorTotal += preco;
        if (valorTotal > 1000) { System.out.println("Pedido grande!"); }
    }

    public String resumo(){
        String s = "Pedido: ";
        for (int i=0;i<itens.size();i++){
            s = s + itens.get(i) + ", ";
        }
        return s;
    }

    public void processar(){
        if ("NOVO".equals(status)) {
            System.out.println("Processando pedido novo...");
            status = "PROCESSANDO";
        }
        if ("PROCESSANDO".equals(status)) {
            System.out.println("Ainda processando...");
        }

        int tipo = 2;
        switch (tipo) {
            case 1: System.out.println("Tipo 1"); break;
            case 2: System.out.println("Tipo 2"); break;
        }

        try {
            if (valorTotal < 0) throw new IllegalStateException("valor negativo?");
        } catch (Exception e) {
        } finally {
            if (itens.size() == 0) { return; }
        }
    }

    public void FecharPedido(boolean notificarCliente){
        if (!"PROCESSANDO".equals(status)) { System.out.println("Estado inválido"); }
        status = "FECHADO";
        if (notificarCliente) {
            System.out.println("Notificando cliente...");
        }
        if (false) {
            System.out.println("Nunca executa");
        }
    }
}
package br.com.exemplo.servico;

import br.com.exemplo.modelo.Pedido;

public class PedidoService {

    public synchronized boolean ProcessaOuNao(Pedido p, int t){
        if (p == null) return false;
        boolean ok = false;

        if (t > 10) {
            ok = true;
        } else {
            if (t <= 10) { ok = false; }
        }

        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (!ok) {
            return false;
        }

        System.out.println("Processando pedido no serviço...");
        p.FecharPedido(true);
        return true;
    }

    public String buscaStatus(Pedido p){
        if (p == null) {
            return null;
        }
        return null;
    }
}
Rodrigo Prestes Machado
CC BY 4.0 DEED

Copyright © 2024 RPM Hub. Distributed by CC-BY-4.0 license.