quinta-feira, 19 de junho de 2014

Curso de Maven lição 3: O "ó" do borogodó!


É, caro amigo, cara amiga, me traz lágrimas aos olhos ver o quanto você se desenvolveu até aqui. Sö falta uma coisinha ou outra para te falar sobre o Maven. Só que essas coisinhas são o "ó do borogodó", então, sentae e acompanha mais um pouquinho, ok?

Vídeo da lição AQUI!!!

O "ó" do borogodó!


- Repositórios normais e de plugins
- Gerenciadores e Mirrors;
- Deploy de artefatos;
- Configuração de Site Maven;


Pra você ficar "pro" mesmo em Maven, só faltam essas coisinhas! Ai, você vai poder tirar onda no seu trabalho, esnobando a ajuda daquele nerd esquisito, que vive querendo te levar para uma convenção de "starwars".

Repositórios externos

O Maven possui um grande "ecossistema" de artefatos e plugins. Esse "ecossistema", em sua maioria, fica residente no "Repositório Central do Maven", cujo endereço é: http://repo.maven.apache.org/maven2/.

Você não pode navegar nesse repositório, pois isso atrapalharia o acesso. Ele é utilizado no mundo inteiro e você também pode publicar seus artefatos nele. Para consultar o repositório Central, eu recomendo o site: http://mvnrepository.com, que é muito rápido e prático.

Para baixar artefatos e plugins do Repositório Central, você não precisa fazer coisa alguma. Basta colocar o plugin ou a dependência em seu projeto e pronto! Ao executar um "build", o Maven vai verificar se aquele artefato, com aquela versão, já existe no seu repositório local (pasta ".m2"), e, caso não exista, ele vai baixar do Repositório Central.

E se o artefato ou o plugin não está no Repositório Central?

Nesse caso, você precisa informar qual é o repositório (ou repositórios) onde o Maven deve procurar seu artefato ou plugin. Um uso muito comum disso é quando nosso projeto depende de artefatos corporativos, criados por nossa Empresa, e que não desejamos disponibilizar no Repositório Central. Nesse caso, precisamos especificar de onde o Maven vai baixar a dependência. Isso é feito no "pom.xml":

<project>
...
  <repositories>
    <repository>
      <id>interno</id>
      <url>http://interno.empresa:8080/archiva/internal</url>
    </repository>
    <repository>
      <id>snapshots</id>
      <url>http://interno.empresa:8080/archiva/snapshots</url>
    </repository>
  </repositories>
...
</project>


Outra maneira é informar os repositórios dentro de um "pom" pai, ou criar um "profile" dentro do "settings.xml":

<settings>
 ...
 <profiles>
   ...
   <profile>
     <id>corporativo</id>
<repositories>
       <repository>
         <id>interno</id>
         <url>http://interno.empresa:8080/archiva/internal</url>
       </repository>
       <repository>
         <id>snapshots</id>
         <url>http://interno.empresa:8080/archiva/snapshots</url>
       </repository>
     </repositories>
</profile> ... </profiles>


Desta forma, o Maven vai tentar buscar sua dependência nos repositórios que você colocou (e também no Repositório Central).

Repositórios de Plugins

Os plugins, assim como as dependências, ficam armazenados em repositórios externos. A maioria deles fica no Repositório Central Maven, porém, alguns podem ter seus próprios repositórios, como o jQana, por exemplo. Neste caso, você precisa indicar em qual (ais) Repositório Externo o Maven deve procurar o plugin. Isso é feito com o tag "<pluginRepository>". Vamos ver um exemplo:

<pluginRepositories>
    <pluginRepository>
        <id>jqana-mvn-repo</id>
        <url>https://raw.github.com/cleuton/jqana/mvn-repo/</url>
    </pluginRepository>
</pluginRepositories>
É muito importante que você entenda isso:

  • Repositórios externos de dependências são configurados com "<repository>";
  • Repositórios externos de plugins são configurados com "<pluginRepository>";
Assim como os repositórios externos de dependências, os repositórios externos de plugins podem ser configurados em "profiles", tanto no "pom.xml" como no "settings.xml".


Repositórios de espelhamento - Mirror

Você viu que temos dois tipos de repositórios: O Repositório Local e os Repositórios Externos, e que o Repositório Central do Maven é o principal deles.

Sempre que você executa um "build", o Maven busca os plugins e as dependências do seu repositório local, ou seja, a pasta ".m2". Vamos ver. novamente, como fica organizado um repositório, por exemplo, o seu repositório local:



Os artefatos ficam organizados em pastas, por "groupId", "artifactId" e "version", o que facilita a sua localização. Cada elemento do "groupId" vira uma pasta, por exemplo, o artefato: "com.teste.projeto", versão "1.0.0-SNAPSHOT", ficou armazenado na estrutura de pastas: "repository/com/teste/projeto/1.0.0-SNAPSHOT".

Porém, pode ser que você esteja usando uma versão diferente, que ainda não esteja em seu repositório local. Neste caso, o Maven precisa baixar do Repositório Externo para o Repositório Local. Com o tempo, seu Repositório Local tende a ficar cheio de arquivos JAR.

Isso nos faz pensar um pouco: Esse negócio de ficar baixando da Internet deve tornar o "build" lento! Sim, e como! Mas não é só isso... E se o repositório externo estiver fora do ar? E se a conexão com a Internet cair?

Podemos criar Repositórios de Espelhamento, ou "Mirror", dentro da nossa própria Rede. Neste caso, o Maven buscará as dependências e plugins necessários em nossos próprios repositórios de espelhamento. Se alguma dependência não existir neles, eles se encarregarão de buscar no verdadeiro repositório externo.

Gerenciadores de Repositórios

Para criar Repositórios de Espelhamento, precisamos de um software que gerencie Repositórios. Os mais populares são:

  • Apache Archiva;
  • Sonatype Nexus (tem uma versão free e uma versão paga);
Uma vez que você instalou o Gerenciador, pode configurar "proxies"para criar Repositórios de Espelhamento. Então, sempre que vier um pedido de Artefato, o Repositório Mirror pode consultar o Repositório Externo para saber se deve baixar a versão necessária, ou se pode usar a que ele contém.

Configurando Mirrors

Antes de usarmos mirrors, devemos configurá-los no "settings.xml". Seu uso é totalmente transparente para os projetos, pois o "pom.xml" não precisa ser modificado. Basta criarmos um ou mais tags "<mirror>":


<settings ...>
  ...
  <mirrors>
    <mirror>
      <id>mirror1/id>
      <url>http://archiva.rede:8080/repository/internal</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
  ...
</settings>


Note que especificamos "O QUÊ" este repositório está espelhando, no caso, o Repositório Central do Maven ("<mirrorOf>central</mirrorOf>".

Podemos especificar outras opções de espelhamento, por exemplo: 
  • Espelho de componentes de versão "internal";
  • Espelho de componentes "Snapshot";
  • Espelho de tudo;
  • Espelho de determinados repositórios;
Por exemplo, a seguinte configuração de mirror diz que o repositório é o espelho de TUDO: 


<settings ...>
  ...
  <mirrors>
    <mirror>
      <id>internal/id>
      <url>http://localhost:8080/repository/internal</url>
      <mirrorOf>*</mirrorOf>
    </mirror>
  </mirrors>
  ...
</settings>


Exercício 1: Configurando mirror

É isso aí! Vamos fazer um exercício! Para começar, baixe o "Apache Arquiva" e instale em sua máquina:

  1. Baixe o Apache Archiva;
  2. Descompacte o ZIP em sua máquina (qualquer pasta);
  3. Execute o Archiva: 
    1. Windows: %PASTA%/bin/archiva.bat console
    2. Linux / Mac: $PASTA/bin/archiva console
É claro que você pode instalar o Archiva como um serviço, mas isso é assunto para outro curso. Vamos apenas executar no Terminal, daí o argumento "console".

Agora, abra a console do Archiva em um Navegador. O Endereço é: "http://localhost:8080", e veja se a página inicial está aparecendo: 




A primeira coisa a fazer é criar um usuário administrativo, clicando no botão vermelho "Create admin user". Guarde bem a senha que você criou.

Você verá que o Archiva já criou dois repositórios para nós. Para isso, clique no link "Repositories", na coluna lateral esquerda:

Temos um repositório "internal", para artefatos publicados, e um "snapshots", para artefatos em desenvolvimento. Você pode acessar esses repositórios usando suas URLs padrões:

  • "http://localhost:8080/repository/internal/"para o repositório de artefatos publicados;
  • "http://localhost:8080/repository/snapshots/" para o repositório de artefatos em desenvolvimento;
E, se abrirmos a configuração de "Proxy Connectors", veremos que já temos um Espelhamento do Repositório Central Maven configurado: 

Isso significa que podemos usar o nosso repositório "internal" como "Mirror" do Repositório Central do Maven. Então, vamos configurar isso no "settings.xml". Vambora, isso faz parte do exercício!

Agora, para concluir o exercício, apaque o conteúdo do seu repositório local. Entre na pasta ".m2", abra a pasta "repository" e apague tudo o que está lá.

Configure um "Mirror" em seu "settings.xml" (dentro da pasta ".m2") e aponte para a URL do repositório "internal".

Finalmente, execute um "build" Maven de qualquer projeto que criamos nas aulas passadas. 

Execute um "mvn clean package" e note que as dependências estão sendo baixadas de "localhost:8080":


Downloaded: http://localhost:8080/repository/internal/org/apache/maven/maven-archiver/2.5/maven-archiver-2.5.jar (22 KB at 21.6 KB/sec)
Downloaded: http://localhost:8080/repository/internal/org/codehaus/plexus/plexus-archiver/2.1/plexus-archiver-2.1.jar (181 KB at 163.9 KB/sec)
Downloaded: http://localhost:8080/repository/internal/org/codehaus/plexus/plexus-interpolation/1.15/plexus-interpolation-1.15.jar (60 KB at 51.6 KB/sec)
Downloaded: http://localhost:8080/repository/internal/commons-lang/commons-lang/2.1/commons-lang-2.1.jar (203 KB at 151.5 KB/sec)
[INFO] Building jar: /Users/cleutonsampaio/Documents/cursomaven/projetoteste/target/projetoteste-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25.167 s
[INFO] Finished at: 2014-06-18T07:03:25-03:00
[INFO] Final Memory: 11M/81M
[INFO] ------------------------------------------------------------------------

Agora, abra a url do repositório "internal" em seu navegador: http://localhost:8080/repository/internal

Note que o repositório "internal" agora contém vários artefatos Maven, que foram baixados do Repositório Central, pois ele é um "Espelho". Daqui para a frente, se o Maven não encontrar um plugin ou dependência no Repositório Local, irá no "Mirror", que, por sua vez, copiará do Repositório Central.

É um "cache" de Repositório!

Deploy de artefatos

O ciclo de vida de construção de aplicativos é mais ou menos esse:

  1. Análise de requisitos;
  2. Projeto;
  3. Construção;
  4. Testes;
  5. Entrega.
Eventualmente, chegamos à etapa de entrega, durante a qual devemos entregar uma versão executável e completamente funcional do nosso Software. Na Entrega, publicamos uma versão completa e executável, que pode ser um "Snapshot", ou seja uma versão intermediária, ou então uma versão final, também conhecida como "internal".

Nós já vimos como instalar versões dos artefatos gerados por nossos projetos Maven em nosso Repositório Local (a pasta ".m2"). Isso é feito com a fase Maven "install": 

mvn clean install

Porém, se estamos desenvolvendo em equipe, é melhor usarmos repositórios Externos, gerenciados por um software como o Apache Archiva. E podemos instalar versões dos nossos artefatos nele, só que, para isso, usamos a fase "deploy":

mvn clean deploy

O "deploy plugin" vai instalar o nosso artefato no repositório apropriado, dependendo se ele é uma versão "internal" ou "snapshot". Lembrando que versão "snapshot" é apropriada para desenvolvimento apenas.

Configurando repositórios para deploy

Para que o "deploy" funcione, é necessário configurar o repositório para onde devemos copiá-lo. Isso é feito através do tag "<distributionManagement>". Por exemplo: 


<project ...>
  ...
  <distributionManagement>
      <repository>
          <id>internal</id>
          <url>http://localhost:8080/repository/internal</url>
      </repository>
      <snapshotRepository>
          <id>snapshots</id>
          <url>http://localhost:8080/repository/snapshots</url>
      </snapshotRepository>
  </distributionManagement>
  ...
</project>



Temos dois repositórios: "internal" e "snapshots". Esses nomes são importantes, pois o Maven conhece os repositórios através do seu "<id>". Se a versão do seu Projeto contiver o sufixo "-SNAPSHOTS", então ele será instalado no repositório "<snapshotRepository>", caso contrário, será no "<repository>".

Porém, se tentarmos rodar um "mvn deploy", tomaremos um erro HTTP status 401.

Note que estamos usando o protocolo "http" na URL dos repositórios, então, o Maven Deploy Plugin tentará enviar o JAR usando esse protocolo. O status 401 é quando não temos autorização para gravar o arquivo no repositório.

Precisamos configurar as credenciais de gravação em cada um dos repositórios, e isso é feito no "settings.xml":

<settings ...>
...
  <servers>
      <server>
          <id>internal</id>
          <username>admin</username>
          <password>admin1</password>
      </server>
      <server>
          <id>snapshots</id>
          <username>admin</username>
          <password>admin1</password>
      </server>
  </servers>
...
</settings>

O "<id>" conecta a informação de credencial, especificada no "settings.xml", à URL do repositório, especificada no "pom.xml". O "<username>" e "<password>" são específicos do protocolo utilizado para "deploy". No nosso caso, foi "http", logo, o Maven Deploy Plugin vai tentar se autenticar no Archiva com esse "<username>" e "<password>" para tentar fazer o "upload".

Existem outros protocolos, por exemplo: "scp", "webdav" e "file", cada um tem o seu mecanismo de credenciais específico, que deve ser configurado no "settings.xml".

Exercício 2: Faça "deploys"

Pegue um dos projetos que já criamos e faça dois deploys: Um para o repositório de Snapshots do Archiva e outro para o repositório "internal".

Dicas:

  1. Suba o Archiva, como já fizemos antes;
  2. Altere o "settings.xml", para incluir as credenciais de autorização. Lembre-se do usuário "admin" e da senha que você criou no exercício passado;
  3. Altere o "pom.xml" para configurar o "<distributionManagement>";
  4. Faça o deploy usando a versão "-SNAPSHOT", depois, altere a versão, retirando o sufixo, e faça o deploy novamente;
  5. Verifique se o deploy foi feito utilizando a interface web do Archiva: http://localhost:8080";

  • "http://localhost:8080/repository/internal"para o repositório de artefatos publicados;
  • "http://localhost:8080/repository/snapshots" para o repositório de artefatos em desenvolvimento;
Podemos verificar se o deploy foi feito usando a opção "Browse", do Archiva, e escolhendo o repositório apropriado.

Configuração de Site Maven

Você já ouviu falar do Site Maven de um Projeto? Não? É um conjunto de informações, a maioria retirada do "pom.xml", em forma de páginas HTML. É a documentação do seu projeto toda prontinha! Para dar um exemplo, veja o Site Maven do jQana, a minha ferramenta de análise de código:

Entre no site do jQana e veja por si mesmo (a).

Este site é gerado pelo "maven-site-plugin", acionado pelo comando: "mvn site". Se pegarmos qualquer projeto que criamos nas aulas anteriores e rodarmos esse comando, o que sairá? Após rodar o comando, abra a pasta "target/site" e note que existem páginas html lá. Abra a página "index.html" em um navegador.


Note que o site foi criado, mas não tem muita informação... Por exemplo, abra o link "project team" e veja que não contém as informações esperadas. Podemos mudar isso!

Para começar, podemos acrescentar alguns elementos no "pom.xml" que estão faltando, entre eles:

  • A licença do projeto; 
  • A equipe;
  • O repositório de código-fonte (SCM);
Estas três informações podem ser acrescentadas com os tags: 


<licenses>
  <license>
    <name>Apache License, Version 2.0</name>
    <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
    <distribution>repo</distribution>
    <comments>Licença de uso permissiva</comments>
  </license>
</licenses>

<developers>
    <developer>
      <id>cleuton</id>
      <name>Cleuton</name>
      <email>cleuton@teste.com</email>
      <organization>O Bom Programador</organization>
      <organizationUrl>http://www.obomprogramador.com</organizationUrl>
      <roles>
        <role>architect</role>
        <role>developer</role>
      </roles>
      <timezone>-3</timezone>
      <properties>
        <picUrl>http://picasaweb.com/foto20394</picUrl>
      </properties>
    </developer>
  </developers>

<scm>
    <connection>scm:svn:http://127.0.0.1/svn/projeto1</connection>
    <developerConnection>scm:svn:https://127.0.0.1/svn/projeto1</developerConnection>
    <tag>HEAD</tag>
    <url>http://127.0.0.1/websvn/projeto1</url>
  </scm>

Experimente colocar esses tags no "pom.xml" e rode novamente o "mvn clean site". Agora, você tem informação disponível nos links "Source reposittory", "Project team" e "Project license". Existem muito mais informações que você pode fazer aparecer no Site só usando o "pom.xml", por exemplo:

<issueManagement>
    <system>Bugzilla</system>
    <url>http://127.0.0.1/bugzilla/</url>
  </issueManagement> 


Serve para indicar qual é o site de "issue management", ou seja, de problemas, do projeto, que aparece quando selecionamos o link "Issue tracking" no Site. Outra boa informação é:

<mailingLists>
    <mailingList>
      <name>Lista de usuários</name>
      <subscribe>user-subscribe@127.0.0.1</subscribe>
      <unsubscribe>user-unsubscribe@127.0.0.1</unsubscribe>
      <post>user@127.0.0.1</post>
      <archive>http://127.0.0.1/user/</archive>
      <otherArchives>
        <otherArchive>http://base.google.com/base/1/127.0.0.1</otherArchive>
      </otherArchives>
    </mailingList>
  </mailingLists>

Serve para mostrarmos os links para listas de email do Projeto.

Se você quiser ver um "pom.xml" mais detalhado, eu sugiro que consulte o do jQana, cujo relatório é muito completo.

Como configurar o conteúdo do site

Você deve ter notado que, apesar disso, o conteúdo do site, pelo menos o link "About" continua sem informação. Para configurar isso, precisamos mudar o layout do Site Maven, e isso é feito através do diretório: "src/site". Veja a estrutura:

+- src/
   +- site/
      +- apt/
      |  +- index.apt
      |
      +- fml/
      |  +- general.fml
      |  +- faq.fml
      |
      +- xdoc/
      |  +- other.xml
      |
      +- site.xml

Esta pasta "src/site" serve para configurar o Site Maven. O arquivo "site.xml" permite configurar os links e a aparência. O conteúdo pode ser acrescentado através de arquivos de "template", em 3 formatos diferentes: "apt", "fml" ou "xdoc". O formato "apt" é mais simples e é quase texto puro. Por exemplo, vamos criar uma página inicial para nosso projeto. Digite esse texto EXATAMENTE como está vendo, criando um arquivo "sobre.apt", dentro da pasta "src/site/apt":

Projeto de teste
    Este é um projeto de teste que eu criei com o Maven Archetype Plugin.

Muito Importante: TENHA CERTEZA DE USAR CODIFICAÇÃO UTF-8 para os caracteres acentuados!

Agora, crie um arquivo "site.xml" com esse conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
<project name="projetoteste">

    <body>
        <menu ref="modules" />
        <menu ref="reports"/>
    </body>
</project>

Note que estamos referenciando dois conjuntos de relatórios, gerados pelo Maven Site. Um deles é um "modules", que contém todas as informações geradas a partir do "pom.xml", que são as mesmas que já vimos antes. E o outro é o "reports", que inclui todos os relatórios gerados a partir do "build".

Antes de finalizar, devemos configurar o plugin Maven Site para aceitar caracteres acentuados codificados como UTF-8, daí a importância de você usar a codificação correta ao criar o arquivo "index.apt". Para isto, configuramos o Plugin Maven Site no "pom.xml":

  <build>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-site-plugin</artifactId>
              <version>3.3</version>
              <configuration>
                  <inputEncoding>UTF-8</inputEncoding>
              </configuration>
          </plugin>
      </plugins>

  </build>

Agora, rode um "mvn clean site" e veja o resultado.

Nós usamos o formato APT, do Doxia, para criar um arquivo "index.apt". Existem outros formatos, descritos AQUI. E o formato do arquivo APT é descrito NESSE SITE.

Fazendo deploy do Site

Se você quiser fazer deploy do site Maven para uma pasta remota, por exemplo, para ser servida via HTTP por um Servidor Web, então precisa fazer duas coisas: Configurar o "<distributionManagement>" e rodar "mvn site:deploy".

O tag "<distributionManagement>" tem um subtag "<site>" que serve para configurar para onde o site deve ser enviado:

  <distributionManagement>
    ...
    <site>
      <id>sitesmaven</id>
      <url>dav:https://sitesmaven.empresa.com/publico</url>
    </site>
    ...
  </distributionManagement>

Neste exemplo, estamos usando o protocolo WebDav para a publicação do Site Maven. É claro que será exigida uma credencial de acesso, que deve ser configurada no seu arquivo "settings.xml":

  <servers>
      <server>
          <id>sitesmaven</id>
          <username>usuariodav</username>
          <password>dav1001</password>
      </server>
...
</servers>


Como eu disse antes, existem vários protocolos, desde "file" até "scp", dependendo de como foi configurada sua rede. O protocolo "dav" é bom porque ultrapassa firewalls sem problemas.

Finalmente, rode o comando "mvn site:deploy" e, ao final, consulte seu site usando HTTP.

Podemos exercitar isso mesmo sem ter um servidor:

  1. Crie uma pasta "sitemaven" em qualquer lugar do seu disco (guarde o caminho);
  2. Configure o "distributionManagement";
  3. Rode o "mvn clean site:deploy".
Nem precisa alterar o "settings.xml", afinal, você está rodando na mesma máquina e com o seu usuário, o qual, logicamente, tem acesso à pasta. Eis a minha configuração do "pom.xml":


  <distributionManagement>
      <repository>
          <id>internal</id>
          <url>http://localhost:8080/repository/internal</url>
      </repository>
      <snapshotRepository>
          <id>snapshots</id>
          <url>http://localhost:8080/repository/snapshots</url>
      </snapshotRepository>
      <site>
          <id>pasta</id>
          <url>file:///Users/cleutonsampaio/Documents/cursomaven/sitemaven</url>
      </site>
  </distributionManagement>


Conclusão

Bão! Você, certamente, ainda não sabe tudo sobre o Maven. Nem eu mesmo, que uso e trabalho com isso há anos, posso afirma que sei. Porém, você já sabe o suficiente para se "virar" e ajudar os outros. 


Acompanhe as lições do curso Maven Pro: