Processo de build com o Maven

O Maven é uma ferramenta de gerenciamento, construção e implantação de projetos muito interessante, que te ajuda no processo de gerenciamento de dependências e no de build, geração de relatórios e de documentação. Na Caelum esta é a ferramenta usada em todos os projetos internos e nas consultorias.

Muitas pessoas migram seus projetos para o Maven, mas acabam arrumando mais problemas que soluções, pois não conseguem configurá-lo corretamente, e acabam desistindo e fazendo tudo na mão, ou voltando para o Ant. Mas se você conseguir ajustar as configurações, o Maven vai te ajudar muito e vai compensar todos os (poucos) problemas que ele eventualmente causa. No início do uso do Maven, espere formar com ele uma relação de amor e ódio.

Para começar a usar o Maven, tudo o que você precisa fazer é baixá-lo e configurar umas poucas variáveis de ambiente. Depois de ter feito isso, é só digitar mvn [target] na linha de comando. Alguns sistemas operacionais já te oferecem essa instalação através do macport ou apt-get.

A unidade básica de configuração do Maven é um arquivo chamado pom.xml, que deve ficar na raiz do seu projeto. Ele é um arquivo conhecido como Project Object Model: lá você declara a estrutura, dependências e características do seu projeto. A idéia é bem parecida com o build.xml do Ant: você deixa o pom.xml na raiz do seu projeto para poder chamar as targets de build do seu projeto. O menor arquivo pom.xml válido é o seguinte:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>br.com.caelum</groupId>
  <artifactId>teste</artifactId>
  <version>1.0</version>
</project>

Que contém apenas a identificação do projeto, e uma informação a mais: modelVersion, que é a identificação da versão do arquivo pom.xml e deve ser sempre 4.0.0. A identificação do projeto consiste em três informações:

  • groupId: um identificador da empresa/grupo ao qual o projeto pertence. Geralmente o nome do site da empresa/grupo ao contrário. Ex: br.com.caelum.
  • artifactId: o nome do projeto. Ex: teste.
  • version: a versão atual do projeto. Ex: 1.0-SNAPSHOT.

Essas informações são usadas em muitos lugares, ccomo o controle de dependências que é, na minha opinião, a funcionalidade mais útil do Maven. Por exemplo, para dizer que o log4j 1.2.15 é uma dependência da sua aplicação é só acrescentar no seu pom as linhas:

<project>
...
  <dependencies>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.15</version>
    </dependency>
  </dependencies>
...
</project>

Quando necessário, o Maven vai baixar pra você o jar do log4j 1.2.15, e todas as suas dependências, e vai colocá-las no classpath da sua aplicação durante os builds, testes, etc. Ou seja, você não precisa mais entrar no site do log4j, baixar um zip com vários jars e ter que procurar quais jars devem ser colocados no classpath! No Repositório de Bibliotecas do Maven você encontra os jars que você pode colocar como dependência do seu projeto, e o pedaço de xml que você deve copiar e colar dentro da tag dependencies do seu pom para incluir essas bibliotecas.

Todos os jars baixados pelo Maven são guardados na pasta repository dentro da M2_HOME que você configurou quando instalou o Maven. Assim, se mais de um projeto seu depende do mesmo jar, ele não é baixado de novo.

A grande diferença entre o build.xml do Ant e o pom.xml do Maven é o paradigma. No Ant usamos esse XML praticamente como uma linguagem de programação, onde você da comandos em relação ao build do projeto. No Maven usamos o XML para definir a estrutura do projeto, e a partir dessas declarações o Maven possui targets bem definidos que usam essas informações para saber como realizar aquela tarefa. Um exemplo: para compilar com o Ant criamos um target que chama o javac, mas para compilar com o Maven usamos um target já existente (não o criamos), e ele vai usar a informação que define onde está o código fonte e para onde ele deve ser compilado (sendo que muitas dessas informações possuem convenções e defaults, e nem precisam ser configuradas).

Além dos principais targets do Maven, você pode executar targets de plugins. Você só precisa digitar na linha de comando:

mvn [nomedoplugin]:[target]

e então o Maven baixa o plugin, se necessário, e executa a target pra você. Existe uma lista bem grande de plugins do Maven e uma boa parte desses plugins podem ser usados sem nenhuma configuração adicional no seu pom.

Para dar um exemplo de plugin do Maven nada melhor do que o plugin que cria um protótipo de projeto do Maven: o Archetype. É bem parecido com o scaffold do Ruby: ele cria um protótipo de projeto a partir de um modelo escolhido. O jeito mais fácil de usar esse plugin é digitando na linha de comando:

mvn archetype:create

E então o Archetype vai perguntar qual é o tipo de projeto que você deseja, o groupID, artifactID, version e o pacote referentes ao seu projeto. Depois disso você terá uma estrutura de projeto pronta para ser usada.
Por exemplo se você escolheu o tipo de projeto maven-archetype-quickstart, o Archetype vai criar uma estrutura de pastas parecidas com a seguinte:


teste
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- br
    |           `-- com
    |               `-- caelum
    |                   `-- teste
    |                       `-- App.java
    `-- test
        `-- java
            `-- br
                `-- com
                    `-- caelum
                        `-- teste
                            `-- AppTest.java

E então é só continuar o seu projeto a partir daí. O código de teste já vem separado do código principal, e o junit já vem como dependência da aplicação. Você também pode criar as pastas src/main/resources e src/test/resources para colocar os recursos (arquivos de configuração, de teste, e etc) do código principal e do de testes, respectivamente. Tudo que estiver dentro dessas pastas é copiado diretamente para o diretório onde as classes são compiladas, sem que seja necessário fazer nenhuma configuração adicional.

Se você, por algum motivo, não gostou da estrutura que o Maven criou, ou está querendo migrar um projeto para o Maven que não segue essa estrutura, você pode configurar os diretórios do projeto
acrescentando algumas linhas no pom:

<project>
...
<build>
    <sourceDirectory>
      ${project.basedir}/src/java/main
    </sourceDirectory>
    <testSourceDirectory>
      ${project.basedir}/src/java/test
    </testSourceDirectory>
    <resources>
          <resource>
                 <directory>
                   ${project.basedir}/src/resources/main
                 </directory>
          </resource>
    </resources>
    <testResources>
          <testResource>
                 <directory>
                   ${project.basedir}/src/resources/test
                 </directory>
          </testResource>
    </testResources>
</build>


...
</project>

Nesse exemplo o diretório principal de código e de recursos estarão em src/java/mainsrc/resources/main respectivamente, e os diretorios de teste em src/java/test e src/resources/test.

Agora com um projeto Maven já preparado, vamos para a principal funcionalidade: o build. O build do Maven é baseado no conceito de ciclo de vida: o processo de construção e distribuição da sua aplicação é dividido em partes bem definidas chamadas fases, seguindo um ciclo. O ciclo padrão é o seguinte:

  • compile – compila o código fonte do projeto
  • test – executa os testes unitários do código compilado, usando uma ferramenta de testes unitários, como o junit.
  • package – empacota o código compilado de acordo com o empacotamento escolhido, por exemplo, em JAR.
  • integration-test – processa e faz o deploy do pacote em um ambiente onde os testes de integração podem ser rodados.
  • install – instala o pacote no repositório local, para ser usado como dependência de outros projetos locais
  • deploy – feito em ambiente de integração ou de release, copia o pacote final para um repositório remoto para ser compartilhado entre desenvolvedores e projetos

Você pode invocar qualquer dessas fases na linha de comando, digitando:

mvn [fase]

Por exemplo se você digitar mvn package o Maven vai executar todas as fases anteriores do ciclo até a fase package. Uma lista completa das fases do ciclo de vida possíveis pode ser encontrada aqui.

Algumas das fases do ciclo possuem plugins associadas a elas, e esses plugins são executados assim que a fase é chamada para ser executada. Você pode também registrar plugins para rodarem em qualquer fase do ciclo, conseguindo, assim, personalizar o build do seu projeto facilmente. Por exemplo, se você quiser criar um jar com o código fonte do projeto, e que esse jar seja gerado depois que o projeto foi empacotado, é só acrescentar no seu pom:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <executions>
          <execution>
            <id>attach-sources</id>
            <phase>package</phase>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Assim, o plugin Source vai executar seu goal jar na fase package do ciclo de vida. É como se fosse chamado mvn source:jar quando o build passa pela fase de package. A fase package já possui um plugin associado a ela: o jar:jar (supondo que é um projeto jar), então o plugin source só será executado depois do jar:jar. Em geral se você registrar mais de um plugin pra mesma fase, eles serão executados na ordem em que eles forem declarados. O jeito de configurar o plugin para colocá-lo dentro de uma fase do ciclo geralmente está no site principal do plugin, na seção Usage.

O Maven possui ainda outras funcionalidades interessantes, como geração de relatórios. Alguns plugins também merecem uma atenção especial, como o Eclipse que gera informações de projeto para o eclipse (.classpath e .project), o Antrun que te permite executar código Ant dentro do Maven, o Cobertura que gera um relatório mostrando a cobertura de testes no seu projeto, o Jetty que sobe uma instância do Jetty com sua aplicação deployed, o Selenium que sobe uma instância do servidor do Selenium para poder fazer os testes de aceitação do selenium, enfim, existem vários plugins interessantes e é relativamente fácil achar o plugin que faz o que você precisa. É igualmente fácil, também, fazer um plugin para o Maven, o chamado Mojo.

Aqui na Caelum, além do Maven e JUnit, usamos muito o Selenium, juntamente com o SeleniumDSL, para os testes de integração, e o Cruise Control para o controle da integração contínua. Esperamos colocar tutoriais e vídeos sobre essas ferramentas também.

30 Comentários

  1. Bruno Andrade 07/07/2008 at 20:46 #

    olá lucas,
    muito bom o artigo,uma curiosidade como vocês da caelum fazem no dia a dia, quero dizer usam wtp(eclipse)+maven ou maven e eclipse só para codificar mesmo?

  2. Lucas Cavalcanti 07/07/2008 at 22:40 #

    Olá Bruno,
    a gente costuma usar o eclipse com wtp e maven… Se o seu projeto for web, você pode ainda passar um parametro adicional para que o seu projeto vire um projeto web no eclipse:

    mvn eclipse:eclipse -Dwtpversion=2.0

    ou mude a versão pra versão do wtp…

  3. Fernando Boaglio 08/07/2008 at 01:23 #

    Bom artigo para introdução ao Maven2, com certeza o seu uso é como você disse, ou as pessoas adoram ou detestam.

    Sugiro também além do link que você publicou, essa engine de busca: http://maven.ozacc.com/ e o uso do plugin do eclipse: http://m2eclipse.codehaus.org/

  4. Diego Carrion 08/07/2008 at 02:06 #

    Muito bom o post.

  5. Dennys 08/07/2008 at 13:33 #

    Bacana! Ja uso o maven faz algum tempo… junto com o Continuum…

    Vou plugar meu listener aqui para ver quando vai sair algo com o Cruise Control, Selenium… hehehe

    Abraços!

  6. mauricio gamarra 08/07/2008 at 14:17 #

    Um grande problema que tenho com o maven com eclipse, mesmo usando o m2eclipse é debugar aplicações web, nunca consegui.
    Alguém tem alguma dica de como fazer?
    Abraços

  7. Lucas Cavalcanti 08/07/2008 at 16:20 #

    A versão nova do m2eclipse tem uma integração com o WTP que já transforma o projeto em projeto web. E o plugin eclipse:eclipse do maven tem uma opção pra usar o wtp também.
    É só instalar um servidor web no eclipse e fazer o deploy do seu projeto nesse servidor.
    Dá pra subir o servidor em modo debug… Isso deve funcionar

  8. Donizetti 10/07/2008 at 01:50 #

    Ola Bruno….Otimo post…
    So gostaria de perguntar oque é o SeleniumDSL ??? =D

  9. Antonio Kantek 12/07/2008 at 18:36 #

    Eu gosto muito do Team City. Acho ele um bom competidor para o Cruise Control.

  10. Bruno 14/07/2008 at 14:09 #

    Parabéns pelo post, muitas vezes o pessoal desanima por ter que apagar incêncio e falta de tempo para artigos gigantes sobre o assunto.

  11. Danilo Torres 17/07/2008 at 13:21 #

    Olá todos,
    Bom, tenho procurado muitos artigos, fóruns sobre o plugin m2eclipse, porém tenho encontrado uma certa dificuldade em encontrar um bom material, visto que a grande maioria informa os comandos que devem ser passados para executar as fazer e tal… (inclusive neste artigo – por sinal bastante simples e eficiente). Gostaria de saber se mesmo com o m2eclipse é necessário estar com o cmd aberto para executar os comandos do maven2

    valeu!

  12. Lucas Cavalcanti 17/07/2008 at 16:23 #

    Então Danilo, com o plugin m2eclipse é só colocar o projeto como gerenciado pelo plugin e vc provavelmente não vai precisar rodar os targets do maven na mão. Se mesmo assim você precisar rodar algum plugin do maven, é só ir em Run As >> Maven build e colocar o target… Não precisa estar com o cmd aberto…

    []’s

  13. Luiz 19/07/2008 at 19:00 #

    Olá, Lucas!

    Pelo que eu sei, o mvn package gera um jar apenas com seu projeto, sem os jars de que ele depende. Existe algum comando para o maven que gere o jar com as dependências inclusas?

    Ah! Parabéns pelo post! Muito bom!

  14. Lucas Cavalcanti 20/07/2008 at 03:00 #

    Olá, Luiz,
    existe o plugin shade que cria um uber-jar com as dependências inclusas… nunca usei, mas deve resolver o problema…

    []’s

  15. paulo 20/11/2008 at 09:51 #

    oi, tenho uma dúvida parecida com a do luiz (coment 13).
    Como faço para rodar um jar gerado pelo maven usando o comando java no terminal? quando tento fazer isso, estou usando jdbc com mysql, dá um erro de classe não encontrada. o comando é mais ou menos java -jar myapp.jar. como faço para minha aplicação enxergar as dependências que já foram baixadas para o repositório local.

  16. Lucas Cavalcanti 20/11/2008 at 13:58 #

    pra rodar o jar, vc precisa colocar todas as dependencias no classpath:

    java -classpath -jar myapp.jar

  17. Fred 30/01/2009 at 06:29 #

    Tenho utilizado o maven com um amigo nos projetos da empresa em que trabalhamos e tb tenho utilizado ele em casa nos estudos.
    O maven realmente ajuda muito e automatiza muito.

    Ontem precisei alterar um jar do tomahawk para uma versão mais nova, então eu somente entrei no pom.xml ou na administração do eclipse e alterei o número da versão…. ele automaticamente retirou o antigo arquivo e baixou a versão desejada.

  18. José 03/05/2012 at 16:59 #

    Olá Lucas, antes de mais nada quero lhe dar os parabéns pelo post, muito bom.

    Quero te pedir uma ajuda, estou tentando trabalhar com o Maven 3.0.4 e o plugin M2eclipse, mas estou encotrando problemas, fiz as configurações e quando tento criar um projeto no eclipse “Maven Project”, e tento trabalhar com o maven-archetype-webapp da o seguinte erro:

    Could not resolve archetype org.apache.maven.archetypes:maven-archetype-webapp:RELEASE from any of the configured repositories.

    já fiz de tudo pra tentar resolver, mais não consegui, tem como você me ajudar?

  19. Fabiano Góes 12/09/2012 at 09:43 #

    Olá Lucas, ressuscitando esse post sobre Maven, primeiro quer dar parabéns pelo excelente post.
    Esse “Cruise Control” tem o mesmo papel do Hudson??
    O que exatamente é o Selenium?
    Outra coisa: usando o plugin maven/eclipse você cria o projeto direto no Eclipse ou cria via cmd e depois importa no eclipse?

  20. Thiago 23/01/2014 at 11:32 #

    Olá Lucas, sei que o Post é antigo, mas espero que consiga responder minha dúvidas.

    Já procurei em vários lugares, tentei entender… mas como posso fazer por exemplo, qdo tenho um problema que possui WebServices e outro com o Backend para Web, que compartilham POJOS ? Consigo compilar sem ter que duplicar minhas classes ? E isso eu consigo dentro do Eclipse ?

    Obrigado

  21. Tio 17/03/2014 at 09:43 #

    Estou começando a usar o Maven agora e digo que este foi o artigo que mais facilitou a compreensão e uso dele.
    Vlw

  22. Simeao 30/04/2014 at 12:10 #

    Tenho seguinte problema a versão do jar que estou usando é superior a que está disponível no repositorio do Maven como faço para criar um repositorio local para essas situações.

  23. Hugo Benício 09/05/2014 at 11:13 #

    Excelente post! Continue com o bom trabalho!

  24. Cleiton Maciel 09/05/2014 at 13:55 #

    Sou iniciando no mundo java, e o que estou vendo do Maven que o sufoco pra encontrar os jar’s correto para a plicação acabou uffaa… Pelo que entendi ele pega todas as library que o projeto irá precisar pra funcionar… caramba.. que maravilha.

  25. Leonardo 10/08/2015 at 17:52 #

    Olá Lucas, parabéns pelo post. Sucinto e objetivo.
    Porderia me auxiliar numa dúvida: Possuo um projeto não maven e um projeto maven. Como faço para utilizar meu projeto não maven no meu projeto maven? Utilizo Eclipse como IDE
    Anteriormente não trabalhava com maven e quando precisava fazer isto simplesmente adicionava um projeto dentro do outro no Java Build Path, aba Projects. E como maven, pra importar um projeto não maven em um maven, como fica?

    Abraços!

  26. Divino Junior 25/08/2016 at 02:33 #

    Parabéns pelo post.

Deixe uma resposta