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.
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 🏋️
- Crie um projeto Java usando o Maven (pode ser um projeto Quarkus).
- Adicione o PMD e o Checkstyle ao projeto.
- Inclua as três classes abaixo no projeto.
- 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;
}
}

CC BY 4.0 DEED