Labs SD > Ferramentas

Maven


Introdução

O Maven é uma ferramenta Java para a gestão de projetos que fornece aos programadores uma estrutura completa para suportar o ciclo de desenvolvimento de uma aplicação. Em particular, o Maven trata da compilação, distribuição, documentação, e colaboração em equipa, entre outras tarefas.

A estrutura e conteúdo do projeto Maven são declaradas num ficheiro XML, chamado POM (Project Object Model) pom.xml, que é a unidade fundamental deste sistema.

Estrutura de um ficheiro POM (documentação):

<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>

  <!--
    Os elementos de configuração básicos permitem 
    identificar unicamente o projeto, 
    especificar dependências e
    definir propriedades (variáveis). 
  -->
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <packaging>...</packaging>

  <dependencies>...</dependencies>
  <parent>...</parent>
  <dependencyManagement>...</dependencyManagement>
  <modules>...</modules>

  <properties>...</properties>

  <!-- 
    Os elementos de configuração de construção permitem declarar 
    a estrutura de pastas do projeto e 
    a gestão de extensões (plugins).
  -->
  <build>...</build>
  <reporting>...</reporting>

  <!-- 
    Informações adicionais do projeto 
  -->
  <name>...</name>
  <description>...</description>
  <url>...</url>
  <inceptionYear>...</inceptionYear>
  <licenses>...</licenses>
  <organization>...</organization>
  <developers>...</developers>
  <contributors>...</contributors>

  <!-- 
    Elementos de configuração do ambiente 
  -->
  <issueManagement>...</issueManagement>
  <ciManagement>...</ciManagement>
  <mailingLists>...</mailingLists>
  <scm>...</scm>
  <prerequisites>...</prerequisites>
  <repositories>...</repositories>
  <pluginRepositories>...</pluginRepositories>
  <distributionManagement>...</distributionManagement>
  <profiles>...</profiles>
</project>

Exemplo de ficheiro POM:

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- http://maven.apache.org/pom.html#Quick_Overview -->

  <!-- The Basics -->
  <groupId>example</groupId>
  <artifactId>java-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>java-app</name>
  <url>http://maven.apache.org</url>
  
  <!-- Build Settings -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.9</version>
        <configuration>
          <programs>
            <program>
              <mainClass>mypackage.MyClass</mainClass>
              <id>java-app</id>
            </program>
          </programs>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

 

Estrutura típica de pastas

Assumindo que ${basedir} corresponde à localização do projeto, a estrutura de pastas associada a um projecto Maven é a seguinte:

 

Conceitos fundamentais

Ciclos de vida de construção, fases e objetivos (documentação)

Em Maven, o processo de construção é dividido em ciclos de vida de construção, fases e objetivos. Um ciclo de vida de construção é composto por uma sequência de fases de construção e por sua vez cada fase de construção consiste numa sequência de objetivos.

Por exemplo, o ciclo default inclui as seguintes fases (lista completa de fases):

Uma execução no Maven consiste em passar um comando a este. Este comando corresponde ao nome dum ciclo de vida de construção, fase ou objetivo.

Se um ciclo de vida solicitado é executado, todas as fases de construção deste ciclo de vida são executadas. Por conseguinte, se uma fase de construção solicitada é executada, todas as fases de construção que a antecedem na sequência pré-definida de fases de construção são também executadas.

Por exemplo, executar:
mvn package
irá correr todas as fases anteriores - validate, compile, ... - antes de executar package.

Dependências e repositórios

Um dos primeiros objetivos executados pelo Maven é a verificação das dependências do projeto. As dependências são arquivos externos JAR (bibliotecas Java) necessárias para o projeto. Se as dependências não forem encontrados no repositório local, isto é, numa pasta no disco rígido do computador local, o Maven descarrega-as de um repositório central para o repositório local. Por omissão, o repositório local encontra-se na pasta %USER_HOME%. Contudo, é possível especificar um repositório local onde Maven irá guardar os artefactos.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository>C:/RepositorioLocal</localRepository>

Um exemplo de uma dependência é o JUnit, como pode ser visto abaixo.

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
  </dependencies>
</project>

Os três primeiros campos identificam a dependência. O parâmetro scope especifica que a dependência apenas existe para os testes. Isto significa que o Maven vai providenciar um classpath sem o JUnit para compilação do código principal e um classpath com o JUnit (na versão indicada) para compilação e execução do código de testes.

As dependências podem ser pesquisadas no motor de pesquisa amigável do repositório central Maven. Por exemplo, o JUnit 4.12 tem a seguinte página informativa: http://mvnrepository.com/artifact/junit/junit/4.12

Para o caso de projetos em desenvolvimento com inúmeros módulos (por exemplo: módulos A, B e C), com dependências entre eles, o conceito de SNAPSHOT é muitas vezes usado. Se um módulo A está em desenvolvimento rápido, e a criar novas versões com muita frequência, o sufixo -SNAPSHOT é adicionado no elemento <version>. Exemplo do pom.xml de A:

<project>
  ...
  <groupId>exemplo</groupId>
  <artifactId>modA</artifactId>
  <version>1.0-SNAPSHOT</version>
  ...
</project>

Assim, cada vez que o módulo A enviar uma SNAPSHOT do seu código actualizado para o repositório, vai substituir a versão que existia anteriormente. Por sua vez, os outros módulos, B e C, que dependem de A escolhem essa mesma versão SNAPSHOT como dependência. O pom.xml de B e C iriam conter:

<project>
  ...
    <dependency>
        <dependency>
            <groupId>exemplo</groupId>
            <artifactId>modA</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>
  </dependencies>
</project>

Deste modo, sempre que os módulos B e C são construídos, o Maven automaticamente actualiza o módulo A, obtendo fazendo o JAR correspondente ao SNAPSHOT mais recente.


Plugins de construção (documentação)

Os plugins de construção são utilizados para inserir objetivos adicionais numa fase de construção, caso seja necessário executar um conjunto de ações no projeto que não estejam cobertos pelas fases e objetivos padrão do Maven. Os plugins podem ser adicionados ao ficheiro POM. Para além dos plugins padrão disponibilizados, outros podem também ser implementados em Java.

Damos como exemplo o plugin AppAssembler:

<build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.9</version>
        <configuration>
          <programs>
            <program>
              <mainClass>mypackage.MyClass</mainClass>
              <id>java-app</id>
            </program>
          </programs>
        </configuration>
      </plugin>
    </plugins>
</build>

Este plugin é usado para criar um script de arranque do programa, tanto para Windows (ficheiro .bat) como para Linux (ficheiro com o atributo "executável"). Neste caso, o programa a executar é um programa de exemplo (java-app) cuja classe principal se chama mypackage.MyClass.


Perfis de construção

Os perfis de construção são utilizados caso seja necessário construir um projeto de maneira diferente. Por exemplo, pode ser necessário construir num computador pessoal projetos para desenvolvimento e teste. Pode ainda ser necesssário construí-los para um ambiente de produção. Estas versões poderão ser diferentes. Para permitir diferentes versões, diferentes perfis de construção podem ser adicionados aos ficheiros POM. Durante a execução pode ser especificado que perfil de construção deve ser usado.


© Docentes de Sistemas Distribuídos, Dep. Eng. Informática, Técnico Lisboa