Skip to content

3. As ferramentas do documento

Os exemplos deste documento foram testados com as seguintes ferramentas:

  • NetBeans, da versão 6.8 à versão 7.1.2. A instalação do NetBeans é descrita no [ref3], no parágrafo 1.3.1.
  • Wampserver, versão 2.2. A instalação do WampServer está descrita no [ref3], no parágrafo 1.3.3;
  • O Maven está integrado no NetBeans. Passamos agora a descrever esta ferramenta.

3.1. Maven

3.1.1. Introdução

O Maven está disponível no URL [http://maven.apache.org/index.html ]. Segundo os seus criadores:

O objetivo principal do Maven é permitir que um programador compreenda o estado completo de um projeto de desenvolvimento no menor espaço de tempo possível. Para atingir este objetivo, existem várias áreas de interesse que o Maven procura abordar:

  • Simplificar o processo de compilação
  • Fornecer um sistema de compilação uniforme
  • Fornecer informações de qualidade sobre o projeto
  • Fornecer diretrizes para as melhores práticas de desenvolvimento
  • Permitir uma migração transparente para novas funcionalidades

O Maven está integrado no NetBeans e vamos utilizá-lo apenas para uma das suas funcionalidades: a gestão das bibliotecas de um projeto. Estas são constituídas pelo conjunto de arquivos jars, que devem estar na pasta Classpath do projeto. Podem ser em grande número. Por exemplo, os nossos projetos futuros irão utilizar o ORM (Object Relational Mapper) Hibernate. Este ORM é composto por dezenas de arquivos jar. A vantagem do Maven é que nos poupa de ter de as conhecer todas. Basta indicarmos no nosso projeto que precisamos do Hibernate, fornecendo todas as informações úteis para localizar o arquivo principal desse ORM. O Maven descarrega então também todas as bibliotecas necessárias ao Hibernate. A isto chama-se «dependências do Hibernate». Uma biblioteca necessária ao Hibernate pode, por sua vez, depender de outros arquivos. Estes serão igualmente descarregados. Todas estas bibliotecas são colocadas numa pasta denominada «repositório local do Maven».

Um projeto Maven é facilmente partilhável. Se for transferido de um computador para outro e as dependências do projeto não estiverem presentes no repositório local do novo computador, estas serão descarregadas.

O Maven pode ser utilizado sozinho ou integrado num IDE (Ambiente de Desenvolvimento Integrado) como o NetBeans ou o Eclipse.

Vamos criar um projeto Maven no NetBeans:

  • no [1], criar um novo projeto,
  • em [2], selecione a categoria [Maven] e o tipo de projeto [Java Application],
  • em [3], indicar a pasta pai da pasta do novo projeto,
  • em [4], atribuir um nome ao projeto,
  • em [5], o projeto gerado.

Vamos analisar os elementos do projeto e explicar a função de cada um.

  • em [1]: os diferentes ramos do projeto:
    • [Source packages]: as classes Java do projeto;
    • [Test packages]: as classes de teste do projeto;
    • [Dependencies]: os arquivos .jar necessários ao projeto e geridos pelo Maven;
    • [Test Dependencies]: os ficheiros .jar necessários para os testes do projeto e geridos pelo Maven;
    • [Java Dependencies]: os ficheiros .jar necessários ao projeto e não geridos pelo Maven;
    • [Project Files]: ficheiros de configuração do Maven e do NetBeans,
  • em [3], o ramo [Source Packages],

Este ramo contém os códigos-fonte das classes Java do projeto. O NetBeans gerou uma classe por predefinição:


package istia.st.mvexemple;

/**
 * Hello world!
 * 
 */
public class App {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
  • em [4], o ramo [Test Packages], que contém os códigos-fonte das classes de teste do projeto,
  • em [5], a biblioteca JUnit 3.8 necessária para a execução dos testes,

O NetBeans gerou uma classe por predefinição:


package istia.st.mvexemple;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Unit test for simple App.
 */
public class AppTest extends TestCase {
    /**
     * Create the test case
     * 
     * @param testName
     *          name of the test case
     */
    public AppTest(String testName) {
        super(testName);
    }

    /**
     * @return the suite of tests being tested
     */
    public static Test suite() {
        return new TestSuite(AppTest.class);
    }

    /**
     * Rigourous Test :-)
     */
    public void testApp() {
        assertTrue(true);
    }
}

Trata-se de um teste JUnit 3.8. Posteriormente, utilizaremos testes JUnit 4.x.

  • no [6], o ramo [Dependencies] está aqui vazio,

Este ramo apresenta todas as bibliotecas necessárias ao projeto e geridas pelo Maven. Todas as bibliotecas aqui listadas são descarregadas automaticamente pelo Maven. É por isso que um projeto Maven necessita de acesso à Internet. As bibliotecas descarregadas serão armazenadas localmente. Se outro projeto necessitar de uma biblioteca já presente localmente, esta não será descarregada. Veremos que esta lista de bibliotecas, bem como os repositórios onde podem ser encontradas, estão definidos no ficheiro de configuração do projeto Maven.

  • em [7], as bibliotecas necessárias ao projeto e que não são geridas pelo Maven,
  • em [7], o ficheiro [pom.xml] de configuração do projeto Maven. POM significa Project Object Model. Teremos de intervir diretamente neste ficheiro.

O ficheiro [pom.xml] gerado é o seguinte:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>istia.st</groupId>
  <artifactId>mv-exemple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mv-exemple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
  • as linhas 5 a 8 definem o objeto (artefacto) Java que será criado pelo projeto Maven. Estas informações provêm do assistente utilizado durante a criação do projeto:

Um objeto Maven é definido por quatro propriedades:

  • [groupId]: uma informação que se assemelha a um nome de pacote. Assim, as bibliotecas do framework Spring têm groupId=org.springframework, as do framework JSF têm groupId=javax.faces,
  • [artifactId]: o nome do objeto Maven. No grupo [org.springframework] encontram-se, assim, os seguintes artifactId: spring-context, spring-core, spring-beans, ... No grupo [javax.faces], encontram-se o artifactId e o jsf-api,
  • [version]: número de versão do artefacto Maven. Assim, o artefacto org.springframework.spring-core tem as seguintes versões: 2.5.4, 2.5.5, 2.5.6, 2.5.6.SECO1, ...
  • [packaging]: o formato do artefacto, na maioria das vezes war ou jar.

O nosso projeto Maven irá gerar um [jar] (linha 8) no grupo [istia.st] (linha 5), denominado [mv-exemple] (linha 6) e com a versão [1.0-SNAPSHOT] (linha 7). Estas quatro informações devem definir de forma única um artefacto Maven.

As linhas 17-24 enumeram as dependências do projeto Maven, ou seja, a lista das bibliotecas necessárias ao projeto. Cada biblioteca é definida por quatro elementos (groupId, artifactId, versão, embalagem). Quando a informação packaging está ausente, como neste caso, é utilizado o ficheiro JAR packaging. Acrescenta-se ainda outra informação, o «scope», que determina em que fases do ciclo de vida do projeto a biblioteca é necessária. O valor predefinido é «compile», o que indica que a biblioteca é necessária para a compilação e para a execução. O valor «test» significa que a biblioteca é necessária durante os testes do projeto. É o caso aqui com a biblioteca JUnit 3.8.1. Se esta biblioteca não estiver presente no repositório local do computador, é descarregada.

3.1.2. Execução do projeto

Executamos o projeto:

No [1], o projeto Maven é compilado e, em seguida, executado no [1]. Os registos na consola do NetBeans são os seguintes:

Scanning for projects...
...

------------------------------------------------------------------------
Building mv-exemple 1.0-SNAPSHOT
------------------------------------------------------------------------

[resources:resources]
[debug] execute contextualize
Using 'UTF-8' encoding to copy filtered resources.
skip non existing resourceDirectory D:\data\istia-1112\netbeans\glassfish\mv-pam\00\mv-exemple\src\main\resources

[compiler:compile]
Compiling 1 source file to D:\data\istia-1112\netbeans\glassfish\mv-pam\00\mv-exemple\target\classes

[exec:exec]
Downloading: http://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/1.0.1/commons-exec-1.0.1.pom

Downloaded: http://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/1.0.1/commons-exec-1.0.1.pom (8 KB a 113,5 KB/seg)
Downloading: http://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/1.0.1/commons-exec-1.0.1.jar

Downloaded: http://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/1.0.1/commons-exec-1.0.1.jar (49 KB a 763,6 KB/seg)
Hello World!
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 4.040s
Finished at: Thu Jun 21 10:10:40 CEST 2012
Final Memory: 13M/122M

O resultado está na linha 23. Vemos que, mesmo neste caso simples, o Maven descarregou alguns elementos (linhas 17 e 20).

3.1.3. O sistema de ficheiros de um projeto Maven

  • [1]: o sistema de ficheiros do projeto encontra-se no separador [Files],
  • [2]: os códigos-fonte Java encontram-se na pasta [src / main / java],
  • [3]: os códigos-fonte Java dos testes encontram-se na pasta [src / test / java],
  • [4]: a pasta [target] é criada durante a compilação (build) do projeto,
  • [5]: neste caso, a compilação do projeto criou um arquivo [mv-exemple-1.0-SNAPSHOT.jar].

3.1.4. O repositório Maven local

Já referimos que o Maven descarrega as dependências necessárias ao projeto e as armazena localmente. É possível explorar este repositório local:

  • em [1], seleciona-se a opção [Window / Other / Maven Repository Browser],
  • em [2], abre-se um separador [Maven Repositories],
  • em [3], este contém dois ramos, um para o repositório local e outro para o repositório central. Este último é gigantesco. Para visualizar o seu conteúdo, é necessário atualizar o seu índice [4]. Esta atualização demora várias dezenas de minutos.
  • em [5], as bibliotecas do repositório local,
  • em [6], encontra-se um ramo [istia.st] que corresponde ao [groupId] do nosso projeto,
  • em [7], acede-se às propriedades do repositório local,
  • em [8], temos o caminho do repositório local. É útil conhecê-lo, pois, por vezes (raramente), o Maven deixa de utilizar a versão mais recente do projeto. Fazemos alterações e verificamos que estas não são tidas em conta. Podemos então eliminar manualmente o ramo do repositório local correspondente ao nosso [groupId]. Isto obriga o Maven a recriar o ramo a partir da última versão do projeto.

3.1.5. Procurar um artefacto com o Maven

Vamos agora aprender a procurar um artefacto com o Maven. Comecemos pela lista de dependências atuais do ficheiro [pom.xml]:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>istia.st</groupId>
  <artifactId>mv-exemple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mv-exemple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

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

As linhas 17 a 23 definem dependências que vamos alterar para utilizar as bibliotecas na sua versão mais recente.

Em primeiro lugar, eliminamos as dependências atuais [1]. O ficheiro [pom.xml] é então alterado:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>istia.st</groupId>
  <artifactId>mv-exemple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mv-exemple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies></dependencies>
</project>

Na linha 17, a dependência removida já não aparece no ficheiro [pom.xml]. Agora, vamos procurá-la nos repositórios do Maven.

  • em [1], adiciona-se uma dependência ao projeto,
  • no [2], é necessário especificar informações sobre o artefacto procurado (groupId, artifactId, versão, embalagem (Tipo) e âmbito). Começamos por especificar o [groupId] [3],
  • em [4], digitamos [espace] para exibir a lista de artefactos possíveis. Aqui, [junit] e [jnit-dep]. Escolhemos [junit],
  • em [5], procedendo da mesma forma, escolhemos a versão mais recente. O tipo de empacotamento é jar,
  • e, no [6], selecionamos o escopo «teste» para indicar que a dependência é necessária apenas para os testes.

Em [6], as dependências adicionadas aparecem no projeto. O ficheiro [pom.xml] reflete estas alterações:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>istia.st</groupId>
  <artifactId>mv-exemple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mv-exemple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
      <type>jar</type>
    </dependency>
  </dependencies>
</project>

Note-se que o ficheiro [pom.xml] não menciona a dependência [hamcrest-core-1.1] que vemos em [6]. Isto porque se trata de uma dependência do JUnit 4.10 e não do próprio projeto. Tal é indicado por um ícone diferente no ramo [Dependencies]. Este foi descarregado automaticamente.

Suponhamos agora que não conhecemos o [groupId] do artefacto que pretendemos. Por exemplo, queremos utilizar o Hibernate como ORM (Object Relational Mapper) e é tudo o que sabemos. Podemos então aceder ao site [http://mvnrepository.com/]:

No [1], é possível introduzir palavras-chave. Digamos hibernate e iniciemos a pesquisa.

  • no [2], selecionemos o [groupId], o org.hibernate e o [artifactId], o hibernate-core,
  • em [3], escolhemos a versão 4.1.2-Final,
  • em [4], obtemos o código Maven para colar no ficheiro [pom.xml]. Fazemo-lo.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>istia.st</groupId>
  <artifactId>mv-exemple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mv-exemple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>4.1.2.Final</version>
    </dependency>
  </dependencies>
</project>

Guardamos o ficheiro [pom.xml]. O Maven inicia então o download das novas dependências. O projeto evolui da seguinte forma:

  • para [5], a dependência [hibernate-core-4.1.2-Final]. No repositório onde foi encontrado, este [artifactId] também é descrito por um ficheiro [pom.xml]. Este ficheiro foi lido e o Maven descobriu que o [artifactId] tinha dependências. Também as descarrega. Fará o mesmo para cada [artifactId] descarregado. No final, encontramos no [6] dependências que não tínhamos solicitado diretamente. Estas são assinaladas por um ícone diferente do do [artifactId] principal.

Neste documento, utilizamos o Maven principalmente por esta característica. Isto evita-nos ter de conhecer todas as dependências de uma biblioteca que pretendemos utilizar. Deixamos que o Maven as gere. Além disso, ao partilhar um ficheiro [pom.xml] entre programadores, temos a garantia de que cada programador utiliza efetivamente as mesmas bibliotecas.

Nos exemplos que se seguem, limitar-nos-emos a fornecer o ficheiro [pom.xml] utilizado. O leitor só terá de o utilizar para se encontrar nas mesmas condições que o documento. Além disso, os projetos Maven são reconhecidos pelos principais ambientes de desenvolvimento Java (Eclipse, NetBeans, IntelliJ, JDeveloper). Assim, o leitor poderá utilizar o seu IDE preferido para testar os exemplos.