Sobre esse Tutorial

Néki Technologies.

Agradecimentos ao Néki Team!

Introdução

"The intent of Maven is to make intra-project development highly manageable in the hopes of providing more time for cross-project development. You might call it cross-project pollination or the sharing of project development knowledge; this is what Maven attempts to encourage" (Jason van Zyl)

Com cadeira cativa em quase todos os projetos J2EE, a ferramenta de build ANT - que substitui ferramentas tradicionais como make, gnumake, nmake e jam - tornou-se de fato um padrão para a construção de aplicações Java.

Originalmente parte do código base do TomCat, tornou-se independente, tendo sua primeira release gerada em Julho de 2000. Totalmente escrita em Java, multi-plataforma, utiliza-se de um script escrito em XML, denominado build file, para descrever as tarefas que deverão ser realizadas para o projeto, como por exemplo, compilação, empacotamento (jar, war e ear), deployment, javadocs, integração com frameworks de teste, controladores de versão, entre outros. Porém, apesar de incontestável sua utilização, o ANT deixa a desejar quando se trata de gerenciamento do projeto como um todo. Examinando um script de build, fica impossível sabermos quais são as dependências do projeto, seus responsáveis, versão, entre outras meta-informações do projeto.

Maven vai além! Baseando-se no conceito de um Project Object Model (POM), todos os artefatos produzidos pelo Maven são resultantes de um modelo bem definido para o seu projeto. Em poucas linhas de descrição do projeto, pode-se facilmente realizar algumas tarefas padrão - compilação, empacotamento (jar, war, ear), deployment, entre outras - sem que seja necessária a criação e/ou customização de scripts de build. Essa facilidade faz com que essa ferramenta seja cada vez mais incorporada não só aos projetos da Jakarta, mas também aos projetos corporativos.

Bastante flexível, o ANT permite executar uma infinidade de tarefas para o projeto, porém pagasse um preço razoavelmente alto no desenvolvimento de uma quantidade significativa de linhas de código para a criação de scripts. Já com o Maven, despendesse um esforço na descrição do projeto, no entanto com a utilização de plug-ins, todo o "trabalho sujo" que deveria ser programado através de scripts, não será mais necessário. A restrição imposta pelo Maven para que você não precise programar scripts complexos, é a de gerar um artefato por projeto (entende-se projeto aquela pasta que contém o project.xml). Então, não poderemos gerar um EAR (Enterprise ARchieve) de um projeto, certo? A resposta é: errado! Um projeto pode conter subprojetos, que por sua vez geram seu artefato - jar e war. Como veremos adiante, o projeto principal ficará encarregado de juntar essas peças e colocá-las dentro de um EAR. Claro que todo esse trabalho é facilitado, através de plug-ins e herança.

Quem já trabalhou em projetos corporativos utilizando o ANT, sabe o quão complexo se torna gerir todos os scripts criados, além é claro, da quantidade de scripts que realizam tarefas similares ou muitas vezes idênticas, construídos quase sempre através do famoso "Crtl+C, Crtl+V". O fato é que precisamos executar atividades que são de uma certa forma padrão, ou seja, precisamos compilar e empacotar classes, compartilhar bibliotecas, recursos, remover diretórios, arquivos, entre outros.

O problema começa a ficar mais sério quando se perde o controle sobre quais são as dependências internas e externas - versões dos frameworks externos e módulos internos utilizados no projeto -, quando não existe nenhum procedimento de medição e análise de dados quantitativos para se obter informações objetivas quanto à qualidade do produto em construção, possibilitando um controle preciso da evolução do projeto e principalmente quando o desenvolver balbucia aquela celebre frase: "mas isso funcionava na minha máquina!".

Instalação e Configuração

Atualmente o Maven é distribuído em vários formatos: um arquivo de instalação tar/gzipped, zip, exe, entre outros. Iremos utilizar aqui a release candidate 1 do maven 1.0 (maven-1.0-rc1.zip). Siga os passos abaixo:

  1. Faça o download do arquivo maven-1.0-rc1.zip (veja links);
  2. Crie a variável de ambiente MAVEN_HOME apontando para o diretório aonde maven foi descompactado;
  3. Adicione a pasta $MAVEN_HOME/bin no seu PATH

Obs: Tenha certeza que o Java está instalado corretamente e a variável JAVA_HOME setada.

Para ter certeza de que tudo foi instalado corretamente, vá até ao prompt de comando e digite maven -v. Se você vir o que segue abaixo, significa que a instalação foi um sucesso.

 __  __
|  \/  |__ Jakarta _ ___
| |\/| / _ \ V / -_) ' \  ~ intelligent projects ~
|_|  |_\__,_|\_/\___|_||_|   v. 1.0-rc1-SNAPSHOT

Exemplo de utilização

Criando um projeto simples com o Maven Application Generator Plug-in

Uma boa forma de automatizar o processo de criação de um novo projeto utilizando o Maven é através do genapp plug-in (Maven Application Generator Plug-in - http://maven.apache.org/reference/plugins/genapp/index.html).

No prompt de comando, vá até um diretório aonde o projeto de exemplo possa ser criado e digite: maven -Dmaven.genapp.template.package=br.com.neki genapp. ENTER para as demais opções.

Abaixo segue o output gerado pelo comando:

 __  __
|  \/  |__ Jakarta _ ___
| |\/| / _ \ V / -_) ' \  ~ intelligent projects ~
|_|  |_\__,_|\_/\___|_||_|   v. 1.0-rc1-SNAPSHOT


Enter a project template to use: [default]
Please specify an id for your application: [app]
Please specify a name for your application: [Example Application]     
[copy] Copying 1 file to <diretório do projeto>\src\java\com\neki     
[copy] Copying 3 files to <diretório do projeto>\src\test\com\neki     
[copy] Copying 1 file to <diretório do projeto>     
[copy] Copying 2 files to <diretório do projeto>

BUILD SUCCESSFUL
Total time: 5 seconds

Listagem 1 - Output de criação do projeto utilizando o Maven Application Generator Plugin

No final será criada uma estrutura como a que segue abaixo:



Figura 1 - Organização de um projeto simples utilizando o Maven

Conceitos Básicos

Antes de executar os comandos básicos, serão apresentados alguns conceitos importantes utilizados pelo Maven. O principal deles é o projeto. No "mundo Maven" significa dizer: qualquer diretório que contenha um project.xml é um projeto e se esse, por sua vez, contiver sub-diretórios que possuam seu project.xml, eles também serão considerados projetos.

O repositório remoto, que dentre outras coisas, elimina completamente a necessidade de armazenamento de arquivos jars no CVS, é um outro conceito importante. Através da análise das dependências descritas para o projeto, o Maven irá se encarregar de efetuar automaticamente o download dos artefatos de um ou mais repositórios remotos. Quando trazidos, eles serão armazenados no repositório local, criado em um diretório chamado ".maven/repository", que quando não especificada sua localização, ficará no ${user.home}. Em uma máquina Windows isso seria o equivalente a C:\Documents And Settings\${nome_do_usuário}.

Abaixo segue a esquematização do processo:



Figura 2 - Esquematização do processo de build do Maven

É importante salientar que na seqüência serão apresentados em detalhes os elementos descritos acima, formas de configurar a localização dos repositórios e como descrever as dependências do projeto.

Comandos Básicos

Para executar alguns comandos básicos em cima do projeto criado, vá até o prompt de comando na raiz do projeto exemplo.

Abaixo, segue um quadro explicativo com alguns comandos simples que poderão ser executados:

ComandoDescrição
maven java:compileCompila o código fonte do projeto. O diretório dos arquivos fontes é definido através da target build do project.xml.
maven jar:jarCria um arquivo jar para o projeto no diretório de build do Maven, no formato ${project.id}-${project.currentVersion}.jar, onde o id e a currentVersion são definidos no project.xml
maven site:generateGera um site com a documentação do projeto: jdepend, javadoc, checkstyle, junit-report, tasklist, xdoc, changelog entre outros. Por default, o site do projeto será criado no diretório: ${diretório do projeto}/target/docs.
maven cleanRemove os diretórios criados pelo Maven no processo de build.
maven -g//TODO
Tabela 1 - Comandos básicos do Maven

Nota Importante: Antes de você brigar comigo, é bom avisar que na primeira vez que formos executar o Maven, ele irá baixar da net (repositório remoto) uma série de jars e plugins necessários a sua execução. Portanto, não fique irritado com isso, pois é só na primeira vez. Tome um pouquinho de café, vai dar uma voltinha e em seguida continue a sua leitura.

Abaixo segue um exemplo de execução do comando maven jar:jar:

 __  __
|  \/  |__ Jakarta _ ___
| |\/| / _ \ V / -_) ' \  ~ intelligent projects ~
|_|  |_\__,_|\_/\___|_||_|   v. 1.0-rc1-SNAPSHOT

Attempting to download maven-SNAPSHOT.jar.
Overriding previous definition of reference to clover.classpath

java:prepare-filesystem:java:compile:    
	[echo] Compiling to <diretório do projeto>/target/classes
	
java:jar-resources:
Copying 1 file to <diretório do projeto>\target\classes

test:prepare-filesystem:    
	[mkdir] Created dir: <diretório do projeto>\target\test-classes    
	[mkdir] Created dir: <diretório do projeto>\target\test-reports

test:test-resources:

test:compile:    
	[javac] Compiling 3 source files to <diretório do projeto>\target\test-classes

test:test:    
	[junit] dir attribute ignored if running in the same VM    
	[junit] Running com.neki.AppTest    
	[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.05 sec

jar:jar:    
	[jar] Building jar: <diretório do projeto>\target\app-1.0.jar

BUILD SUCCESSFUL
Total time: 18 seconds

Listagem 2 - Output de execução da goal jar do Maven JAR Plugin

PROJECT OBJECT MODEL (POM)

Materializado pelo arquivo project.xml, pode-se entender por POM (Project Object Model), o local onde serão definidas todas as informações acerca do projeto. Suas dependências, relatórios que deverão ser gerados, informações gerenciais e localização dos arquivos fontes do projeto, são alguns dados que estarão contidos nesse arquivo.

Uma divisão bastante interessante e didática pode ser feita quando se trata de explicar o POM. Podemos dividi-lo em quatro grandes seções: gerenciamento, dependências, construção e relatórios do projeto.

Utilizaremos como exemplo o project.xml do projeto gerado pelo Maven Application Generator Plug-in, apresentado acima. Os itens que aparecem em negrito são obrigatórios.

01 <?xml version="1.0" encoding="ISO-8859-1"?>
02 <project>
03
04   <pomVersion>3</pomVersion>
05   <id>app</id>
06   <currentVersion>1.0</currentVersion>
07   <name>Example Application</name>
08
09   <!-- A Seção de Gerenciamento do Projeto entrará aqui -->
10
11   <!-- A Seção de Dependências do Projeto entrará aqui -->
12   
13   <!-- A Seção de Construção do Projeto entrará aqui -->
14   
15   <!-- A Seção de Relatórios do Projeto entrará aqui -->
16
17 </project>

Listagem 3 - Exemplo de um Project Object Model (POM)

A linha 04, apesar de não ser diretamente utilizada, descreve a versão do POM e é obrigatória. As linhas 05 e 06 definirão o nome do artefato que será armazenado no repositório local no momento da instalação do projeto ("${pomId}-${pomCurrentVersion}.jar"), no caso acima: app-1.0.jar. A linha 07 representa o nome dado ao projeto.

Na Seção de Gerenciamento do Projeto, que será apresentada em detalhes abaixo, poderão estar descritas algumas informações importantes, tais como: detalhes da organização detentora do produto, data da criação, descrição, pacote, logotipo, lista de discussão, equipe, entre outras informações que também irão fazer parte do web site do projeto criado pelo Maven. Ainda nesse tutorial, será apresentada uma maneira da organização ter um projeto-base que servirá como um template para que algumas informações não precisem ser reescritas a cada módulo, ou seja, uma forma de herdar o POM. O único elemento obrigatório é o nome da organização, como segue abaixo:

01  <organization>
02    <name>Apache Software Foundation</name>
03    <url>http://www.apache.org/</url>
04    <logo>http://maven.apache.org/images/jakarta-logo-blue.gif</logo>
05  </organization>
06  
07  <inceptionYear>2002</inceptionYear>
08  <package>com.neki</package>
09  <logo>http://maven.apache.org/images/maven.jpg</logo>
10  <description>...</description>
11  <shortDescription>...</shortDescription>
12  <url>http://maven.apache.org/reference/plugins/examples/</url>
13  <issueTrackingUrl>
14     http://nagoya.apache.org/scarab/servlet/scarab/
15  </issueTrackingUrl>
16  <siteAddress>jakarta.apache.org</siteAddress>
17  <siteDirectory>
18      /www/maven.apache.org/reference/plugins/examples/
19  </siteDirectory>
20  <distributionDirectory>
21      /www/maven.apache.org/builds/
22  </distributionDirectory>
23
24  <repository>
25    <connection>
26scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:maven/src/plugins-
27build/examples
28    </connection>
29    <url>
30       http://cvs.apache.org/viewcvs/maven/src/plugins- build/examples/
31    </url>
32  </repository>
33
34   <mailingLists>                                              
35      <mailingList>                                            
36         <name>Maven User List</name>                                  
37         <subscribe>users-subscribe@maven.apache.org</subscribe>           
38         <unsubscribe>users-unsubscribe@maven.apache.org</unsubscribe>            
39      </mailingList>                                            
40      ...                                                      
41      ...                                                       
42   </mailingLists>                                              
43
44   <developers>                                                
45      <developer>                                              
46         <name>Fabiano Cruz</name>                             
47         <id>fabianocruz</id>                                       
48         <email>fabiano.cruz@neki-technologies.com.br</email>                     
49      </developer>                                             
50  <developers/>
Listagem 4 - Seção de Gerenciamento do Projeto no POM

  • Linhas 01 a 05 - informações da organização;
  • Linha 07 - data de criação do projeto;
  • Linha 08 - pacote principal do projeto;
  • Linha 09 - logotipo do projeto;
  • Linha 10 - uma descrição um pouco mais detalhada a respeito do projeto;
  • Linha 11 - uma descrição sucinta do projeto;
  • Linha 12 - web site do projeto;
  • Linhas 13 a 15 - localização da ferramenta de controle das atividades do projeto - requisitos, alterações, pendências, bugs etc;
  • Linha 16 - site onde o projeto está hospedado;
  • Linhas 17 a 19 - diretório de publicação do site do projeto;
  • Linhas 20 a 22 - diretório de distribuição do artefato gerado pelo projeto;
  • Linhas 24 a 32 - informações a respeito do controle de versão;
  • Linhas 34 a 42 - lista de discussão utilizada para debates a respeito do projeto;
  • Linhas 44 a 50 - informações a respeito da equipe envolvida com o projeto.

A Seção de Construção do Projeto geralmente é definida no projeto-base e nela serão colocadas as informações relevantes à compilação e execução dos testes para o projeto. Nenhum item dessa seção é obrigatório, porém, a não definição fará com que o Maven ignore a existência de código fonte e testes no projeto. Uma vez definidas as informações dessa seção, o Maven irá compilar os arquivos Java e quando terminado, irá rodar os testes automaticamente.

01  <build>
02    <nagEmailAddress>
03       turbine-maven-dev@jakarta.apache.org
04    </nagEmailAddress>
05    <sourceDirectory>src/java</sourceDirectory>
06    <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
07
08    <unitTest>
09      <includes>
10        <include>**/*Test.java</include>
11      </includes>
12      <excludes>
13        <exclude>**/NaughtyTest.java</exclude>
14      </excludes>
15    </unitTest>
16
17    <resources>
18      <resource>
19        <directory>src/conf</directory>
20        <includes>
21          <include>*.properties</include>
22        </includes>
23      </resource>
24    </resources>
25  </build>
Listagem 5 - Seção de Construção do Projeto no POM

  • Linhas 02 a 04 - Endereço de e-mail para o envio de notificações a respeito do status da construção da aplicação;
  • Linha 05 - Diretório contendo os arquivos fontes do projeto. Os arquivos fontes poderão ser arquivos Java, JSP etc;
  • Linha 06 - Diretório contendo os testes unitários do projeto;
  • Linhas 09 a 11 - Nome padrão para os arquivos que deverão ser incluídos na execução dos testes, quando no término da compilação do projeto;
  • Linhas 12 a 14 - Arquivos que deverão ser excluídos dos testes
  • Linhas 18 a 24 - Arquivos que deverão ser adicionados ao artefato criado - jar e war.

As Seções de Dependências e Relatórios não são criadas pelo plug-in (Maven Application Generator Plug-in), portanto, os exemplos apresentados abaixo não estão no project.xml do projeto exemplo.

Pode-se dizer que a Seção de Dependências do Projeto é umas das mais importantes dentro do POM, pois nela estarão descritas todas as dependências necessárias à compilação e execução do projeto. Uma vez descritas as dependências, o Maven irá procura-las no repositório local e quando não encontradas, elas serão automaticamente baixadas.

01 <dependencies>
02	  <dependency>
03		<groupId>log4j</groupId>
04		<artifactId>log4j</artifactId>
05		<version>1.2.8</version>
06		<type>jar</type>
07	  </dependency>
08	  <dependency>
09		<groupId>maven</groupId>
10		<artifactId>maven-findbugs-plugin</artifactId>
11		<version>SNAPSHOT</version>
12		<type>plugin</type>
13	  </dependency>
14 </dependencies>
Listagem 6 - Seção de Dependências do Projeto no POM

  • Linha 03 - Diretório onde está o artefato (jar) descrito na seqüência;
  • Linhas 04, 05 e 06 - Juntas irão descrever o nome, a versão e o tipo de artefato requerido. No nosso caso, o arquivo: log4j-1.2.8.jar. Quando não especificada a tag type, será utilizado por default o arquivo do tipo jar, porém os tipos ejb, plugin, war, ear e tld também são suportados.
  • Linha 11 - Quando na tag version é colocada a palavra SNAPSHOT, significa que o Maven sempre irá buscar a última versão daquele artefato. Deve-se ter cuidado quando se estiver trabalhando off-line, pois você poderá estar com uma versão desatualizada no seu repositório local.

Na Seção de Relatórios do Projeto estarão descritos os diferentes tipos de relatórios a serem gerados assim que o processo de build é terminado. Esses relatórios estarão concentrados no site do projeto criado pelo Maven. Eles são uma ferramenta de apoio bastante eficiente na implantação de um processo de qualidade na organização, dada a riqueza das informações geradas. Não se preocupe com os detalhes dessa seção. Mais na frente serão apresentados alguns dos plug-ins descritos abaixo:

01 <reports>
02    <report>maven-jdepend-plugin</report>
03    <report>maven-pmd-plugin</report>
04    <report>maven-checkstyle-plugin</report>
05    <report>maven-simian-plugin</report>
06    <report>maven-findbugs-plugin</report>
07    <report>maven-changes-plugin</report>
08    <report>maven-changelog-plugin</report>
09    <report>maven-file-activity-plugin</report>
10    <report>maven-developer-activity-plugin</report>
11    <report>maven-jxr-plugin</report>
12    <report>maven-junit-report-plugin</report>
13    <report>maven-jcoverage-plugin</report>
14    <report>maven-clover-plugin</report>
15    <report>maven-tasklist-plugin</report>
16    <report>maven-javadoc-plugin</report>
17    <report>maven-faq-plugin</report>
18 </reports>
Listagem 7 - Seção de Relatórios do Projeto no POM

Processamento do POM

Processado como um script Jelly, o já familiar POM poderá dentre outras coisas, ser estendido e/ou conter trechos programados. Na verdade, na grande maioria das vezes, não precisaremos nos preocupar como funcionam scripts em Jelly, porém teremos o poder de trabalhar com estruturas condicionais, de repetição, sobrescrever propriedades etc.

Abaixo, segue um exemplo:

<?xml version="1.0" encoding="ISO-8859-1"?>
<project>  
	<pomVersion>3</pomVersion>  
	<id>maven</id>  
	<name>Maven</name>  
	<currentVersion>1.0-b5-dev</currentVersion>  
	<organization>    
		<name>Apache Software Foundation</name>    
		<url>http://jakarta.apache.org/</url>    
		<logo>/images/jakarta-logo-blue.gif</logo>  
	</organization>  
	<inceptionYear>2001</inceptionYear>  
	<package>org.apache.${pom.artifactId}</package>  
	<logo>/images/${pom.artifactId}.jpg</logo>  
	<description>    Maven is a project that was created in ${pom.inceptionYear}.  </description>  
	<shortDescription>    ${pom.name} is a Java Project Management Tool  </shortDescription>
</project>
Listagem 8 - Exemplo de utilização de scripts em Jelly

As partes em negrito serão substituídas pelos valores descritos no POM.

Herdando um POM

Abaixo, segue um exemplo de herança:

<?xml version="1.0" encoding="ISO-8859-1"?>  
<project>    
	<extend>project.xml</extend>    
	<id>super-extendo</id>    
	<name>Super Extendo</name>    
	<build>      
		<unitTest>        
			<includes>          
				<include>**/*Test*.java</include>        
			</includes>        
			<excludes>          
				<exclude>**/TestAll.java</exclude>          
				<exclude>**/*Abstract*.java</exclude>        
			</excludes>      
		</unitTest>    
	</build>  
</project>
Listagem 9 - Exemplo de herança de um POM

PLUG-INS

Essa é a essência do Maven! São eles, os PLUG-INS, os grandes responsáveis pelo sucesso dessa ferramenta. Dedicados a trabalhos específicos - compilação, execução de testes, criação de jar etc -, os PLUG-INS são extremamente poderosos e simples de serem desenvolvidos, quando necessário.

maven.xml

Esse é um arquivo 'especial' lido pelo Maven durante o processamento. Aqui, você poderá sobrescrever goals e/ou criar um procedimento especial para o seu projeto - copiar coisas, invocar outras goals, criar uma goal, entre outros.

Maven utiliza scripts escritos em uma linguagem denominada: Jelly ( http://jakarta.apache.org/commons/sandbox/jelly/), portanto, qualquer tag Jelly, válida, poderá ser colocada dentro de um arquivo maven.xml.

Exemplo

Nota: Abaixo, apresentaremos um exemplo ilustrativo, pois o Maven não define a goal 'compile' como default.

Um exemplo de maven.xml:

01 <project
02   default="nightly-build"
03   xmlns:j="jelly:core"
04   xmlns:u="jelly:util">
05
06   <goal name="nightly-build">
07     <!-- Any ant task, or jelly tags can go here thanks to jeez -->
08     <j:set var="goals" value="compile,test" />
09     <mkdir dir="${maven.build.dir}" />
10     <u:tokenize var="goals" delim=",">${goals}</u:tokenize>
11     <j:forEach items="${goals}" var="goal" indexVar="goalNumber">
12       Now attaining goal number ${goalNumber}, which is ${goal}
13       <attainGoal name="${goal}" />
14     </j:forEach>
15   </goal>
16 </project>
Listagem 10 - Exemplo de um arquivo maven.xml

  • Linha 01 - elemento principal de todos os arquivos maven.xml;
  • Linha 02 - o atributo default (default="nightly-build") definirá a goal que será executada quando nenhum parâmetro for passado pelo maven, ou seja, simplesmente executando maven na linha de comando;
  • Linha 03 - seguindo, temos as declarações de alguns XML namespaces, por exemplo: xmlns:j="jelly:core", que diz ao Jelly que todos os elementos XML prefixados com j: são parte de uma tag library predefinida, registrada com o identificador core dentro do Jelly;
  • Linha 04 - xmlns:u="jelly:util", que diz ao Jelly que todos os elementos XML prefixados com u: são parte de uma tag library predefinida, registrada com o identificador util dentro do Jelly;

    Nota:
    1. Qualquer tag library Jelly que você queira utilizar dentro do maven.xml deverá estar declarada no elemento project e ter um namespace definido.
    2. O Maven já mantém pré-registrado a tag library jeez com um prefixo vazio. Essa tag agrupa as tag libraries Ant e werkz dentro de um namespace. Isso permite, que o Maven utilize qualquer tag Ant ou werkz sem precisar definir um namespace, fazendo com que o processo de migração de qualquer fragmento de script Ant, seja bastante simples.


  • Linha 06 - Similar as targets do Ant, as goals do Maven irão agrupar uma série de atividades a serem executadas. Dentro delas, poderemos colocar qualquer tag Ant. Para executar uma goal definida no maven.xml, basta passar o nome da goal parâmetro para o Maven na linha de comando. Por exemplo, para executar a goal 'nightly-build', definida no nosso exemplo, basta digitar:

    > maven nightly-build
    
    Nota:
    1. Os plug-ins escritos para o Maven, sempre colocam como prefixo da goal o seu próprio nome, sendo fácil identificá-lo. Por exemplo: jar:jar, a goal jar definida pelo plug-in para criar um arquivo jar para o seu projeto


  • Linha 08 - Dentro de cada goal, poderemos ter qualquer tag Jelly ou Ant, como apresentado em Nota acima. No nosso exemplo: <j:set var="goals" value="compile,test"/> , utilizando o namespace j:, definido elemento project, invocaremos a função set da tag library core do Jelly. Essa função irá setar a variável, cujo nome está definido no atributo var, com o valor colocado no atributo value.
  • Linha 09 - <mkdir dir="${maven.build.dir}"/>, irá executar task mkdir do Ant, criando o diretório especificado pela variável ${maven.build.dir}.
  • Linha 10 - <u:tokenize var="goals" delim=",">${goals}</u:tokenize>, utilizando o namespace u:, definido no elemento project, invocaremos a função tokenize da tag library util do Jelly. Atributos:

    1. O Atributo var será setado com o valor na nova lista;
    2. O atributo delim é o delimitador utilizado para separar os itens da string;
    3. No corpo da tag tokenize, encontramos a variável goals, setada algumas linhas acima, que contém compile e test separados por vírgula.
  • Linha 11 a 14 - Aqui temos a função forEach: <j:forEach items="${goals}" var="goal" indexVar="goalNumber">, que irá facilitar a vida quando o assunto é estrutura de repetição. Atributos:

    1. O atributo items é uma expressão que irá conter a coleção a ser iterada;
    2. O atributo var especificará o nome da variável que receberá cada item da coleção durante o processamento
    3. O atributo indexVar conterá o nome da variável que irá receber o contador com o número de elementos a serem processados (zero-based).


    Dentro da função, temos o output de um texto que irá informar o nome da goal e o número a ser processado e invocará a goal, utilizando a tag werkz: attainGoal.

Customizando o Maven através do maven.xml

Até agora, vimos como compilar classes Java utilizando o Maven e também criar arquivos jars. Vimos também, que através do arquivo maven.xml, residente na mesma pasta do arquivo project.xml, podemos customizar as ações do Maven. Veremos agora, como definir, além de goals, pre e post goals.

01 <project default="foobar-dist" xmlns:m="jelly:maven">
02 
03   <preGoal name="java:compile">
04     <attainGoal name="xdoclet:webdoclet"/>
05   </preGoal>
06 
07   <goal name="foobar-dist">
08     <attainGoal name="war:install" />
09   </goal>
10
11   <postGoal name="war:war">
12     <mkdir dir="${test.result.dir}"/>
13     <echo>Creating directories</echo>
14   </postGoal>
15
16 </project>
Listagem 11 - Exemplo de um arquivo maven.xml, com pre e pos goals

Acima, colocamos um exemplo de maven.xml. Repare a goal default do projeto, aqui definida como: foobar-dist. A goal foobar-dist é simplesmente um wrapper para uma outra goal denominada war:install. A goal "install" do Maven WAR Plug-in, cria um war e publica-o dentro do repositório. A instrução "attainGoal" irá executar a goal descrita no atributo name.

O elemento preGoal instrui o Maven a executar as tarefas definidas dentro dele, antes de executar a goal especificada no nome do atributo. Isso pode gerar alguma confusão às vezes. Note que a preGoal (java:compile) é diferente da goal default (foobar-dist). A goal default para esse projeto, instala o arquivo war. Entretanto, o WAR Plug-in precisa compilar arquivos Java antes de criar o arquivo WAR. A preGoal especificada está muito mais ligada a goal java:compile, do que a goal foobar-dist. Nesse caso, a preGoal irá executar um Maven Xdoclet Plug-in.

Um postGoal pode ser especificado para qualquer goal implícita que seja parte da goal default ou a própria. No exemplo, a postGoal é especificada para a goal war:war, que é executada antes da goal war:install. A postGoal especifica que um dado diretório deve ser criado depois de construído o WAR.

MAVEN SETUP

Os arquivos de propriedade utilizados pelo Maven são processados segundo a seguinte ordem:

  • ${project.home}/project.properties
  • ${project.home}/build.properties
  • ${user.home}/build.properties

Onde a última definição vence. Portanto, o Maven utiliza essa seqüência de arquivos de propriedades para sobrescrever qualquer propriedade definida anteriormente, pela nova propriedade, segundo essa ordem. Nessa seqüência, o arquivo: ${user.home}/build.properties, tem a palavra final na lista de arquivos de propriedades processados.

No mais, as propriedades de sistema serão processadas após a seqüência de arquivos, apresentados acima. Portanto, as propriedades especificadas via CLI (commandline), utilizando a convenção: -Dproperty=value, irão sobrescrever qualquer propriedade definida anteriormente.

Plug-in Properties

Os Plug-ins são carregados depois de processada a seqüência de propriedades definidas acima, porém, o PluginManager foi programado para não sobrescrever os valores que tiverem sido previamente setados. Isso funciona de forma oposta ao processamento normal das propriedades do Maven, uma vez que os Plug-ins só poderão ser carregados depois que o kernel do Maven for inicializado. Seria algo do tipo:

  • As propriedades default do Plug-in são processadas
  • ${project.home}/project.properties são processadas
  • ${project.home}/build.properties são processadas
  • ${user.home}/build.properties são processadas

Então, uma vez que os Plug-ins são processados tardiamente no ciclo de inicialização, você poderá sobrescrever qualquer propriedade default definida pelo plug-in. Por exemplo, o plug-in CheckStyle define a propriedade default, que segue abaixo:

maven.checkstyle.format = sun

Aqui, o plug-in CheckStyle, recebe a instrução de utilizar a convenção de código definida pela SUN, como formato default. Mas, você poderá sobrescrever esse valor em qualquer um dos arquivos de propriedades, descritos acima. Portanto, se você colocar o trecho, que segue abaixo, no arquivo: ${project.home}/project.properties, o plug-in CheckStyle passará a utilizar a convenção de código definida pelo Turbine.

maven.checkstyle.format = turbine

Behavioral Properties

Abaixo, a tabela apresenta a lista de propriedades que altera a forma com que o Maven trabalha:

PropriedadeDescriçãoValor Default
maven.build.destDiretório para aonde as classes geradas irá.${maven.build.dir}/classes
maven.build.dir Diretório para aonde os outputs gerados, por exemplo: arquivos .class, documentação relatórios de testes unitários etc, irá.

CUIDADO: Alterar o valor default da propriedade maven.build.dir, no seu ${user.home}/build.properties, pode permitir algum controle sobre a estrutura de diretório do projeto. Porém, essa prática interferirá com o bootstrap do Maven a partir do código fonte, uma vez que ele espera que o jar criado para o projeto esteja em: ${basedir}/target/.
${basedir}/target/
maven.build.src Diretório para aonde arquivos fontes gerados irá.${maven.build.dir}/src
maven.conf.dir O diretório que armazena os arquivos de configuração.${basedir}/conf
maven.docs.dest O diretório de output dos html´s gerados dos relatórios.${maven.build.dir}/docs
maven.docs.omitXmlDeclaration Se a documentação gerada deve conter uma declaração xml, por exemplo:

<?xml version="1.0"?>
false
maven.docs.outputencodingO character enconding da documentação gerada. ISO-8859-1
maven.docs.srcO diretório que contém a documentação fornecida pelo usuário. ${basedir}/xdocs
maven.gen.docs O diretório aonde os xdocs, que precisam ser transformados em html, são colocados. ${maven.build.dir}/generated-xdocs
maven.home.local O diretório na máquina local utilizado pelo Maven para escrever detalhes específicos do usuário, como por exemplo: informações expandidas de plug-ins e cache. ${user.home}/.maven
maven.mode.onlineSe você está conectado a internet ou não.true
maven.plugin.dirOnde o Maven pode encontrar os plug-ins.${maven.home}/plugins
maven.plugin.unpacked.dirOnde o Maven irá expandir os plug-ins a serem instalados para o processamento.${maven.home.local}/plugins
maven.repo.central Esse é o host que o Maven irá utilizar para fazer o deploy da distribuição, durante um dist:deploy. login.ibiblio.org
maven.repo.central.directory Esse é o diretório que o Maven irá copiar a distribuição, durante um dist:deploy. /public/html/maven
maven.repo.local O repositório na máquina local, que o Maven irá utilizar para armazenar os artefatos baixados (jars etc). ${maven.home.local}/repository
maven.repo.remote O repositório que o Maven irá utilizar para baixar os artefatos (jars etc), que não forem encontrados na máquina local. http://www.ibiblio.org/maven
maven.repo.remote.enabled Se o repositório remoto deve ou não ser utilizado. true
maven.scp.executableO executável utilizado para cópias seguras. scp
maven.src.dirO diretório base para o arquivos fontes. ${basedir}/src
maven.ssh.executable O executável utilizado para executar comandos remotamente. scp
Tabela 2 - Propriedade do Maven

Utilizando Proxies

Se você estiver atrás de um proxy, o Maven irá obedecer as seguintes propriedades:

PropriedadeDescrição
maven.proxy.hostO endereço IP do seu proxy.
maven.proxy.portO número da porta do seu proxy.
maven.proxy.usernameNome do usuário, caso o seu proxy requeira autenticação.
maven.proxy.passwordSenha, caso o seu proxy requeira autenticação.
Tabela 3 - Propriedade do Maven utilizando Proxies

Se você precisa utilizar um proxy, o lugar mais apropriado para setar os valores dessas propriedades será no seu arquivo: ${user.home}/build.properties. Abaixo, segue um exemplo:

## ----------------------------------------------------------
## ${user.home}/build.properties
## ----------------------------------------------------------
maven.proxy.host = meu.servidorproxy.com.br
maven.proxy.port = 8080
maven.proxy.username = nomedousuario
maven.proxy.password = senha

Utilizando Múltiplos Repositórios Remotos

Você poderá especificar o uso de múltiplos repositórios remotos em qualquer um dos arquivos de propriedades processados pelo Maven, simplesmente, fazendo algo como o que segue abaixo:

maven.repo.remote = http://www.ibiblio.org/maven/,http://www.meusite.com.br/maven/

REMOTE REPOSITORY LAYOUT

O objetivo dessa seção é apresentar o layout do repositório remoto do Maven. Atualmente, o repositório principal está hospedado no Ibiblio (http://www.ibiblio.org/maven/), mas você poderá utilizar os seus repositórios remotos, desde que estejam de acordo com a estrutura apresentada nesse documento.

Todo projeto tem o seu próprio diretório no repositório, onde os artefatos para o projeto poderão ser armazenados. Cada projeto tem um id único e um diretório onde o mesmo, irá armazenar seus artefatos nomeados após o id do projeto.

Dentro do diretório de um projeto, vários tipos de artefatos podem ser armazenados. Atualmente, os dois tipos de artefatos mais comuns são JARs e distributions. Abaixo, segue a esquematização de um repositório:

Repository	
	|-- seuprojeto
	|	|-- ears	
	|	|	`-- nomedoear-0.9-beta.ear	
	|	|-- ejbs	
	|	|	`-- nomedoejb-0.8-dev.jar	
	|	|-- jars	
	|	|	|-- nomedojar-0.2-b1.jar	
	|	|	|-- nomedooutrojar-1.2.jar	
	|	|	|-- nomedemaisumjar-1.0-dev.jar	
	|	|	`-- outrojarqualquer-1.0-dev.jar	
	|	`-- wars	
	|		`-- nomedomoduloweb-1.1.war	
	|-- ojb
	|	`-- jars	
	|		`-- ojb-1.0.rc4.jar
	|
	`-- servletapi			
		`-- jars	
			|-- servletapi-2.2.jar			
			`-- servletapi-2.3.jar		
Listagem 12 - Layout do Repositório Remoto

PROJETOS J2EE COM MAVEN - EXEMPLO

Nas seções acima, pudemos analisar o funcionamento básico do Maven. Abordamos alguns tópicos, como: configurações do POM, criação de um projeto simples, execução de algumas goals, plug-ins, maven.xml, entre outros. Porém, existem muito mais coisas para aprendermos no decorrer desse tutorial. Iremos agora, entender como o Maven trabalha com projetos J2EE, criação de WARs, EJB-JARs, JARs de dependência e por último, EARs. Porém, antes de qualquer coisa, iremos dar uma olhada em um outro conceito muito importante do Maven.

No Maven, um projeto poderá produzir um único artefato. O projeto mais externo poderá ter múltiplos sub-projetos e esses por sua vez, também poderão conter outros sub-projetos. Mas no final, cada um deles poderá produzir um único artefato. Isso faz bastante sentido, se você for considerar como os scripts do Ant são utilizados para criar múltiplos artefatos para um projeto -causando, quase sempre, uma confusão danada. Tipicamente, os projetos possuem uma árvore de arquivos fontes, monolítica, de onde todos os JARs de dependência, WARs e EARs são criados utilizando diferentes scripts de build. No final, a idéia de dividir a aplicação é perdida e as classes são criadas em diferentes pacotes sem considerar o mecanismo de classloader, fazendo com que fique bastante complicado manter os scripts atualizados. O Maven desencoraja essa prática. É claro que ele te dará a flexibilidade para sobrescrever essa prática. Mas como somos bastante obedientes e gostamos muito do Maven, iremos seguí-la no decorrer desse material. ;)

Projeto Agenda On-line

AgendaOnline	
	|- conf				- Diretório contendo alguns arquivos de configuração	
	|- maven.xml		- Utiliza o Maven Multiproject Plug-in	
	|- project.xml		- Template de definitpo do Projeto Master	
	|- AgendaWeb		- Sub-projeto que irá produzir o agenda-web.war	
	|	|- maven.xml	- Define as goals para o sub-projeto AgendaWeb	
	|	`- project.xml	- Definições do projeto AgendaWeb. Estende as definições do 
	|					  Projeto Master   
	|                         
	|- AgendaEAR		- Sub-projeto que irá produzir o agenda-online.ear	
	|	`- maven.xml	- Define as goals para o sub-projeto AgendaEAR	
	|	`- project.xml	- Definições do projeto AgendaEAR. Estende as definições do
	|					  Projeto Master	
	|
	|- AgendaEjb		- Sub-projeto que irá produzir o agenda-ejb.jar, um arquivo ejb jar
	|	|- maven.xml	- Define as goals para o sub-projeto AgendaEjb	
	|	`- project.xml	- Definições do projeto AgendaEjb. Estende as definições do
	|					  Projeto Master	
	|
	`- AgendaServices		- Sub-projeto que irá produzir o agenda-services.jar		
		|- maven.xml	- Define as goals para o sub-projeto AgendaServices		
		`- project.xml	- Definição das dependencias. Estende as definições do
						  Projeto Master	
Listagem 13 - Relacionamento entre os projetos da Agenda On-line

Agora, iremos utilizar o Maven em um projeto J2EE. O artefato J2EE mais comum gerado e publicado é o EAR. Os componentes que podem ser empacotados dentro de um arquivo EAR não estão diretamente correlacionados com os componentes contidos nos containers. Não há nenhuma exigência do que deve ser minimamente incluso dentro de um arquivo EAR. Um arquivo EAR é composto de qualquer número dos seguintes componentes:



Figura 3 - J2EE Application

Master Project

Na Agenda On-line iremos utilizar o template apresentado na Figura 1 - Organização de um projeto simples utilizando o Maven -, item 1.1.3 (Criando um projeto simples com o Maven Application Generator Plug-in) desse tutorial. Na Listagem 13 acima, apresentamos o relacionamento entre os projetos, assim como sua hierarquia. O Master Project é definido no nível mais alto dos projetos. Um resumo do template do projeto master é apresentado abaixo (Listagem 15), contendo somente os elementos essenciais. No item 2 desse tutorial, você pode ver na íntegra todos os elementos do POM. É importante observar que as dependências não estão descritas nesse template. Isso se deve ao fato de que o master project é um template para os sub-projetos estenderem. A Listagem 14 apresenta a estrutura do arquivo EAR gerado por esse projeto. Você encontrará uma organização semelhante entre o conteúdo do EAR e o projeto J2EE com Maven, apresentado na Listagem 13. Na maioria dos projetos J2EE não teremos um artefato de distribuição muito diferente do apresentado na Listagem 14. E quando desviarmos dessa rota usual, os scripts de build "out-of-the-box" do Maven, trabalharão para que tudo funcione.

agenda-online-1.0-dev.ear	
	|- application.xml	
	|- xerces-1.4.4.jar	
	|- log4j-1.2.8.jar	
	|- agenda-services-1.0-dev.jar - EJB e WAR possuem o agenda-services.jar 
	|								 no seu CLASSPATH	
	|- agenda-ejb-1.0-dev.jar				
	|	` META-INF	
	|		` MANIFEST.MF  		   - WAR manifest file possui o agenda-ejb.jar no  
	|								 seu CLASSPATH
	|	
	`- agenda-web-1.0-dev.war					
		` META-INF			
			` MANIFEST.MF
Listagem 14 - Estrutura do EAR no projeto Agenda On-line

<?xml version="1.0" encoding="ISO-8859-1"?>

<project>    
	<pomVersion>1</pomVersion>    
	<groupId>agenda-online</groupId>    
	<currentVersion>1.0-dev</currentVersion>    
	<name>Projeto Agenda Online</name>    

	<!-- ################################################################ -->    
	<!--        Seção de Gerenciamento do Projeto                         -->    
	<!-- ################################################################ -->    

	<organization>        
		<name>Néki Technologies</name>        
		<url>http://www.neki-technologies.com.br</url>        
		<logo>http://www.neki-technologies.com.br/imagens/logo_neki.gif</logo>    
	</organization>    
	<inceptionYear>2003</inceptionYear>    
	<package>br.com.neki.*</package>    
	<distributionDirectory>       
		${maven.repo.local}/${pom.groupId}/${pom.artifactId}/    
	</distributionDirectory>    

	<!-- ################################################################ -->    
	<!--        Seção de Dependências do Projeto                          -->    
	<!-- ################################################################ -->    

	<dependencies/>    

	<!-- ################################################################ -->    
	<!--        Seção de Construção do Projeto                            -->    
	<!-- ################################################################ -->    

	<build>        

		<nagEmailAddress>fabiano.cruz@neki-technologies.com.br</nagEmailAddress>        
		<sourceDirectory>${basedir}/src</sourceDirectory>       
		<unitTestSourceDirectory>${basedir}/test</unitTestSourceDirectory>        
		<unitTest>          
			<includes>            
				<include>**/Test*.java</include>          
			</includes>         
			<excludes>           
				<exclude>**/*Test*All.java</exclude>          
			</excludes>        
		</unitTest>        
		<resources/>  

		<!-- (OPTIONAL) Resources packaged inside the JAR file. -->    
	</build>    

	<!-- ################################################################ -->    
	<!--        Seção de Relatórios do Projeto                            -->   
	<!-- ################################################################ -->    

	<reports/>

</project>
Listagem 15 - Template de definição do Master Project

Construindo o JAR de Serviço (Java Module)

A Listagem 16 apresenta a definição do projeto de Serviço - um sub-projeto no Maven. Esse sub-projeto cria o arquivo agenda-services-1.0-dev.jar - uma biblioteca de dependência utilizada por ambos, ejb e camada web. Repare na tag extends a referência ao template do Master Project, apresentado na Listagem 15. Por ter estendido o pai, todas as propriedades serão herdadas. Ele irá definir os elementos dependency, indicando suas dependências na API J2EE (que não foram definidas no pai) e irá sobrescrever o id, name e description definidos no pai.

<?xml version="1.0" encoding="ISO-8859-1"?>
<project>  
	<extend>${basedir}/../project.xml</extend>  
	<id>agenda-services</id>  
	<name>Agenda Services</name>  
	<package>br.com.neki.service.*</package>  
	<description>Servicos referentes ao Projeto Agenda Online</description>  
	<shortDescription>Agenda Services JAR</shortDescription>  
	<dependencies>     
		<dependency>        
			<groupId>j2ee</groupId>        
			<artifactId>j2ee</artifactId>        
			<version>1.3.1</version>     
		</dependency>  
	</dependencies>
</project>
Listagem 16 - Definição do sub-projeto Agenda Services

Agora, vamos dar uma examinada no maven.xml do projeto Agenda Services. Tecnicamente falando, não precisaríamos fazer absolutamente nada para gerar o jar desse projeto, bastando executar maven jar:install na linha de comando. Entretanto, como veremos mais na frente, existirá um maven.xml que irá nos auxiliar, eliminando a execução manual do Maven para todos os sub-projetos. Portanto, o maven.xml do projeto Agenda Services, ficaria assim:

<project default="main" xmlns:m="jelly:maven">  
	<goal name="main">     
		<attainGoal name="jar:install" />  
	</goal>
</project>
Listagem 17 - maven.xml do sub-projeto Agenda Services

Construindo o WAR (Web Module)

Depois do ejb jar, é hora do war. Gastaremos um tempinho a mais nessa seção. Primeiramente, iremos analisar o project.xml. Então, iremos adicionar uma funcionalidade básica, que ainda não existe no Maven WAR Plug-in. E por último, veremos como fica o arquivo maven.xml.

A Listagem 18 apresenta o project.xml da aplicação Web da Agenda. A atual definição do projeto possui muito mais dependências para serem baixadas. Aqui, iremos mostrar as partes relevantes para ilustrar os conceitos. A parte importante é a seção de dependências. A aplicação Web depende das APIs J2EE providas pelo container em tempo de compilação, assim como de execução. Entretanto, não há nenhuma necessidade de empacotar a API J2EE dentro do WAR, uma vez que isso é responsabilidade do servlet container. No mais, a aplicação web depende do JAR do Struts 1.1. Setando a propriedade <war.bundle>true</war.bundle>, indicará que o struts-1.1.jar será empacotado no WAR. Sempre que o WAR Plug-in receber a instrução de empacotar os jars, ele irá coloca-los dentro do diretório WEB-INF/lib do WAR. Comparado à cópia manual dos jars para o diretório WEB-INF/lib, pelo Ant. O WAR também depende do arquivo jar do Agenda Services, agenda-services-1.0-dev.jar. Entretanto, não queremos copiar o jar para o WEB-INF/lib, uma vez que o mesmo é uma biblioteca de dependência compartilhada por ambos, camada web e ejb. Dessa forma, teremos setada a propriedade war.bundle como false para o arquivo agenda-services-1.0-dev.jar. Você terá todas essas funcionalidades out of the box através do Maven WAR Plug-in.

<?xml version="1.0" encoding="ISO-8859-1"?>
<project>  
	<extend>${basedir}/../project.xml</extend>  
	<id>agenda-web</id>  
	<name>Aplicação Agenda Web </name>  
	<package>br.com.neki.web.*</package>  
	<description>Projeto Agenda Web</description>  
	<shortDescription>Agenda web project</shortDescription>  
	<dependencies>    
		<dependency>        
			<groupId>j2ee</groupId>        
			<artifactId>j2ee</artifactId>        
			<version>1.3.1</version>    
		</dependency>    
		<dependency>       
			<id>xdoclet+web-module</id>       
			<version>1.2b4</version>    
		</dependency>    
		<dependency>      
			<groupId>struts</groupId>      
			<artifactId>struts</artifactId>      
			<version>1.1</version>      
			<properties>        
				<war.bundle>true</war.bundle>      
			</properties>    
		</dependency>    
		<dependency>        
			<groupId>agenda</groupId>        
			<artifactId>agenda-services</artifactId>        
			<version>${pom.currentVersion}</version>        
			<properties>            
				<war.bundle>false</war.bundle>            
				<war.manifest.classpath>true</war.manifest.classpath>        
			</properties>    
		</dependency>  
	</dependencies>
</project>
Listagem 18 - Definição do sub-projeto Agenda Web

Entretanto, o Maven WAR Plug-in não possui uma característica. Ele não possui a capacidade de setar o manifest classpath. Sem essa característica, você não poderá utilizar bibliotecas de dependência. Então, acrescentaremos esse característica no WAR Plug-in. Serão necessárias somente duas pequenas alterações. Abra o plugin.jelly do WAR Plug-in em: C:/Documents And Settings/<login-id>/.maven/plugins/maven-war-plugin-<version>-[SNAPSHOT]. Essas alterações devem ser feitas na goal de nome war. Coloque o código que segue abaixo, nessa goal.

<j:forEach var="dep" items="${pom.dependencies}">  
	<j:if test="${dep.getProperty('war.manifest.classpath')=='true'}">
		<j:set var="maven.war.classpath" value="${maven.war.classpath} ${dep.artifact}"/>  
	</j:if>
</j:forEach>

Esse código irá iterar em cima de cada dependência descrita no project.xml (identificada pelo pom.dependencies) e irá checar se o war.manifest.classpath está setado como true. Caso sim, ele irá adicionar o nome do artefato na propriedade denominada maven.war.classpath.

A segunda alteração que precisa ser feita é quando o manifest file é escrito. O manisfest file é criado pelo Ant Plug-in, executando uma goal chamada manifest. O código de criação do manifest é apresentado abaixo. É necessário inserir a linha em negrito para setar o atributo manifest classpath. Que irá utilizar a propriedade maven.war.classpath setada acima.

<ant:manifest>  
	<ant:attribute name="Built-By" value="${user.name}" />  
	<ant:attribute name="Class-Path" value="${maven.war.classpath}"/>  
	<ant:section name="${pom.package}">    
		<ant:attribute name="Specification-Title"   value="${pom.artifactId}" />    
		<ant:attribute name="Specification-Version" value="${pom.currentVersion}" />    
		<ant:attribute name="Specification-Vendor"  value="${pom.organization.name}" />  
	</ant:section>
</ant:manifest>

Simples, não é!? :) Espero que isso o estimule a criar seus próprios plug-ins, quando for necessário, ao invés de ficar adicionando, repetidamente, tarefas dentro de preGoals e posGoals.

Abaixo, segue o maven.xml:

<project default="main" xmlns:m="jelly:maven">  
	<goal name="main">    
		<attainGoal name="war:install"/>  
	</goal>
</project>
Listagem 19 - maven.xml do sub-projeto Agenda Web

Construindo o EAR

Até agora, você viu como criar cada artefato individual que irá para dentro do EAR. Finalmente chegamos a última parte - construir o EAR propriamente dito. Você pode imaginar que o EAR deveria ser construído a partir da definição do projeto no topo da hierarquia, no nosso caso, na raiz do diretório AgendaOnline, uma vez que o EAR é um único artefato para todo o projeto. Entretanto, não é o caso. O EAR é construído como um artefato de um sub-projeto chamado ear (veja Listagem 13). Por que essa anomalia? Em primeiro lugar, o project.xml no nível do projeto AgendaOnline é um template para todos os outros sub-projetos estender. Se tivéssemos que especificar as dependências para construir o EAR, então, isso resultaria em uma dependência cíclica - aquela situação do ovo e da galinha - quando o template fosse estendido por outros sub-projetos. Se o template tivesse sido definido em outro lugar, provavelmente no nível mais alto, logo o project.xml do diretório AgendaOnline poderia produzir um EAR, porém o mesmo não seria utilizado como um template para o restante dos sub-projetos estenderem.

A Listagem 20 apresenta o project.xml para o projeto Agenda EAR. Na lista, você poderá ver as bibliotecas mais relevantes (que precisam de alguma explicação), o qual o ear depende.

01 <?xml version="1.0"?>
02 <project>
03  <extend>${basedir}/../project.xml</extend>
04  <id>agenda-online</id>
05  <name>Agenda EAR</name>
06  <description>Projeto Agenda EAR.</description>
07  <dependencies>
08        <dependency>
09            <groupId>j2ee</groupId>
10            <artifactId>j2ee</artifactId>
11            <version>1.3.1</version>
12        </dependency>
13      <dependency>
14            <groupId>xerces</groupId>
15            <artifactId>xerces</artifactId>
16            <version>1.4.4</version>
17            <properties>
18                <ear.bundle>true</ear.bundle>
19            </properties>
20        </dependency>
21        <dependency>
22            <groupId>${pom.groupId}</groupId>
23            <artifactId>agenda-services</artifactId>
24            <version>${pom.currentVersion}</version>
25            <properties>
26                <ear.bundle>true</ear.bundle>
27            </properties>
28        </dependency>
29        <dependency>
30          <groupId>${pom.groupId}</groupId>
31          <artifactId>agenda-web</artifactId>
32          <version>${pom.currentVersion}</version>
33          <type>war</type>
34          <properties>
35            <ear.bundle>true</ear.bundle>
36            <ear.appxml.ear.context-root>AgendaWeb</ear.appxml.ear.context-root>
37          </properties>
38        </dependency>
39  </dependencies>
40 </project>
Listagem 20 - Definição do sub-projeto Agenda EAR

  • Linha 33 - Type = war indicando que trata-se de um arquivo war. Isso será setado no application.xml;
  • Linha 36 - Coloca o context root para a aplicação web. Isso será setado no application.xml;

Maven Multiproject Plug-in

Através do Reactor podemos utilizar o Maven para controlar a construção de múltiplos projetos. O Reactor faz uso do pacote Werkz para determinar a ordem correta das dependências, definidas por cada projeto no seu respectivo POM. Essa ferramenta foi criada para encorajar a criação, ou refatoramento, de projetos em unidades menores, mais coerentes e discretas. O Reactor é ideal para a Programação Orientada a Componentes (Component Oriented Programming - COP), onde o sistema é compreendido em várias pequenas entidades que necessitam ser agregadas para formar o todo para ser distribuído.

O Reactor pode executar uma lista arbitrária de goals para qualquer conjunto de projetos especificado. Sendo assim, apesar do Reactor ter sido criado para o building, o mesmo poderá ser utilizado para a geração do site, ou para a geração de qualquer outro artefato escolhido.

Propriedades do Multiproject Plug-in:

PropriedadeDescriçãoOpcional?
maven.multiproject.aggregateDir //TODO//TODO
maven.multiproject.basedir//TODO//TODO
maven.multiproject.excludes//TODO//TODO
maven.multiproject.ignoreFailures//TODO//TODO
maven.multiproject.includes//TODO//TODO
maven.multiproject.navigation//TODO//TODO
maven.multiproject.overviewPage.create//TODO//TODO
maven.multiproject.overviewPage.title//TODO//TODO
maven.multiproject.overviewPage.link//TODO//TODO
maven.multiproject.overviewPage.linkTitle//TODO//TODO
maven.multiproject.overviewPage.text//TODO//TODO
maven.multiproject.type//TODO//TODO
maven.multiproject.overviewPage.text//TODO//TODO
Tabela 02 - Propriedade do Maven Multiproject Plug-in

MAVEN SITE

Com o auxílio do Maven ficou simples gerar a documentação do projeto através de um site, sendo facilmente mantida atualizada e consistente com as informações e propriedades do projeto. Na documentação gerada podemos encontrar a lista de desenvolvedores, mailling list, dependências do projeto, relatórios de cobertura dos testes unitários, relatórios de métricas aplicadas nos códigos fonte, change logs, JavaDocs, duplicidade de código, relatório sobre análise da padronização dos códigos fonte, entre outras.

Além disso, é criado um menu de navegação para orientar a equipe percorrer toda a documentação do projeto. Para criar esse menu é simples, basta adicioná-lo ao diretório "xdocs" do projeto.

O diretório xdocs é local onde são armazenados os arquivos para a construção dos HTML estáticos para o site do projeto. Esses arquivos são XML's que contém informações que desejam fazer parte da documentação do projeto, sendo transformados em arquivos HTML. Usando arquivos XML como "porta de entrada" para as informações, torna-se fácil mudar o look and feel completo do site, ou gerar a documentação do projeto em outros formatos de arquivos (PDF). Os arquivos XML contém algumas tag's próprias para a geração da documentação através do Maven, mas podem conter também tag´s HTML (isso é essencial).

Para dar início a geração da documentação do projeto, obtendo as descrições que existem nos vários arquivos XML que definem a estrutura do site, além das informações e propriedades do projeto e dos possíveis relatórios, basta executar o comando:

> maven site:generate

O resultado produzido por esse comando é a criação do diretório target/docs dentro do diretório base do seu projeto (no mesmo nível do diretório xdocs). Este diretório conterá todo o site do projeto com a documentação gerada.

Caso você tenha a responsabilidade de ser o mantenedor do site do projeto, pode usar o Maven para publicar o site gerado diretamente no Servidor Web. Isso é uma tarefa simples para o Maven, que irá usar as configurações que estão definidas no descritor do projeto (project.xml), para especificar as várias configurações como hostname do Servidor Web e diretório onde o site residirá, pois são informações relevantes para o deployment. Para isso basta executar o comando:

> maven site:deploy

Assumindo que você tenha acesso ao Servidor Web, o site gerado será publicado. Isso alterará o site do projeto de uma forma fácil e simples. Isso pode também ser facilmente automatizado.

Goals:

GoalDescription
xdocA goal padrão. Esta goal simplesmente executa o xdoc:generate-from-pom e xdoc:transform.
xdoc:generate-from-pomGera um conjunto de relatórios a partir do arquivo project.xml. Isto inclui dependência, mailing list, project info, reports e lista da equipe.
init-dvsl-tagEsta goal define a tag library DVSL para geração de documentação. A definição da é tag dvsl:dvsl.

CONFIGURAÇÕES

Uma das primeiras configurações é a criação de um simples navigation.xml, que conterá a estrutura do menu para navegar pela documentação. Para isso basta adicionar todos os itens e sub-itens que representem os arquivos HTML gerados a partir dos arquivos XML.

Os itens podem ser expandidos ou não, dependendo da sua navegação. Para isso adicione collapse="true" na declaração do item. Exemplo:

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Maven Xdoc Plugin">  
	<title>Maven Xdoc Plugin</title>  
	<body>    
		<menu>      
			<links>      
				<item name="Maven"  href="http://maven.apache.org/"/>
			</links>    
			<item name="Alpha" href="/alpha/index.html">
				<item name="Alpha One" href="/alpha/one/index.html"/>
				<item name="Alpha Two" href="/alpha/two/index.html"/>
			</item>
			<item name="Beta" href="/beta/index.html" collapse="true">
				<item name="Beta One" href="/beta/one/index.html" collapse="true"/>
				<item name="Beta Two" href="/beta/two/index.html" collapse="true"/>
			</item>
		</menu>
	</body>
</project> 

Para adicionar uma imagem a um item de navegação basta adicionar a opção img:

<item name="The Site" href="http://www.thesite.net/" img="http://www.thesite.net/thesite.png"/>

Podem ser adicionadas configurações para o Maven através do arquivo project.properties que se encontra em ${project.home}:

PropriedadeOpcional?Descrição
maven.ui.body.backgroundSimEspecifica a cor de background color usada para o body de cada pagina. O valor default é #fff (branco).
maven.ui.body.foregroundSimEspecifica a cor de foreground usada para o body de cada página. O valor default é #000 (preto).
maven.ui.section.backgroundSimEspecifica a cor de background usada nos headers de primeiro nível das seções. O valor default é #036 (dark blue).
maven.ui.section.foregroundSimEspecifica a cor de foreground usada nos headers de primeiro nível das seções. O valor default é #fff (branco).
maven.ui.subsection.backgroundSimEspecifica a cor de background usada nos headers de segundo nível das seções. O valor default é #888 (gray).
maven.ui.subsection.foregroundSimEspecifica a cor de foreground usada nos headers de segundo nível das seções. O valor default é #fff (branco).
maven.ui.table.header.backgroundSimEspecifica a cor de background usada nas linhas de header das tabelas. O valor default é #bbb (gray).
maven.ui.table.header.foregroundSimEspecifica a cor de foreground usada nas linhas de header das tabelas. O valor default é #fff (branco).
maven.ui.table.row.odd.backgroundSimEspecifica a cor de background usada nas linhas ímpares da tabela. O valor default é #ddd (gray).
maven.ui.table.row.odd.foregroundSimEspecifica a cor de foreground usada nas linhas ímpares da tabela. O valor default é #000 (preto).
maven.ui.table.row.even.backgroundSimEspecifica a cor de background usada nas linhas pares da tabela. O valor default é #ddd (gray).
maven.ui.table.row.even.foregroundSimEspecifica a cor de foreground usada nas linhas pares da tabela. O valor default é #000 (preto).
maven.ui.banner.backgroundSimEspecifica a cor de background usada no banner. O valor default é #036 (dark blue).
maven.ui.banner.foregroundSimEspecifica a cor de foreground usada no banner. O valor default é #fff (branco).
maven.ui.banner.border.topSimEspecifica a cor usada para o borda superior do banner. O valor default é #369 (azul).
maven.ui.banner.border.bottomSimEspecifica a cor usada para o borda inferior do banner. O valor default é #003 (preto).
maven.ui.source.backgroundSimEspecifica a cor usada no background dos source regions. O valor default é #036 (dark blue).
maven.ui.source.foregroundSimEspecifica a cor usada para foreground dos source regions. O valor default é #fff (branco).
maven.ui.source.border.topSimEspecifica a cor usada na borda superior dos source regions. O valor default é #888 (gray).
maven.ui.source.border.bottomSimEspecifica a cor usada na borda inferior dos source regions. O valor default é #888 (gray).
maven.ui.source.border.rightSimEspecifica a cor usada na borda do lado direito dos source regions. O valor default é #888 (gray).
maven.ui.source.border.leftSimEspecifica a cor usada na borda do lado esquerdo dos source regions. O valor default é #888 (gray).
maven.ui.navcol.backgroundSimEspecifica a cor usado para background na coluna de navegação que fica no lado esquerdo da página. O valor default é #eee (gray).
maven.ui.navcol.foregroundSimEspecifica a cor usada para foreground na coluna de navegação que fica no lado esquerdo da página. O valor default é #000 (black).
maven.ui.navcol.border.topSimEspecifica a cor usada na borda superior da coluna de navegação. O valor default é #fff (branco).
maven.ui.navcol.border.rightSimEspecifica a cor usada na borda do lado direito da coluna de navegação. O valor default é #aaa (gray).
maven.ui.navcol.border.bottomSimEspecifica a cor usada na borda inferior da coluna de navegação. O valor default é #aaa (gray).
maven.ui.breadcrumbs.backgroundSimEspecifica a cor usada para background na barra horizontal de navegação lacalizada imediatamente abaixo do banner (esse elemento não aparecerá caso a página não tenha links especificados). O valor default é #ddd (gray).
maven.ui.breadcrumbs.foregroundSimEspecifica a cor usada para foreground na barra horizontal de navegação localizada imediatamente abaixo do banner (esse elemento não aparecerá caso a página não tenha links especificados). O valor default é #000 (preto).
maven.ui.breadcrumbs.border.topSimEspecifica a cor usada na borda superior da seção horizontal de navegação. O valor default é #fff (branco).
maven.ui.breadcrumbs.border.bottomSimEspecifica a cor usada na borda inferior da seção horizontal de navegação. O valor default é #aaa (gray).
maven.ui.href.linkSimEspecifica a cor usada para todos os links. O valor default é azul.
maven.ui.href.link.activeSimEspecifica a cor usada para todos os links quando estes estão ativos. O valor default é #f30 (vermelho).
Propriedades de organização de diretórios
PropriedadeOpcional?Descrição
maven.docs.destSimEspecifica a localização dos arquivos gerados a partir do xdocs. O valor default é ${maven.build.dir}/docs.
maven.docs.srcSimEspecifica a localização da documentação "xdocs" do projeto. O valor default é ${basedir}/xdocs.
maven.gen.docsSimEspecifica a localização onde os arquivos xdocs do Maven são armazenados. Esses arquivos depois são transformados para HTML. O valor default é ${maven.build.dir}/generated-xdocs.
Outras Propriedades
maven.xdoc.crumb.separatorSimSeparador entre links. O padrão é |
maven.xdoc.dateSimPermite o usuário mostrar a data de geração do site. Essa data pode ficar em 5 lugares diferentes com o "maven.xdoc.date":
  • left
  • righ
  • navigation-top
  • navigation-bottom
  • bottom
Se "maven.xdoc.date" esta vazio, nenhuma data é mostrada no site. O "maven.xdoc.date.locale" tem como default o "en" (ex.: english).
maven.xdoc.date.formatSimConfigura o formato da data que será mostrada. O padrão é "dd MMMM yyyy" (ex.: "14 August 2002"). Para detalhes sobre formatação veja SimpleDateFormat na documentação do JDK.
maven.xdoc.date.localeSimConfigura o locale usado para data. Padrão é "en".
maven.xdoc.poweredby.imageSimConfigura o nome da imagem usada (veja images/logos). O valor default é a logo de Stéphane Mor.
maven.xdoc.poweredby.titleSimConfigura o título do link para a logo de powered. O Padrão é "Powered by Maven".
maven.xdoc.poweredby.urlSimConfigura o link para a logo de powered. O padrão é "http://maven.apache.org/"
maven.xdoc.jslSimO JSL stylesheet usado para converter xdocs para HTML. Para sobrescrever especifique-o como um arquivo: URL.

Organização das documentações geradas:

DiretórioConteúdoComentários
target/ Contem classes compiladas e JARs. O conteúdo do diretório target deve ser muito utilizado no projeto. Este diretório contem os JAR's gerados.
target/classes Contem classes compiladas e JARs. O diretório target/classes contém todas as classes compiladas. Este diretório é usado para empacotar o JAR final para o projeto.
target/test-classes Contém as classes de teste unitários compilados. O diretório target/test-classes contém todas as classes dos testes unitários compiladas. Este diretório é usado quando executados os testes unitários.
target/iutest-classes Contém as classes compiladas para os testes unitários de integração. O diretório target/iutest-classes contém todas as classes dos testes unitários de integração compilados. Este diretório é usado durante a execução dos testes unitários de integração.
target/generated-docs Contém os xdocs gerados pelo Maven O diretório target/generated-docs contém todas os xdocs gerados pelo Maven. Todo o conteúdo gerado pelo Maven é primeiro convertido para o formato xdoc, então o mesmo stylesheet usado para transformar o resto do site pode ser usado para gerar o conteúdo. O conteúdo para este diretorio é transformado e armazenado no diretório docs.
target/test-reports Contém os resultados individuais dos testes unitários. O diretório test-reports/ contém os relatórios individuais dos testes unitários em ambos os formatos XML e texto. Os relatórios existentes nesse diretório é usado quando o Maven cria o relatório final sobre os testes unitários.
target/docs Arquivos de documentação para o site a ser publicado. O diretório docs contém somente as documentações geradas com a intenção de ser publicadas no site do projeto. Este diretório inclui os arquivos HTML, JavaDocs, cross-referenced sources e vários relatórios gerados. Geralmente toda a documentação é armazenada no diretório xdocs e então transformada para o seu respectivo diretório.
target/docs/index.html A página inicial para sobre a documentação do projeto. Se o projeto não contém uma página index.html no diretório xdocs, então o Maven automaticamente cria uma página simples baseada nas informações descritas nos elementos do descritor do projeto.
target/docs/apidocs API da documentação. Os JavaDocs do projeto são gerados automaticamente usando o utilitário JavaDoc. Colocando a documentação da API no diretório docs/apidocs faz com que seja fácil referenciar outras documentações que estejam no diretório docs e vice-versa.
target/docs/xref Referência para o código fonte. O Maven gera automaticamente as referências para os códigos fontes que permite uma navegação fácil através da estrutura de fontes. Colocando esses referências no diretório docs/xref/ é fácil referenciar a documentação da API e vice-versa.
target/docs/xref-test Referência de testes para o código fonte. O Maven gera automaticamente as referências para os códigos fontes dos teste, mostrando aos desenvolvedores como usar o software apropriadamente de uma forma fácil.
target/docs/mail-lists.html Documentação sobre o Mailing list. O Maven gera automaticamente a lista de mailing lists baseada nas informações providas pelo descritor do projeto.
target/docs/team-list.html A lista da equipe do projeto. O Maven gera automaticamente a lista dos membros da equipe baseada nas informações providas pelo descritor do projeto.
target/docs/dependencies.html A lista das dependências. O Maven automaticamente gera a lista de dependências do projeto baseada nas informações providas pelo descritor do projeto.
target/docs/changelog.html O log de alterações registradas no CVS. O Maven gera automaticamente o log de alterações a partir do log de mensagens do CVS. Este log é atualmente limitado para os últimos 30 dias.
target/docs/file-activity-report.html Relatório das alterações por arquivos. O Maven gera automaticamente um log a partir dos arquivos alterados nos últimos 30 dias que estão em seu SCM.
target/docs/developer-activity-report.html Relatório das atividades dos desenvolvedores. O Maven gera automaticamente um log a partir dos arquivos alterados nos últimos 30 dias que estão em seu SCM por desenvolvedor.
target/docs/jdepend-report.html Relatório de métricas. O Maven gera automaticamente um relatório com várias métricas de analise sobre os códigos fontes. Estes relatórios facilitam a visão completa do projeto.
target/docs/junit-report.html Relatório dos testes unitários. O Maven gera automaticamente relatórios com resultados dos testes unitários.
target/docs/checkstyle-report.html Relatório do Checkstyle. O Maven gera automaticamente um relatório com os resultados do Checkstyle. Com este relatório poderá ser analisado se as convenções adotadas para o projeto estão sendo seguidas.

RELATÓRIOS

Através da utilização do Maven, vários relatórios podem ser gerados automaticamente, provendo conjunto de informações relevantes sobre o projeto, tanto para as equipes técnica, de qualidade ou gerencial. Isto é feito facilmente com a inclusão da tag reports no descritor do projeto. Mas o uso dessa tag não é obrigatório, onde a supressão de seu uso faz com que um conjunto de relatórios padrão seja gerado. Com essa tag, você pode incluir ou excluir determinados tipos de relatórios que são gerados com a utilização de plugins do Maven, todos esses são adicionados no menu de navegação na ordem em que são adicionados.

Esses relatórios são gerados através do comando maven site.

No project.xml:

<reports>    
	<report>maven-changes-plugin</report>    
	<report>maven-faq-plugin</report>    
	<report>maven-multiproject-plugin</report>  
</reports>

O adicionamento de um plugin chamado xyz para geração de um determinado relatório deve ser feito utilizando o seguinte valor na tag "report": maven-xyz-plugin.

O conjunto padrão de relatórios é definido no plugin xdoc o qual tem como valor padrão os seguintes plugins:

  • maven-changelog-plugin
  • maven-changes-plugin
  • maven-checkstyle-plugin
  • maven-developer-activity-plugin
  • maven-file-activity-plugin
  • maven-javadoc-plugin
  • maven-jdepend-plugin
  • maven-junit-report-plugin
  • maven-jxr-plugin
  • maven-license-plugin
  • maven-linkcheck-plugin
  • maven-pmd-plugin
  • maven-tasklist-plugin

Caso seja desejado usar o conjunto padrão de relatórios, mas adicionar algum em especial, ou retirar algum, a melhor forma de fazer isso é usar postGoal para xdoc:register-reports.

<postGoal name="xdoc:register-reports">
     <attainGoal name="maven-changelog-plugin:deregister"/> 
	 <attainGoal name="maven-meu-plugin:register"/>
</postGoal>

A documentação dos sites que agregam um conjunto de subprojetos e que devem conter a inclusão completa da documentação do projeto como seções na barra de navegação de seus sites. Isto pode ser feito com a configuração da propriedade maven.xdoc.includeProjectDocumentation com o valor de "no". Por padrão o Maven icluirá a documentação do projeto na seção da barra de navegação com a qual incluirá informações sobre o projeto tão quanto links para os numerosos relatórios gerados pelo próprio Maven. //TODO: rever!

MAVEN XDOC PLUGIN

O plugin XDoc é o principal mecanismo utilizado para produzir a documentação do projeto gerado pelo Maven, tão quanto qualquer informações fornecida pela equipe no "xdocs". Um "xdoc" é um arquivo XML composto por pequenos e simples conjuntos de tags. O Maven utiliza esse formato por completo, onde os relatórios gerados são primeiramente gerados como um "xdoc", os quais então são transformados em HTML através desse plugin. Isso é feito com o uso de Jelly/JSL que transformam arquivos XML em HTML. Todos os arquivos XML existentes no diretório são convertidos utilizando JSL. Os arquivos que não são XML e/ou sub-diretórios são copiados sem modificação, com isso é permitido a inclusão de outros tipos de documentos (inclusão de imagens). Os arquivos HTML gerados automaticamente herdam o look-and-feel padrão do Maven.

Os arquivos XML devem ser compostos de sintaxe XML/XHTML que sejam passíveis de "parser" padrão para XML (Xerces).

Exemplo:

<?xml version="1.0"?>
<document>  
	<properties>    
		<author email="nospam.AT.foo.DOT.com">Jon S. Stevens</author>    
		<author email="mrsmith.AT.foo.DOT.com">Mr. Smith</author>    
		<title></title>  
	</properties>  
	<meta name="keyword" content="jakarta, java"/>
	<body>
		<section name="Section 1">  
			<p>This is section 1.</p>  
			<table>    
				<tr>      
					<td>This is a table</td> 
				</tr>  
			</table>
			<ul>      
				<li>This is an unordered list.</li>  
			</ul>
		</section>
		<section name="Section 2">  
			<p>This is section 2.</p>  
			<ol>      
				<li>This is an ordered list.</li>  
			</ol>
		</section>
		<section name="Section 3">  
			<p>This is section 3.</p>  
			<source>      
				Anything within this tag is rendered as a "box" with blue 
				lines and &lt;pre&gt;&lt;/pre&gt; tags around it.  
			</source>  

			<subsection name="Subsection of Section 3">    
				<p>This is the subsection 3.</p>  
			</subsection>
		</section>
	</body>
</document>

Explicando algumas coisas:

  • É possível ter uma ou mais tags <author>
  • É possível ter uma ou mais tags <section>
  • Dentro da tag <section> é possível ter uma ou mais tags <p>. Qualquer tipo de texto deve estar entre tags <p> e pode conter outras marcações XHTML.
  • Tag <meta> são colocadas como tags dentro da <document> e vão direto para o arquivo html.
  • Tags <source> são especiais, existem somente dentro das tags <section> e <subsection>. Se estiver utilizando outras marcações XML/XHTML dentro das tags source, então é necessário utilizar CDATA. Exemplo:
    <source><![CDATA[conteúdo foo]]></source>
    No exemplo do arquivo xml, estamos utilizando a tag <pre> e podemos ver que esta não precisa estar em uma CDATA.

Você pode utilizar a tag footer para incluir texto ou imagens abaixo do menu de navegação e acima do aviso de copyright. Esta tag tem somente uso no arquivo navigation.xml e deve ser colocada dentro do elemento body. Exemplo:

<footer>      
	<A href="http://sourceforge.net/projects/ctecl">        
		<IMG src="http://sourceforge.net/sflogo.php?group_id=72748"
			border="0" alt="sf logo"/>      
	</A>   
</footer>

Se o elemento search é encontrado dentro do body do arquivo navigation.xml, uma opção de pesquisa é gerada no menu de navegação, a qual usará o google.

<project name="foo">  
	<body>     
		<menu name="bar">  ...  </menu>     
		<search/>  
	</body> 
</project>

Adicionando mais usabilidade aos xdocs, podem ser incluídos outros tipos de arquivos como imagens, arquivos HTML, PDF's etc. Por padrão este plugin copiará todos os arquivos localizados no diretório maven.docs.src para a geração final do site. Caso seja criado um style/project.css abaixo de maven.docs.src, ele será copiado para a árvore de documentos e importado para dentro de cada página (via @import). Isto permite você facilmente adicionar e modificar os styles providos pelo Maven.

EXEMPLOS DE REPORTS

Changes:

Com esse relatório você pode navegar por todo o site do projeto e ter um resumo de todas as alterações que ocorrem. Com isso as alterações que ocorrem diariamente, a cada dois dias ou semanalmente (a partir de suas configurações) podem ser acompanhadas e ver o que esta acontecendo de novo. Para habilitar esse relatório, é necessário criar o arquivo changes.xml no diretório xdocs. O formato para esse arquivo é o seguinte:

<?xml version="1.0"?>
<document>  
	<properties>    
		<title>Changes</title>
		<author email="vmassol@octo.com">Vincent Massol</author>
	</properties>
	<body>
		<release version="1.5" date="in CVS">
			<action dev="vmassol" type="add" due-to="Jason Robertson"
					due-to-email="Jason.Robertson@acs-inc.com">  
				Added Form-based authentication support (Submitted by Jason Robertson).
			</action>
			<action dev="vmassol" type="add">
				Added a <link href="howto_build.html">tutorial</link> that 
				explains how to build Cactus from the sources.
			</action>
			[...]    
		</release>
	</body>
</document>

O atributo "type" pode ser add, remove update ou fix.

Para adicionar esse relatório:

  • maven-changes-plugin

Exemplo:

Developer Activity:

Identifica cada desenvolvedor e seu commits e arquivos alterados.

Para adicionar esse relatório:

  • maven-developer-activity-plugin

Exemplo:

File Activity:

Identifica o nome do arquivo e a quantidade de vezes que ele foi alterado.

Para adicionar esse relatório:

  • maven-file-activity-plugin

Exemplo:

Task List:

Identifica a classe, a quantidade de "TODO's" e os métodos com "TODO".

Para adicionar esse relatório:

  • maven-tasklist-plugin

Exemplo:

MÉTRICAS

Durante o desenvolvimento de um produto de software, procedimentos de medição e análise de dados quantitativos permitem que se obtenha informações objetivas quanto à qualidade do produto em construção e possibilitam um controle preciso da evolução do projeto. No contexto de uma organização produtora de software, o uso de medições permite que se tenha um melhor conhecimento da eficácia do processo de desenvolvimento, através do acompanhamento quantitativo de diversos aspectos como produtividade, evolução da qualidade de produtos desenvolvidos, acurácia de estimativas, entre outros.

Em primeiro lugar, devido à quantidade e à complexidade dos fatores envolvidos no desenvolvimento de um software de grande porte, há tantos aspectos a serem medidos que torna-se necessário selecionar apenas um subconjunto restrito, de forma a viabilizar as atividades de coleta e análise. Sem uma política bem definida para definição desse subconjunto de métricas, a probabilidade de se escolher arbitrariamente as métricas mais adequadas é muito remota.

Uma vez modelado o processo de desenvolvimento e alguns conceitos utilizados na medição, é possível definir as medidas a serem coletadas. São definidas as medidas explícitas (obtidas diretamente), a partir das quais se pode construir medidas derivadas.

Um exemplo de medida explícita é o registro de defeitos. Um defeito pode ser definido como qualquer problema ou imperfeição encontrado em um produto ou artefato de software, cuja correção implique na alteração de pelo menos um artefato produzido. São considerados defeitos apenas os problemas decorrentes de erros cometidos por membros da equipe de desenvolvimento. Alterações de requisitos solicitadas pelo cliente ou usuário não são consideradas defeitos, sendo tratadas à parte.

Durante o ciclo de vida do projeto, devem ser registrados todos os defeitos encontrados.

Objetivos

Procedimentos de coleta e análise de métricas envolvem geralmente uma grande quantidade de informação, principalmente no contexto dos grandes projetos de software. Nesses casos, a coleta e análise manual dos dados tornam-se inviáveis, tanto pelo risco de erros decorrentes de falhas humanas, quanto pelo custo envolvido. A existência de ferramentas automatizadas que dêem suporte a essas atividades torna-se, portanto, essencial.

Este trabalho prevê, além da definição da política de medição, o uso de uma solução que ofereça apoio informatizado à gestão das métricas escolhidas. A solução será composta de dois módulos principais:

  • Um módulo de coleta, que engloba funcionalidades que oferecem suporte à realização das medições, armazenando os resultados obtidos em relatórios que se encontram no site do projeto.
  • Um módulo de análise, que contempla recursos para a visualização gráfica dos indicadores quantitativos e métodos estatísticos para o processamento das métricas, com o objetivo de oferecer apoio ao trabalho de análise do resultado das medições.

Plugin's

Jdepend - http://www.clarkware.com/software/JDepend.html

Analisa classes Java e gera métricas sobre a qualidade do "Design" para cada package Java. JDepend permite a equipe de Qualidade automaticamente mensurar a qualidade do "Design" em termos de suas extensibilidades, reusabilidade e manutenibilidade para controle efetivo das dependências dos packages Java.

Segue abaixo uma visão geral do uso dessa métrica:

O objetivo dessa análise é verificar o design se esta flexível, interdependente e fácil de manutenção.

Algumas formas de dependência são desejadas, enquanto outras não.

Simplesmente por usar modelagem OO pode ser insuficiente para obter robustez, manutenibilidade e reusabilidade. Existem outros atributos que são requeridos, como pattern de interdependência entre design de sub-sistemas, isolar elementos reusáveis de elementos não reusáveis e blocos de propagação de mudança em manutenção.

Para adicionar esse plugin:

  • maven-jdepend-plugin

Exemplo:

PMD - http://pmd.sourceforge.net

É uma ferramenta que analisa os arquivos "java" e procura por problemas de relativa importância, tais como:

  • Variáveis locais que não declaradas.
  • Blocos catch que estejam vazios.
  • Parâmetros que não são usados.
  • Blocos de IF's sem preenchimento.
  • Imports duplicados.
  • Métodos privados que não estejam sendo utilizados.
  • Classes que poderiam ser Singletons.

Essa ferramenta utiliza a abordagem de "Rules", ou seja, são configuradas as principais/qualquer "best pratices" que deverá ser seguida pela equipe de desenvolvimento. O conjunto de "Rules" pode ser estendido, através da criação de novos verificadores. Para isso basta criar uma nova rule/verificador utilizando uma expressão em XPath.

Alguns exemplos de "Rules" analisadas pelo PMD:

  • EmptyCatchBlock
  • EmptyIfStmt
  • EmptyWhileStmt
  • EmptyTryBlock
  • UseSingletonRule
  • JUnitAssertionsShouldIncludeMessageRule
  • JUnitSpelling
  • ExcessiveImportsRule

CPD:

Desenvolvido como um plugin ao PMD, tem como objetivo analisar códigos Java e identificar as classes que contém duplicidade em código. Análogo ao Simbian (ver abaixo), mas não tão efetivo em sua analise, tendo como um dos seus principais problemas identificados no seu uso o não apontamento onde ocorreu a duplicidade de códigos entre classes.

Para adicionar esse plugin:

  • maven-pmd-plugin

Exemplo:

Clover - http://www.thecortex.net/clover

Essa ferramenta abrange todos os teste unitários, analisando a cobertura dos testes para as classes relacionadas, executando uma interação com as classes de testes do JUnit. Após a cobertura dos testes é gerado um relatório com a analise focada em cada classe dos packages existentes. Dessa forma, possibilita a equipe de qualidade analisar os testes que estão sendo desenvolvidos, a qualidade de cada e se esta apto a atender a necessidade a serem analisadas. De posse dos relatórios os testes podem ser analisados e sofrer refactoring para que possam cobrir por completo os testes especificados.

O uso desse dessa ferramenta no ciclo de integração continua mantém a equipe de qualidade com informações atualizadas sobre o quão estão os testes da equipe de desenvolvimento cobrindo as classes desenvolvidas, descobrindo possíveis bugs existentes.

Para adicionar esse plugin:

  • maven-clover-plugin

Exemplo:

Simian - http://www.redhillconsulting.com.au/products/simian/index.html

Um analisador de código Java com o intuito de localizar duplicidade em código. Auxilia na atividade de "refactoring" como um guia, apontando as classes que contém código repetido. Ações do tipo "copiar e colar" que são freqüentes entre desenvolvedores e um atraente modo de propagação de erros que dificilmente são identificados pelos testes unitários. O Simbian identifica essas duplicações que em sua grande maioria apontam erros em design e acoplamentos não desejados na modelagem.

Para adicionar esse plugin:

  • maven-simian-plugin

Exemplo:

CheckStyle - http://checkstyle.sourceforge.net

Uma ferramenta desenvolvida para auxiliar desenvolvedores a escreverem código Java que estejam de acordo com uma padrão estabelecido pela equipe de Qualidade. O processo de checagem do código fonte passa a ser executado de forma automatizada, tornando-se ideal para projetos que pretendem manter a padronização de código, garantindo qualidade e legibilidade de códigos Java. Configuração simples e flexível, suportando todas as padronizações de código e podendo seguir as convenções da SUN Microsystems.

Alguns exemplos de verificações executadas pelo CheckStyle:

  • Comentários Javadoc
  • Convenção de nomes
  • Headers
  • Imports
  • Size Violations
  • Whitespace
  • Modifiers
  • Blocks
  • Problemas de codificação
  • Class Design
  • Código duplicado
  • Checagem de métricas
  • Checagem personalizada

Para adicionar esse plugin:

  • maven-checkstyle-plugin

Exemplo:

MAVENIDE

Como vimos, o Maven foi criado para facilitar a vida dos desenvolvedores provendo uma estrutura bem definida para o projeto, através de um processo bem definido que deve ser seguido e uma gama de documentação consistente que mantém de desenvolvedores a clientes, informados no que está acontecendo no projeto.

Podemos dizer que o Maven alivia muitas tarefas que consideramos árduas e que teriam que ser "feitas na mão". Para alcançar esse o objetivo, o Maven utiliza-se do conceito do POM (Project Object Model), um arquivo XML que descreve, dentre outras coisas, o layout do projeto. No outro lado temos as IDEs Java, com a sua própria maneira de representar as configurações necessárias a construção do projeto. Dessa forma, temos uma discrepância que torna difícil a manutenção do projeto e o sincronismo entre essas partes.

Mavenide procura integrar o Maven nas IDEs padrão de mercado. Existindo um número significativo de coisas que podem ser feitas, como: edição do POM, sincronização entre a IDE e POM, executar o Maven de dentro da IDE, prover wizards para a "mavenização" de projetos, gerenciar as propriedades de tempo de execução do Maven etc.

Instalação

Uma vez baixado, um plug-in é normalmente instalado no Eclipse fazendo um unzipping dos arquivos baixados e copiando o conteúdo dos mesmos para o diretório plug-ins e features do Eclipse. Nesse caso, o arquivo mevenide.update_0.0.1.jar deve ser unzipado dentro do diretório 'raiz' do Eclipse (ele automaticamente cairá no diretório de plug-ins e features), enquanto que os arquivos: org.mevenide.config_0.1.jar, org.mevenide.core_0.1.1.jar, org.mevenide.grabber_0.1.1.jar, org.mevenide.ui_0.1.1.jar, necessitam ser unzipado diretamente no sub-diretório plug-ins do Eclipse. Por ultimo, o arquivo org.mevenide.feature_0.1.1.jar, deverá ser unzipado diretamente no sub-diretório features do Eclipse. Por segurança, você deve fazer o unzip em um diretório temporário e copiar para um diretório apropriado dentro do Eclipse. Se o Eclipse estiver sendo executado, você precisará parar e restartar para que os plug-ins sejam reconhecidos.

Configurações

Antes de utilizarmos o MavenIDE, deveremos configurá-lo adequadamente. Faremos isso, através da página de preferências do Maven. Em Window > Preferences > Maven. Java Home, Maven Home e Maven repository são informações requeridas para executarmos com sucesso o MavenIDE.

Um template para o POM também poderá ser especificado. Ele será utilizado na como esqueleto na criação de novos POMs.

Se você quiser, também poderá checar a opção 'Check timestamp before syncronizing', que irá verificar o timestamp do project.xml ou .classpath do projeto. Isso irá prevenir problemas de sobrescrita de arquivos de configuração.

Por último, você poderá especificar uma goal default a ser executada para todos os projetos.



Figura 01 - Maven Preferences

Para executar scripts a partir do Eclipse, utilizando o MavenIDE, basta clicar com o botão direito do mouse no POM (Project Object Model - project.xml) e no 'MavenIDE Menu', clique na opção 'Run Maven...'. Como segue abaixo:



Figura 02 - MavenIDE Menu

Quando você seleciona a opção 'Run Maven...' do Maven menu, um wizard irá aparecer para que você coloque as informações relevantes no contexto da IDE (isso significa que, opções como -b, -h, -p, entre outras, não estão acessíveis). As propriedades de sistema poderão ser especificadas utilizando o botão 'Add'.

A caixa de texto na parte inferior do wizard poderá ser editada e nela iremos colocar as goals que serão executadas. A tabela é utilizada para passarmos propriedades do sistema para o Maven.



Figura 03 - Wizard de execução do Maven

Você também poderá utilizar o atalho do Eclipse, em Run > External Tools > Run As > Maven Project. Esse comando irá executar a goal default especificada na página de preferências.



Figura 04 - Atalho para execução do Maven

Podemos visualizar o output da operação na própria console de debug do Eclipse, dada a inexistência de uma console para o Mavenide (versão atual).

POM Synchronization

Mavenide POM Synchronization é basicamente uma única página, composta de dois elementos:

  • Uma aba, onde o usuário irá especificar qual artefato será colocado dentro do POM;
  • E a outra, permite que o usuário especifique toda o status das dependências existentes no POM

Source Directory Synchronization

Uma vez que o POM contém muito mais informações que o Eclipse .classpath, quando estivermos sincronizando o POM, precisaremos prover algumas informações adicionais. Para toda Eclipse SourceFolder, o tipo do Maven Source Directory tem que ser especificado através da página do wizard Maven Source Directory Mapping. O usuário deverá declarar se existe ou não herança. Se não existir herança, então a checkbox (terceira coluna) ficará desabilitada.



Figura 03 - Página do wizard Maven Source Directory Mapping

Dependency Synchronization

Mavenide prove um mecanismo automático de resolução das dependências, podendo determinar de maneira precisa o groupId, artifactId e version de uma determinada dependência. Ele pode falhar, então o usuário poderá auxiliá-lo utilizando a página do wizard Dependency Mapping. Note também que se a biblioteca nao estiver instalada no repositório local, seu groupId não será resolvido, mas o mesmo será assinalado com nonResolvedGroupId e uma key será adicionada ao project.properties fazendo uso da facilidade do Maven jar overriding.



Figura 04 - Página do wizard Dependency Mapping

Mavenide prove o suporte a dependências de propriedades através da caixa de diálogo Dependency Properties que poderá ser acessada pressionando o botão "Properties".



Feedback

Por favor, dê a sua opinião a respeito do conteúdo apresentado. Correções, sugestões ou qualquer outra informação relevante é de suma importância para nós e será muito bem vinda.

Contato: owner@hotwork.dev.java.net