Maven parent pom vs modules pom

284

Parece haver várias maneiras de estruturar os pais-pais em uma compilação de multiprojetos e eu me pergunto se alguém pensou sobre quais são as vantagens / desvantagens de cada maneira.

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

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

em que pom.xml é o projeto pai e 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 pom pai ainda contém os módulos, mas eles são relativos, por exemplo ../myproject-core

Finalmente, há a opção em que 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 principal 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 escalá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, plug-ins comuns etc. (estou assumindo que o pai, mas muitas vezes fui mordido por isso e eles acabaram em cada projeto em vez de comum).
  • Como o plugin maven-release, hudson e nexus lidam com a maneira como você configura seus multiprojetos (possivelmente uma pergunta gigante, é mais se alguém foi pego quando, pela forma como uma compilação de multiprojetos foi criada)?

Edit: Cada um dos subprojetos tem seu próprio pom.xml, deixei de fora para mantê-lo conciso.

Jamie McCrindle
fonte
Os módulos também têm seu próprio pom? Meu projeto tem um pom pai, mas os módulos também têm um pom. (talvez uma quarta forma de o u descrever)
harschware
Ah, sim, eu vou editar e atualizar. Cada um dos submódulos também possui seu próprio pom.
Jamie McCrindle
3
Assim como uma atualização, posso ver uma vantagem da segunda opção: é mais fácil gerenciar no Eclipse, onde seria difícil incluir o pom.xml raiz no primeiro e no terceiro exemplo se os submódulos fossem projetos separados no Eclipse.
Jamie McCrindle

Respostas:

166

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

Se a resposta for sim (e este é o caso da maioria dos projetos mencionados na pergunta ou nos comentários), o pai pai precisa de seu próprio módulo a partir de um VCS e do ponto de vista do Maven e você acabará com algo parecido com isto 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 checkout um pouco doloroso e é uma maneira comum de lidar com isso svn:externals. Por exemplo, adicione um trunksdiretório:

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

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

Um checkout de trunksresultaria na seguinte estrutura local (padrão # 2):

root/
  parent-pom/
    pom.xml
  projectA/

Opcionalmente, você pode até adicionar um pom.xmlno trunksdiretório:

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é um tipo de pom "falso": nunca é lançado, não contém uma versão real, pois esse arquivo nunca é lançado, contém apenas uma lista de módulos. Com esse arquivo, um checkout resultaria nessa estrutura (padrão nº 3):

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

Esse "hack" permite o lançamento de uma construção de reator a partir da raiz após um checkout e torna as coisas ainda mais úteis. Na verdade, é assim que eu gosto de configurar projetos maven e um repositório VCS para grandes compilações : ele simplesmente funciona, dimensiona bem, oferece toda a flexibilidade que você pode precisar.

Se a resposta for não (de volta à pergunta inicial), acho que você pode viver com o padrão nº 1 (faça a coisa mais simples que possa funcionar).

Agora, sobre as perguntas de bônus:

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

Honestamente, não sei como não dar uma resposta geral aqui (como "use o nível em que você acha que faz sentido mútuo"). De qualquer forma, os filhos-filhos sempre podem substituir as configurações herdadas.

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

A configuração que eu uso funciona bem, nada de especial a ser mencionado.

Na verdade, eu me pergunto como o maven-release-plugin lida com o padrão nº 1 (especialmente com a <parent>seção, pois você não pode ter dependências do INSTANTÂNEO no momento do lançamento). Parece um problema de galinha ou ovo, mas não consigo me lembrar se funciona e estava com preguiça de testá-lo.

Pascal Thivent
fonte
Isso é muito bom, pois posso ver como ele se escala. O svn: externals responde à minha preocupação de que seja complicado.
Jamie McCrindle
@jamie Fico feliz que você ache útil.
precisa saber é o seguinte
1
Você poderia elaborar como fazer o "hack" funcionar? Eu tenho o projeto de troncos e prevejo que você alveje a opção -pl com "lançamento de uma construção de reator", mas isso se apresenta como um problema ao fazer uma liberação na estrutura, porque essa opção não passa de uma construção no nível raiz nem posso colocá-lo na opção <argumentos /> do release-Plugin. Portanto, o release: execute falha porque ele tenta trabalhar com o nível de raiz ...
Jan
O hack svn: externals é o hack svn mais útil que eu já vi há muito tempo. Muito útil com projetos que possuem ramificações por projeto no mesmo repositório.
omerkudat
1
Oi Pascal, Como você lidaria com a versão # se os projetos mencionados na seção de módulos não usam parent-pom como seu <pai>, mas algum outro projeto-pai-pom? Quais versões # obteremos para um artefato de tais projetos (versão # do artefato na seção <parent> desses projetos OU versão # do projeto que lista esses projetos como módulos)? stackoverflow.com/questions/25918593/…
AKS
34

Pela minha experiência e pelas melhores práticas do Maven, existem dois tipos de "pais-pais"

  • pom principal da "empresa" - esse pom contém informações e configurações específicas da sua empresa que herdam cada pom e não precisam ser copiadas. Essas informações são:

    • repositórios
    • seções de gerenciamento de distribuição
    • configurações comuns de plug-ins (como versões de origem e de destino do maven-compiler-plugin)
    • organização, desenvolvedores etc.

    A preparação deste pom pai precisa ser feita com cautela, porque todos os documentos da sua empresa herdarão dele, portanto esse pom deve ser maduro e estável (a liberação de uma versão do pom pai não deve afetar a liberação de todos os projetos da sua empresa!)

  • O segundo tipo de pai pom é um pai multimodular. Prefiro sua primeira solução - esta é uma convenção padrão para projetos de módulos múltiplos, muitas vezes representa a estrutura de código VCS

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

Os projetos múltiplos têm estrutura de árvores - portanto, você não é levado a um nível de pom-pai. Tente encontrar uma estrutura de projeto adequada para suas necessidades - um exemplo clássico é como descrever projetos de 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, plug-ins comuns etc. (estou assumindo que o pai, mas muitas vezes fui mordido por isso e eles acabaram em cada projeto em vez de comum).

Essa configuração deve ser sabiamente dividida em pom principal da "empresa" e pom (s) pai do projeto. As coisas relacionadas a tudo o que você projeta vão para o pai da "empresa" e as relacionadas ao projeto atual vão para o projeto de alguém.

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

O pai da empresa deve ser lançado primeiro. Para multiprojetos, aplicam-se regras padrão. O servidor de CI precisa conhecer tudo para criar o projeto corretamente.

cetnar
fonte
1
Para que haja dois tipos de projetos / poms pai. Um sem declaração de <modules>. Este é o que é usado para Herança. E um projeto pai com declaração <multimodule>. É o que os sub-módulos não herdam, é apenas para gerenciar a construção do projeto de retenção. Estou certo ?
lisak
22
  1. Um pai independente é a melhor prática para compartilhar configurações e opções entre componentes desacoplados. O Apache possui um projeto pai pom 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 um release, você terá conflitos entre as configurações necessárias para executar esse trabalho e as que deseja compartilhar via pai. Um projeto somente pai evita isso.

  3. Um padrão comum (ignorando o nº 1 no momento) é fazer com que os projetos com código usem um projeto pai como pai e o nível superior como pai. Isso permite que os principais itens sejam compartilhados 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 de diretórios. Se você deseja criar um site agregado, precisará fazer algumas manobras para contornar isso.

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

bmargulies
fonte
2
Eu dei uma olhada no ibilio e muitos projetos parecem preferir o pom pai "independente". Hibernate, ActiveMQ, Jetty, XStream etc. O que sugere que é o mecanismo de defesa.
Jamie McCrindle
2
Outra desvantagem do pai independente parece ser que o plug-in maven release parece querer que o pai seja fixado a uma versão antes de fazer um lançamento. Provavelmente não é um problema, pois os pais não devem mudar muito.
Jamie McCrindle
9

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

Isso não é um problema se você usar apenas plug-ins do Central; no entanto, isso falhará se você executar o plugin usando o formato plugin: goal do seu repositório interno. Por exemplo, você pode ter foo-maven-plugincom o groupId de org.examplefornecer meta generate-foo. Se você tentar executá-lo a partir da raiz do projeto usando o comando like mvn org.example:foo-maven-plugin:generate-foo, ele falhará ao ser executado nos módulos agregados (consulte a nota de compatibilidade ).

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

  1. Implante o plug-in no Maven Central (nem sempre possível).
  2. Especifique a seção de repositório em todas as suas POMs agregadas (quebras DRY princípio ).
  3. Tenha esse repositório interno configurado no settings.xml (nas configurações locais em ~ / .m2 / settings.xml ou nas configurações globais em /conf/settings.xml). Fará com que a construção falhe sem o settings.xml (pode ser bom para grandes projetos internos que nunca deveriam ser construídos fora da empresa).
  4. Use o pai com configurações de repositórios em suas POMs agregadas (pode haver muitas POMs pai?).
Ivan Dubrov
fonte