Skip to content

3. Ferramentas utilizadas neste documento

Os exemplos neste documento foram testados com as seguintes ferramentas:

  • NetBeans versões 6.8 a 7.1.2. A instalação do NetBeans é descrita em [ref3], na secção 1.3.1.
  • WampServer versão 2.2. A instalação do WampServer é descrita em [ref3], na secção 1.3.3;
  • O Maven está integrado no NetBeans. Passaremos 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 esforço de desenvolvimento no menor tempo possível. Para atingir este objetivo, existem várias áreas-chave que o Maven aborda:

  • 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 a migração sem problemas para novas funcionalidades

O Maven está integrado no NetBeans, e iremos utilizá-lo apenas para uma das suas funcionalidades: a gestão das bibliotecas de um projeto. Estas consistem em todos os ficheiros JAR que devem estar no classpath do projeto. Pode haver um grande número deles. Por exemplo, os nossos projetos futuros irão utilizar o ORM (Object-Relational Mapper) Hibernate. Este ORM é composto por dezenas de ficheiros JAR. A vantagem do Maven é que nos liberta da necessidade de os conhecermos todos. Basta especificarmos no nosso projeto que precisamos do Hibernate, fornecendo todas as informações necessárias para localizar o ficheiro JAR principal deste ORM. O Maven descarrega então também todas as bibliotecas exigidas pelo Hibernate. Estas são chamadas de dependências do Hibernate. Uma biblioteca exigida pelo Hibernate pode, por sua vez, depender de outros arquivos. Estes também serão descarregados. Todas estas bibliotecas são colocadas numa pasta chamada repositório local do Maven.

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

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

Vamos criar um projeto Maven no NetBeans:

  • Em [1], crie um novo projeto,
  • em [2], selecione a categoria [Maven] e o tipo de projeto [Aplicação Java],
  • em [3], especifique o diretório pai para o novo projeto,
  • em [4], nomeie o projeto,
  • em [5], o projeto gerado.

Vamos examinar os componentes do projeto e explicar a função de cada um.

  • em [1]: os diferentes ramos do projeto:
    • [Pacotes de código-fonte]: as classes Java do projeto;
    • [Pacotes de teste]: as classes de teste do projeto;
    • [Dependências]: os arquivos .jar necessários para o projeto e geridos pelo Maven;
    • [Dependências de teste]: os ficheiros .jar necessários para os testes do projeto e geridos pelo Maven;
    • [Dependências Java]: os ficheiros .jar necessários ao projeto e não geridos pelo Maven;
    • [Ficheiros do projeto]: ficheiros de configuração do Maven e do NetBeans,
  • em [3], o ramo [Pacotes de código-fonte],

Este ramo contém o código-fonte das classes Java do projeto. O NetBeans gerou uma classe padrã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 o código-fonte das classes de teste do projeto,
  • em [5], a biblioteca JUnit 3.8 necessária para executar os testes,

O NetBeans gerou uma classe padrã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);
    }
}

Este é um teste JUnit 3.8. Mais tarde, utilizaremos testes JUnit 4.x.

  • Em [6], a secção [Dependências] está vazia aqui,

Esta secção 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 requer acesso à Internet. As bibliotecas descarregadas serão armazenadas localmente. Se outro projeto precisar de uma biblioteca que já esteja 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, mas não geridas pelo Maven,
  • em [7], o ficheiro de configuração [pom.xml] do projeto Maven. POM significa Project Object Model. Teremos de editar este ficheiro diretamente.

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–8 definem o artefacto Java que será criado pelo projeto Maven. Esta informação provém do assistente utilizado durante a criação do projeto:

Um artefacto Maven é definido por quatro propriedades:

  • [groupId]: informação semelhante a um nome de pacote. Por exemplo, as bibliotecas do framework Spring têm groupId=org.springframework, enquanto as do framework JSF têm groupId=javax.faces,
  • [artifactId]: o nome do artefacto Maven. No grupo [org.springframework], encontramos os seguintes artifactIDs: spring-context, spring-core, spring-beans, ... No grupo [javax.faces], encontramos o artifactId jsf-api,
  • [version]: o número da 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, mais frequentemente war ou jar.

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

As linhas 17–24 listam as dependências do projeto Maven, ou seja, a lista de bibliotecas necessárias ao projeto. Cada biblioteca é definida pelas quatro informações (groupId, artifactId, version, packaging). Quando a informação de packaging está em falta, como neste caso, é utilizada a embalagem jar. É adicionada outra informação: scope, que especifica 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 execução. O valor test significa que a biblioteca é necessária durante os testes do projeto. É o que acontece aqui com a biblioteca JUnit 3.8.1. Se esta biblioteca não estiver presente no repositório local da máquina, é descarregada.

3.1.2. Executar o projeto

Executamos o projeto:

Em [1], o projeto Maven é compilado e, em seguida, executado [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 at 113.5 KB/sec)
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 at 763.6 KB/sec)
Hello World!
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 4.040s
Finished at: Thu Jun 21 10:10:40 CEST 2012
Final Memory: 13M/122M

O resultado é a linha 23. Podemos ver que, mesmo neste caso simples, o Maven descarregou algumas dependências (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 [Ficheiros],
  • [2]: os códigos-fonte Java encontram-se na pasta [src/main/java],
  • [3]: os códigos-fonte de teste Java estão na pasta [src/test/java],
  • [4]: a pasta [target] é criada pela compilação do projeto,
  • [5]: Aqui, a compilação do projeto criou um arquivo [mv-example-1.0-SNAPSHOT.jar].

3.1.4. O Repositório Local do Maven

Mencionámos que o Maven descarrega as dependências necessárias para o projeto e as armazena localmente. Pode explorar este repositório local:

  • em [1], selecione a opção [Janela / Outros / Navegador de Repositórios Maven],
  • em [2], abre-se o separador [Maven Repositories],
  • em [3], esta contém duas ramificações, uma para o repositório local e outra para o repositório central. Este último é enorme. 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 no repositório local,
  • em [6], encontrará um ramo [istia.st] que corresponde ao [groupId] do nosso projeto,
  • em [7], pode aceder às propriedades do repositório local,
  • em [8], vê o caminho para o repositório local. É útil saber isto porque, por vezes (raramente), o Maven deixa de utilizar a versão mais recente do projeto. Faz alterações e repara que estas não estão a ser aplicadas. Pode então eliminar manualmente o ramo no repositório local correspondente ao seu [groupId]. Isto obriga o Maven a recriar o ramo a partir da versão mais recente do projeto.

3.1.5. Pesquisar um artefacto com o Maven

Agora vamos aprender a pesquisar um artefacto com o Maven. Comecemos pela lista de dependências atuais no 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–23 definem as dependências que iremos modificar para utilizar as versões mais recentes das bibliotecas.

Primeiro, removemos as dependências atuais [1]. O ficheiro [pom.xml] é então modificado:


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

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

  • Em [1], adicionamos uma dependência ao projeto;
  • em [2], temos de especificar informações sobre o artefacto que procuramos (groupId, artifactId, versão, embalagem (Tipo) e âmbito). Começamos por especificar o [groupId] [3],
  • em [4], premimos [espaço] para exibir a lista de artefactos possíveis. Aqui, [junit] e [jnit-dep]. Escolhemos [junit],
  • em [5], seguindo o mesmo procedimento, selecionamos a versão mais recente. O tipo de empacotamento é jar,
  • em [6], selecionamos o âmbito de teste para indicar que a dependência é necessária apenas para 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 que o ficheiro [pom.xml] não menciona a dependência [hamcrest-core-1.1] apresentada em [6]. Isto deve-se ao facto de se tratar de uma dependência do JUnit 4.10 e não do próprio projeto. Isto é indicado por um ícone diferente no ramo [Dependencies]. Foi descarregada automaticamente.

Agora, suponha que não sabemos o [groupId] do artefacto que queremos. Por exemplo, queremos usar o Hibernate como um ORM (Object Relational Mapper), e isso é tudo o que sabemos. Podemos então ir ao site [http://mvnrepository.com/]:

Em [1], pode introduzir palavras-chave. Digite hibernate e execute a pesquisa.

  • Em [2], selecione o [groupId] org.hibernate e o [artifactId] hibernate-core,
  • Em [3], selecione a versão 4.1.2-Final,
  • em [4], obtemos o código Maven para colar no ficheiro [pom.xml]. Vamos fazer isso.

<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 descarrega então as novas dependências. O projeto evolui da seguinte forma:

  • em [5], a dependência [hibernate-core-4.1.2-Final]. No repositório onde foi encontrada, este [artifactId] também é descrito por um ficheiro [pom.xml]. Este ficheiro foi lido e o Maven descobriu que o [artifactId] tinha dependências. Ele descarrega-as também. Fará isto para cada [artifactId] descarregado. Por fim, encontramos em [6] dependências que não solicitámos diretamente. Estas são indicadas por um ícone diferente do do [artifactId] principal.

Neste documento, utilizamos o Maven principalmente por esta funcionalidade. Isto evita que tenhamos 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 os programadores, garantimos que todos os programadores estão, de facto, a utilizar as mesmas bibliotecas.

Nos exemplos que se seguem, iremos simplesmente fornecer o ficheiro [pom.xml] utilizado. O leitor apenas precisa de o utilizar para replicar as condições descritas no documento. Além disso, os projetos Maven são suportados pelas principais IDEs Java (Eclipse, NetBeans, IntelliJ, JDeveloper). Assim, o leitor pode utilizar a sua IDE preferida para testar os exemplos.