Maven pai pom vs módulos pom

Parece haver várias maneiras de estruturar poms pai em uma compilation de multiprojetos e me pergunto se alguém pensou em quais são as vantagens / desvantagens de cada maneira.

O método mais simples de ter um pom parente seria colocá-lo na raiz de um projeto, ou seja,

myproject/ myproject-core/ myproject-api/ myproject-app/ pom.xml 

onde o pom.xml é tanto o projeto pai quanto descreve os módulos -core -api e -app

O próximo método é separar o pai em seu próprio subdiretório, como em

 myproject/ mypoject-parent/ pom.xml myproject-core/ myproject-api/ myproject-app/ 

Onde o pai pom ainda contém os módulos, mas eles são relativos, por exemplo .. / myproject -core

Finalmente, há a opção onde a definição do módulo e o pai são separados como em

 myproject/ mypoject-parent/ pom.xml myproject-core/ myproject-api/ myproject-app/ pom.xml 

Onde o pom pai contém qualquer configuração “compartilhada” (dependencyManagement, propriedades etc.) e o myproject / pom.xml contém a lista de módulos.

A intenção é ser escalável para uma construção em larga escala, portanto, deve ser escalonável para um grande número de projetos e artefatos.

Algumas perguntas bônus:

  • Onde é o melhor lugar para definir as várias configurações compartilhadas como no controle de origem, diretórios de implantação, plugins comuns etc. (estou assumindo o pai, mas muitas vezes tenho sido mordido por isso e eles acabaram em cada projeto em vez de um comum).
  • Como o plugin maven-release, o hudson e o nexus lidam com a maneira como você configura seus multi-projetos (possivelmente uma pergunta gigante, é mais se alguém foi pego quando pela configuração de um multi-projeto)?

Edit: Cada um dos sub-projetos tem seu próprio pom.xml, eu deixei de fora para mantê-lo curto.

Na minha opinião, para responder a essa pergunta, você precisa pensar em termos de ciclo de vida do projeto e version control. Em outras palavras, o pom pai tem seu próprio ciclo de vida, isto é, ele pode ser liberado separadamente dos outros módulos ou não?

Se a resposta for sim (e este é o caso da maioria dos projetos que foram mencionados na pergunta ou nos comentários), então o pai pom precisa de seu próprio módulo de um VCS e de um ponto de vista Maven e você acabará com algo parecido com isso no nível VCS:

 root |-- parent-pom | |-- branches | |-- tags | `-- trunk | `-- pom.xml `-- projectA |-- branches |-- tags `-- trunk |-- module1 | `-- pom.xml |-- moduleN | `-- pom.xml `-- pom.xml 

Isso torna o check-out um pouco doloroso e uma maneira comum de lidar com isso é usar o svn:externals . Por exemplo, adicione um diretório de trunks :

 root |-- parent-pom | |-- branches | |-- tags | `-- trunk | `-- pom.xml |-- projectA | |-- branches | |-- tags | `-- trunk | |-- module1 | | `-- pom.xml | |-- moduleN | | `-- pom.xml | `-- pom.xml `-- trunks 

Com a seguinte definição de externals:

 parent-pom http://host/svn/parent-pom/trunk projectA http://host/svn/projectA/trunk 

Um checkout de trunks resultaria então na seguinte estrutura local (padrão # 2):

 root/ parent-pom/ pom.xml projectA/ 

Opcionalmente, você pode até adicionar um pom.xml no diretório de trunks :

 root |-- parent-pom | |-- branches | |-- tags | `-- trunk | `-- pom.xml |-- projectA | |-- branches | |-- tags | `-- trunk | |-- module1 | | `-- pom.xml | |-- moduleN | | `-- pom.xml | `-- pom.xml `-- trunks `-- pom.xml 

Este pom.xml é uma espécie de “falso” pom: nunca é lançado, ele não contém uma versão real, pois este arquivo nunca é liberado, ele contém apenas uma lista de módulos. Com este arquivo, um checkout resultaria nessa estrutura (padrão # 3):

 root/ parent-pom/ pom.xml projectA/ pom.xml 

Este “hack” permite o lançamento de um reator construído a partir da raiz após um checkout e tornar as coisas ainda mais úteis. Na verdade, é assim que eu gosto de configurar projetos de maven e um repository VCS para grandes compilações : ele simplesmente funciona, escala bem, dá toda a flexibilidade que você pode precisar.

Se a resposta for não (volta para a pergunta inicial), então eu acho que você pode viver com o padrão # 1 (fazer a coisa mais simples que poderia funcionar).

Agora, sobre as perguntas bônus:

  • Onde é o melhor lugar para definir as várias configurações compartilhadas como no controle de origem, diretórios de implantação, plugins comuns etc. (estou assumindo o pai, mas muitas vezes tenho sido mordido por isso e eles acabaram em cada projeto em vez de um comum).

Honestamente, eu não sei como não dar uma resposta geral aqui (como “use o nível em que você acha que faz sentido mutualizar as coisas”). E, de qualquer forma, os poms infantis podem sempre replace as configurações herdadas.

  • Como o plugin maven-release, o hudson e o nexus lidam com a maneira como você configura seus multi-projetos (possivelmente uma pergunta gigante, é mais se alguém foi pego quando pela configuração de um multi-projeto)?

A configuração que eu uso funciona bem, nada de especial para mencionar.

Na verdade, gostaria de saber como o plugin-release-maven lida com o padrão # 1 (especialmente com a seção , já que você não pode ter dependencies SNAPSHOT no momento do lançamento). Isso soa como um problema de galinha ou ovo, mas eu não consigo lembrar se funciona e estava com preguiça de testá-lo.

Da minha experiência e das melhores práticas do Maven, existem dois tipos de “poms pai”

  • pom pai “company” – este pom contém informações e configurações específicas da empresa que herdam todos os pom e não precisam ser copiadas. Essas informações são:

    • repositorys
    • seções de gerenciamento de distribuição
    • configurações comuns de plugins (como versões de origem e destino do maven-compiler-plugin)
    • organização, desenvolvedores, etc

    Preparar este pai deve ser feito com caucanvas, porque todos os seus poms da empresa herdarão dele, então este pom tem que ser maduro e estável (liberar uma versão do pom pai não deve afetar o lançamento de todos os projetos da sua empresa!)

  • segundo tipo de pai pom é um pai multimodule. Eu prefiro sua primeira solução – esta é uma convenção de maven padrão para projetos de múltiplos módulos, muitas vezes representa a estrutura de código do VCS

A intenção é ser escalável para uma construção em larga escala, portanto, deve ser escalonável para um grande número de projetos e artefatos.

Mutliprojects têm estrutura de trees – então você não é reduzido a um nível de pom pai. Tente encontrar uma estrutura de projeto adequada às suas necessidades – um exemplo clássico é como distribuir projetos mutimódulos

 distibution/ documentation/ myproject/ myproject-core/ myproject-api/ myproject-app/ pom.xml pom.xml 

Algumas perguntas bônus:

  • Onde é o melhor lugar para definir as várias configurações compartilhadas como no controle de origem, diretórios de implantação, plugins comuns etc. (estou assumindo o pai, mas muitas vezes tenho sido mordido por isso e eles acabaram em cada projeto em vez de um comum).

Essa configuração deve ser sabiamente dividida em pom pai “empresa” e pom (s) pai (s) do projeto. Coisas relacionadas a tudo que você projeta vão para pais “de empresa” e isso relacionado ao projeto atual vai para o projeto.

  • Como o plugin maven-release, o hudson e o nexus lidam com a maneira como você configura seus multi-projetos (possivelmente uma pergunta gigante, é mais se alguém foi pego quando pela configuração de um multi-projeto)?

O pai pai da empresa tem que ser liberado primeiro. Para multiprojetos, as regras padrão se aplicam. O servidor de CI precisa saber tudo para construir o projeto corretamente.

  1. Um pai independente é a prática recomendada para compartilhar configurações e opções em componentes que, de outra forma, são desacoplados. O Apache tem um projeto pom pai para compartilhar avisos legais e algumas opções comuns de empacotamento.

  2. Se o seu projeto de nível superior tiver um trabalho real, como agregar javadoc ou empacotar uma release, você terá conflitos entre as configurações necessárias para fazer esse trabalho e as configurações que deseja compartilhar via pai. Um projeto somente para pais evita isso.

  3. Um padrão comum (ignorando # 1 no momento) é que os projetos com código usem um projeto pai como pai, e ele use o nível superior como pai. Isso permite que as coisas essenciais sejam compartilhadas por todos, mas evita o problema descrito no item 2.

  4. O plugin do site ficará muito confuso se a estrutura pai não for a mesma que a estrutura do diretório. Se você quiser criar um site agregado, precisará fazer alguns ajustes para contornar isso.

  5. O Apache CXF é um exemplo do padrão em # 2.

Há um pequeno problema com a terceira abordagem. Como os POMs agregados (myproject / pom.xml) geralmente não têm pai, eles não compartilham a configuração. Isso significa que todos esses POMs agregados terão apenas repositorys padrão.

Isso não é um problema se você usar somente plugins da Central, no entanto, isso falhará se você executar o plug-in usando o formato plugin: goal do seu repository interno. Por exemplo, você pode ter o foo-maven-plugin com o groupId de org.example fornecendo meta generate-foo . Se você tentar executá-lo a partir da raiz do projeto usando o comando como mvn org.example:foo-maven-plugin:generate-foo , ele falhará em rodar nos módulos agregados (veja nota de compatibilidade ).

Várias soluções são possíveis:

  1. Implante o plugin no Maven Central (nem sempre é possível).
  2. Especifique a seção do repository em todos os seus POMs agregados (quebra o princípio DRY ).
  3. Tenha este repository interno configurado no settings.xml (nas configurações locais em ~ / .m2 / settings.xml ou nas configurações globais em /conf/settings.xml). Fará a compilation falhar sem essas configurações.xml (pode ser bom para grandes projetos internos que nunca devem ser criados fora da empresa).
  4. Use o pai com configurações de repositorys em seus POMs agregados (podem ser muitos POMs pai?).