Como especificar a distribuição do maven em toda a organização?

110

Estou tentando descobrir como organizar muitos (cerca de 50+) projetos maven2, para que eles possam implantar em um repositório central do Nexus. Ao usar a mvn deploymeta, é necessário especificar o destino na tag DistributionManagement como este:

<distributionManagement>
   <repository>
      <id>nexus-site</id>
        <url>http://central_nexus/server</url>
   </repository>
</distributionManagement>

Agora, eu não quero que cada pom.xml (daqueles 50+) contenha este bloco repetidamente. Meu primeiro pensamento seria o settings.xmlarquivo, mas parece que não é possível (por design) defini-lo lá. Então, a primeira pergunta seria: por que isso acontece? Se fosse possível, eu poderia especificá-lo no settings.xml da distribuição maven2, que poderia ser distribuído a todos os desenvolvedores.

A única solução possível que encontrei foi criar um projeto master-pom para toda a organização, que contenha essas configurações, e fazer todos os outros pom.xml dependerem desse master-pom via <parent>tag. Mas isso parece meio estranho em compilações de vários módulos:

- master configuration POM (pm)
- Project 1 parent pom (p1 with module 1 and module 2 as modules)
    - Project 1 module pom (with pm as parent)
    - Project 2 module pom (with pm as parent)

Normalmente eu li em toda a documentação que o módulo poms deve usar o pom pai, não algum diferente. Mas depois de ler o site maven sobre Herança x Agregação, está escrito que é realmente possível.

Um problema que encontrei foi com a geração do site maven, que parece ter problemas com esta configuração (os módulos não são vinculados corretamente se não tiverem uma referência direta)

Então, esta é uma abordagem válida? Alguma outra solução mais simples e óbvia para o problema?

mglauche
fonte
5
@OhadR: Eles apenas escrevem como escrever em um projeto. O ponto é que eu não queria duplicá-lo cerca de 500 vezes ...
mglauche
1
Entendo. ponto tomado. então como disse quem respondeu, você pode ter um pom principal para o projeto, que conterá o 'distribMngmnt' ...
OhadR

Respostas:

144

A melhor solução para isso é criar um projeto de arquivo pom pai simples (com empacotamento 'pom') genericamente para todos os projetos de sua organização.

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>your.company</groupId>
    <artifactId>company-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <distributionManagement>
        <repository>
            <id>nexus-site</id>
            <url>http://central_nexus/server</url>
        </repository>
    </distributionManagement>

</project>

Isso pode ser construído, lançado e implantado em seu nexo local para que todos tenham acesso a seu artefato.

Agora, para todos os projetos que você deseja usar, basta incluir esta seção:

<parent>
  <groupId>your.company</groupId>
  <artifactId>company-parent</artifactId>
  <version>1.0.0</version>
</parent>

Esta solução permite adicionar facilmente outras coisas comuns a todos os projetos da sua empresa. Por exemplo, se você quiser padronizar o uso do JUnit para uma versão específica, este seria o lugar perfeito para isso.

Se você tem projetos que usam estruturas de vários módulos que têm seus próprios pais, o Maven também suporta herança de encadeamento, então é perfeitamente aceitável fazer o arquivo pom pai do seu projeto referir-se ao pom pai da sua empresa e ter os módulos filhos do projeto nem mesmo cientes de seu pai da empresa.

Vejo em sua estrutura de projeto de exemplo que você está tentando colocar seu projeto pai no mesmo nível de seu pom agregador. Se seu projeto precisa de seu próprio pai, a melhor abordagem que encontrei é incluir o pai no mesmo nível que o resto dos módulos e ter seu arquivo pom.xml agregador na raiz de onde existem todos os diretórios de seus módulos.

- pom.xml (aggregator)
    - project-parent
    - project-module1
    - project-module2

O que você faz com essa estrutura é incluir seu módulo pai no agregador e construir tudo com um mvn installdo diretório raiz.

Usamos essa solução exata na minha organização e ela resistiu ao teste do tempo e funcionou muito bem para nós.

Jesse Webb
fonte
Aqui está outra resposta onde descrevo a herança do projeto em mais detalhes e como gerenciar sua complexidade de herança, com o perdão do trocadilho. ;) stackoverflow.com/questions/6347913
Jesse Webb
7
Apenas uma pequena observação: para os motivos pelos quais a empresa-mãe é a melhor solução, consulte a discussão Não é possível especificar o gerenciamento de distribuição em settings.xml da lista de usuários do Maven.
Premek Brada,
No modelo clássico de consultoria, em que "o cliente possui o código", minha equipe de desenvolvimento precisará trabalhar no projeto fora do local e, em seguida, levar o código mais recente para o local do cliente e compilá-lo novamente. Na minha situação, trabalhando com um projeto multi-módulo, se eu fizer referência ao POM da empresa no POM pai do projeto, terei que atualizar essa referência para apontar para o POM da empresa do cliente. Prefiro me esforçar para manter todas as configurações específicas do ambiente em settings.xml se puder ajudar. Qual é a abordagem recomendada para minha situação?
Usuário da web de
2
@WebUser Seu problema parece mais uma situação em que você precisa de valores diferentes em seu (s) arquivo (s) POM, em oposição ao que esta resposta aborda: evitando configurações duplicadas em vários módulos. Acho que você deve tentar injetar propriedades por meio de um arquivo settings.xml . Se isso não ajudar você, faça uma nova pergunta aqui no SO, link para ela aqui, e tentarei ajudá-lo ainda mais.
Jesse Webb
Obrigado @JesseWebb. Acabei experimentando isso e é útil abstrair esses valores do POM para a situação que descrevi. Para minhas necessidades, adicionei propriedades relevantes no perfil ativo e aquelas resolvidas no POM.
Usuário da web
36

Não há necessidade de um POM pai.

Você pode omitir a parte DistributionManagement inteiramente em seu poms e configurá-lo em seu servidor de compilação ou em settings.xml.

Para fazer isso no servidor de compilação, basta passar para o mvncomando:

-DaltSnapshotDeploymentRepository=snapshots::default::https://YOUR_NEXUS_URL/snapshots
-DaltReleaseDeploymentRepository=releases::default::https://YOUR_NEXUS_URL/releases

Consulte https://maven.apache.org/plugins/maven-deploy-plugin/deploy-mojo.html para obter detalhes sobre quais opções podem ser definidas.

Também é possível definir isso no seu settings.xml.

Basta criar um perfil que esteja habilitado e contenha a propriedade.

Configurações de exemplo.xml:

<settings>
[...]
  <profiles>
    <profile>
      <id>nexus</id>
      <properties>
        <altSnapshotDeploymentRepository>snapshots::default::https://YOUR_NEXUS_URL/snapshots</altSnapshotDeploymentRepository>
        <altReleaseDeploymentRepository>releases::default::https://YOUR_NEXUS_URL/releases</altReleaseDeploymentRepository>
      </properties>
    </profile>
  </profiles>

  <activeProfiles>
    <activeProfile>nexus</activeProfile>
  </activeProfiles>

</settings>

Certifique-se de que as credenciais para "instantâneos" e "lançamentos" estão na <servers>seção de seu settings.xml

As propriedades altSnapshotDeploymentRepository e altReleaseDeploymentRepository são apresentadas com maven-deploy-plugin versão 2.8. Versões mais antigas falharão com a mensagem de erro

Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter

Para corrigir isso, você pode aplicar uma versão mais recente do plug-in:

        <build>
          <pluginManagement>
            <plugins>
              <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8</version>
              </plugin>
            </plugins>
          </pluginManagement>
        </build>
Michael Wyraz
fonte
Estou continuamente tentando essa solução, mas apenas a propriedade altDeploymentRepository funciona. altReleaseDeploymentRepository e altSnapshotDeploymentRepository não são reconhecidos e recebo este erro: Falha na implantação: o elemento do repositório não foi especificado no POM dentro do elemento distributionManagement ou no -DaltDeploymentRepository = id :: layout :: url paramete. Qualquer sugestão ajudaria. Obrigado
Shabirmean
@Shabirmean O motivo é uma versão muito antiga do plug-in de implementação. Eu estendi minha resposta com uma solução.
Michael Wyraz
Sim, eu percebi. Muito obrigado :)
Shabirmean