Dividindo um grande projeto para criar um projeto Maven com vários módulos

23

Estou trabalhando em um aplicativo Spring-MVC no qual estamos usando o Maven para gerenciamento de dependências. Como o projeto é grande, estamos pensando em dividi-lo em várias partes. Eu tinha algumas dúvidas, que espero obter respostas aqui.

Atualmente, estamos implantando um único arquivo WAR como ROOT.warno Apache tomcat em nosso servidor. Como o projeto é grande, há partes no aplicativo da web como Notificações e E-mail, Serviços de Terceiros, PUSH (Cometd), API REST, etc. Atualmente, todos eles estão em clubes e dependem um do outro. Por exemplo, o Notificationobjeto também depende do Personobjeto, pois as Notificações são personalizadas para os usuários.

A principal intenção de dividir o grande projeto é poder trabalhar em módulos individuais, para correção de bugs, adição de recursos, testes etc. E, quando satisfeito, somente esse módulo pode ser substituído no servidor em vez de em todo o aplicativo. Isso é possível?

Como eu já mencionei antes, existem dependências e mapeamentos entre objetos. Como eles serão gerenciados em diferentes submódulos ou apenas as instruções de importação serão alteradas para incluir outros projetos?

Como eu disse, a intenção é trabalhar em módulos individuais e poder implantá-los (de preferência quente). Atualmente, temos apenas um único arquivo WAR como ROOT.war. A divisão criará vários arquivos de guerra, que são referidos pela URL como domain-name.com/module_name/some_mapping?

Atualmente, estou verificando a documentação, mas esse é o objetivo principal que queremos alcançar com o multi-módulo fornecido pelo Maven e interessado em saber se isso é viável. Se houver mais informações necessárias, entre em contato.

Atualmente, estou usando um POM pai da primavera, da seguinte maneira:

<parent>
    <groupId>io.spring.platform</groupId>
    <artifactId>platform-bom</artifactId>
    <version>1.1.3.RELEASE</version>
    <relativePath />
</parent>
Nós somos Borg
fonte
1
Deixo para os outros responderem. A ideia é muito sólida. Você pode começar com um POM pai com dependencyManagement e um jar para os DAOs como Person. Uma biblioteca muito básica. E assim por diante. Claro que não há dependências cíclicas.
Joop Eggen

Respostas:

20

É possível ?

Sim certamente. No passado, eu estruturei alguns projetos como este, aqui alguns bits que espero que você o inicie.

Existem duas características principais do Maven que você usará para tecer as coisas:

Dividir e conquistar

Você precisará dividir seus projetos em vários projetos independentes. Aqui, por independente, quero dizer que todas as referências ao código fora do projeto são feitas através de dependências no Maven e não mesclando diretamente a árvore de origem.

Dependendo do estado da sua árvore de origem, isso pode representar muito trabalho. Dito isto, você não está fazendo isso para calçar sapato no Maven, mas como um meio de estruturar e higienizar sua base de código. Pense nisso como seu depósito de ferramentas, muito mais fácil de encontrar coisas aqui:

Nice toolshed

do que aqui:

Ferramentas não muito agradáveis

O Maven depende muito da convenção, portanto, quanto melhor organizado o seu material, mais ele pode ajudá-lo. Dito isto, pode ser necessário que você reorganize para se adequar melhor à sua própria convenção e, se eu tiver que dar um conselho aqui, é MUITO mais fácil mudar suas coisas para se adequar às convenções do Maven do que tentar configurar o Maven para entenda sua convenção.

Se esses projetos pudessem ser utilizados fora do aplicativo principal, eles poderiam viver como bibliotecas verdadeiramente independentes e incluir dependências ainda não definidas. Eles devem residir em seu próprio repositório (não na árvore de origem do aplicativo) e não devem depender de nenhuma parte do aplicativo principal.

Partes principais do seu aplicativo, uma vez divididas em projetos, podem ser reunidas como módulos. Normalmente, você os colocará como subpasta da pasta de origem principal do seu aplicativo.

Além disso, o POM pai do seu aplicativo conterá a declaração do módulo. Você também colocará todas as dependências comuns do seu aplicativo e declarará a maioria dos plug-ins de compilação e suas configurações. Aqui também recomendo fortemente que você coloque um grupo de propriedades para coisas como a versão do aplicativo que você pode reutilizar nos módulos. Muito mais fácil de gerenciar quando tudo tem a mesma versão e ter a versão em um só lugar faz com que isso funcione.

Ferramentas

Se você é um time maior que 1, também recomendo fortemente que você instale um repositório para suas dependências do Maven. Veja Artifactory , Nexus ou Archiva . Você pode configurar o arquivo POM para instalar diretamente neles, para que, uma vez executado, não exija muito, mas economize muito tempo para a equipe resolver as dependências com o jar correto no local correto.

Sobre o assunto das ferramentas, o próximo passo lógico aqui é um sistema de integração contínua ( Jenkins , há muito mais). Ele cuidará da criação da fonte executando os testes e empurrando para o artefato, com tudo isso no lugar, tudo o que você precisa fazer é trabalhar com o código e o resto simplesmente funciona.

Como você está empacotando seu aplicativo como um especialista em guerra, pode lidar com a construção da guerra e colocar todas as dependências em seus devidos lugares, sem ter que mesclar arquivos jar ou outro trabalho semelhante, então não se preocupe.

Exemplo

Eu poderia continuar por muito mais tempo aqui, mas nada é um bom exemplo. Procure no github projetos de magnitude semelhante e veja como eles construíram seus arquivos pom e hierarquias de pastas. Olhe para mais de um, alguns se ajustam melhor à sua configuração do que outros, nenhum realmente encarna a verdade, mas você deve encontrar o suficiente para alimentar seus pensamentos sobre como fazê-lo.

Veja o Jenkins, por exemplo:

Você pode ver que o pai deles é bastante extenso.

Eles usam módulos como você pode ver nesta seção:

<modules>
    <module>core</module>
    <module>war</module>
    <module>test</module>
    <module>cli</module>
</modules>

E cada módulo corresponde a uma subpasta com o mesmo nome que também contém um POM. Você pode aninhar quantas quiser, embora o mantenha dentro dos níveis de sanidade;).

Comece pequeno

Se você nunca usou o Maven, sugiro que você não inicie os módulos imediatamente. Vá devagar, comece com, diga uma das bibliotecas mais simples que você possa ter e torne-a um projeto inovador. Então faça da sua aplicação principal um projeto simples. Depois disso, comece a adicionar dependências simples, divida seu primeiro módulo e assim por diante.

O Maven é uma ótima ferramenta, mas também pode ser uma super dor no pescoço, especialmente quando as coisas não estão indo do seu jeito. Começando com todo o golpe em sua primeira tentativa é um destinatário de um desastre (foi para mim!).

Se as coisas estiverem um pouco estranhas, você sempre pode usar o mvn help:effective-pomcomando para ver o que Maven realmente entendeu.

plugins

Pelo seu comentário, entendo melhor o que você deseja obter. Neste caso, eu iria para a abordagem de plugins. Crie um projeto que exponha a API dos pontos de extensão em que você deseja isolar o trabalho. Em seguida, você pode usar isso como uma dependência em um novo projeto que o implementará. No seu aplicativo principal, basta adicionar as dependências apropriadas para essas implementações (desta vez não usando módulos maven) e você deve estar pronto. Eventualmente, o projeto principal do aplicativo não terá quase nenhum código-fonte, tudo sendo feito em projetos externos e carregado através de dependências.

Você precisará reimplantar o aplicativo inteiro, no entanto, com essa abordagem, independentemente de o núcleo ter sido alterado ou não, pois a guerra é estaticamente criada a partir das dependências, alterar um deles implica em reconstruir tudo. Parece pior do que realmente é. Na verdade, apenas as novas alterações serão construídas, o restante será basicamente uma cópia dos jarros anteriores. Mas como tudo está no arquivo war, ele precisará ser reconstruído e o servidor precisará ser parado e reiniciado.

Se você precisar ir mais longe, as coisas ficam um pouco mais complicadas, embora não sejam impossíveis. Eu recomendaria que você analisasse o OSGI, o Apache Felix pode dar os primeiros passos, embora existam outras implementações também. Isso permitirá que você pegue o frasco externo e faça-o em plugins adequados. Você obterá muito mais controle sobre o ciclo de vida dos componentes, abrindo a porta para recarregamentos e atualizações dinâmicos. No entanto, isso exigirá grandes alterações em seu núcleo, novamente, provavelmente não é um bom ponto de partida. No entanto, uma vez que você tenha um projeto bem separado e com todas as partes isoladas da maneira que deseja, esse poderá ser o próximo passo natural se iniciar e parar o aplicativo na atualização for um grande problema.

A diferença básica entre módulos e dependências é esta:

  • Os módulos viverão na mesma árvore de origem que o aplicativo principal, como subpastas, idealmente.
  • Dependências podem estar em qualquer lugar.

Você pode encontrar a Bíblia aqui .

Espero que isso ajude, boa sorte.

Newtopian
fonte
Agrupar módulos através do maven, em vez da árvore de origem, esclareceu muitas perguntas que eu tinha. Você pode me falar sobre a implantação de um projeto desse tipo. Uma das outras razões que estamos considerando é para que os desenvolvedores possam trabalhar no módulo necessário e fazer as alterações em tempo real. Uma coisa que desejamos evitar é parar o servidor de aplicativos e iniciar novamente, além do módulo principal. Como 2 módulos, consigo pensar em um código que muda frequentemente. Usamos o tomcat como servidor de aplicativos, balanceado por carga pelo Apache. Obrigado.
Estamos Borg
Os módulos Maven geralmente ficam na mesma árvore de origem do aplicativo principal. Usar módulos maven fora da árvore de origem é realmente mais complicado do que realmente vale a pena. Se você hospedar os projetos fora da árvore de origem, escolha projetos independentes normais e use dependências normais.
Newtopian
Acho que iremos adicionar partes do nosso projeto diretamente como dependências do Maven. Dessa forma, podemos trabalhar diretamente em partes do projeto. Apenas uma pergunta que tive, se adicionarmos um dos subprojetos como uma dependência no POM.xml, digamos a versão 2.0.0, e depois com algumas alterações, enviaremos uma 2.0.1 do módulo para sonatype, como podemos diga diretamente ao módulo principal que vá para a versão 2.0.1, basta alterar o POM.xml dentro do ROOT.war e excluir o diretório ROOT. A principal intenção não é parar o servidor. Obrigado.
Estamos Borg
O pom.xml não tem influência alguma depois que a guerra é criada, ou seja, o Tomcat (ou qualquer outro contêiner que você use) não usa esse arquivo. O arquivo é usado pelo Maven para criar um novo arquivo de guerra, que, por sua vez, você precisará implantar no servidor. Portanto, o ciclo é trabalhar no código, criar um arquivo jar, atualizar a versão no POM da guerra, criar um arquivo de guerra, atualizar o servidor com o novo arquivo de guerra. Alguns servidores suportam a reimplantação a quente, embora isso geralmente implique em desligar o aplicativo por alguns segundos.
Newtopian 21/09/16