Dividir un gran proyecto para crear un proyecto Maven de módulos múltiples

23

Estoy trabajando en una aplicación Spring-MVC en la que estamos usando Maven para la gestión de dependencias. Como el proyecto es grande, estamos pensando en dividirlo en varias partes. Tenía algunas dudas y espero obtener respuestas aquí.

Actualmente, estamos implementando un solo archivo WAR como ROOT.waren Apache tomcat en nuestro servidor. Como el proyecto es grande, hay partes en la aplicación web como Notificaciones y correo electrónico, Servicios de terceros, PUSH (Cometd), REST API, etc. Actualmente, todas ellas están agrupadas y dependen unas de otras. Por ejemplo, el Notificationobjeto también depende del Personobjeto, ya que las notificaciones se adaptan a los usuarios.

La intención principal de dividir el gran proyecto es poder trabajar en módulos individuales, para corregir errores, agregar funciones, pruebas, etc. Y cuando esté satisfecho, solo este módulo puede reemplazarse en el servidor en lugar de la aplicación completa. es posible?

Como ya mencioné antes, hay dependencias y asignaciones entre objetos. ¿Cómo se gestionarán en diferentes submódulos, o solo cambiarán las declaraciones de importación para incluir otros proyectos?

Como dije, la intención es trabajar en módulos individuales y poder implementarlos (preferiblemente en caliente). Actualmente, solo tenemos un único archivo WAR como ROOT.war. ¿La división creará múltiples archivos de guerra, que luego se denominan URL como domain-name.com/module_name/some_mapping?

Actualmente estoy revisando la documentación, pero este es el objetivo principal que queremos lograr con el módulo múltiple proporcionado por Maven e interesado en saber si esto es factible. Si necesita más información, hágamelo saber.

Actualmente estoy usando un POM padre de primavera de la siguiente manera:

<parent>
    <groupId>io.spring.platform</groupId>
    <artifactId>platform-bom</artifactId>
    <version>1.1.3.RELEASE</version>
    <relativePath />
</parent>
Somos Borg
fuente
1
Dejo que otros respondan. La idea es muy sólida. Podrías comenzar con un POM principal con dependencyManagement y un jar para los DAO como Person. Una biblioteca muy básica. Y así. Por supuesto que no hay dependencias cíclicas.
Joop Eggen

Respuestas:

20

Es posible ?

Si ciertamente. En el pasado, he estructurado algunos proyectos como este, aquí algunos bits que espero que te ayuden a comenzar.

Hay dos características principales de Maven que usará para tejer cosas juntas:

Divide y conquistaras

Deberá dividir sus proyectos en múltiples proyectos independientes. Aquí por independiente quiero decir que todas las referencias al código fuera del proyecto se realizan a través de dependencias en Maven y no fusionando directamente el árbol fuente.

Dependiendo del estado de su árbol de origen, esto podría representar mucho trabajo. Dicho esto, no lo estás haciendo para calzar a Maven sino como un medio para estructurar y desinfectar tu base de código. Piense en ello como su herramienta, mucho más fácil de encontrar aquí:

Bonito cobertizo

que aqui:

No tan bonito cobertizo de herramientas

Maven depende en gran medida de la convención, por lo que cuanto mejor organizado esté tu material, más puede ayudarte Maven. Dicho esto, puede requerir que se reorganice para adaptarse mejor a su propia convención y si tengo que dar un consejo aquí es que es MUCHO más fácil cambiar sus cosas para que se ajusten a las convenciones de Maven de lo que es tratar de configurar Maven para Entiende tu convención.

Si estos proyectos pudieran ser utilizados fuera de la aplicación principal, podrían vivir como bibliotecas verdaderamente independientes e incluidas aunque dependientes de Maven. Deben vivir en su propio repositorio (no en el árbol de origen de la aplicación) y no deben depender de ninguna parte de la aplicación principal.

Las partes centrales de su aplicación, una vez divididas en proyectos, se pueden juntar como módulos. Por lo general, los colocará como subcarpeta de la carpeta de origen principal de su aplicación.

Además, su POM principal para su aplicación contendrá la declaración del módulo. También colocará allí todas las dependencias comunes para su aplicación, así como declarará la mayoría de los complementos de compilación y su configuración. Aquí también le recomiendo encarecidamente que coloque un grupo de propiedades para cosas como la versión de la aplicación que puede reutilizar en los módulos. Mucho más fácil de administrar cuando todo tiene la misma versión y tener la versión en un solo lugar hace que esto funcione.

Estampación

Si es un equipo mayor de 1, también le recomendaría que instale un repositorio para sus dependencias de Maven. Mira Artifactory , Nexus o Archiva . Puede configurar el archivo POM para que se instale en ellos directamente, por lo que una vez que se ejecute, no debería ser una sobrecarga, pero le ahorrará mucho tiempo a su equipo resolviendo las dependencias con el jar correcto en el lugar correcto.

Sobre el tema de las herramientas, el siguiente paso lógico aquí es un sistema de integración continua ( Jenkins , hay muchos más). Manejará la construcción de la fuente ejecutando las pruebas y empujando hacia la fábrica, con todo esto en su lugar, todo lo que tiene que hacer es trabajar el código y el resto simplemente funciona.

Dado que está empaquetando su aplicación como un experto en guerra, puede manejar la construcción de la guerra y colocar todas las dependencias en sus lugares adecuados sin tener que fusionar archivos jar u otro trabajo similar, por lo que no se preocupe.

Ejemplo

Podría seguir mucho más tiempo aquí, pero nada es mejor que un buen ejemplo. Busque en Github proyectos de magnitud similar y vea cómo construyeron sus archivos pom y jerarquías de carpetas. Mire más de uno, algunos se adaptarán mejor a su configuración que otros, ninguno realmente encarna la verdad, pero debe encontrar lo suficiente para alimentar sus pensamientos sobre cómo hacerlo.

Tome a Jenkins por ejemplo:

Puedes ver que su POM padre es bastante extenso.

Usan módulos como puede ver en esta sección:

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

Y cada módulo corresponde a una subcarpeta con el mismo nombre que también contiene un POM. Podría anidar tantos como quiera de esta manera, aunque manténgalo dentro de los niveles de cordura;).

Empieza pequeño

Si nunca ha usado Maven, sugeriría que no comience con módulos de inmediato. Tómelo con calma, comience con, diga una de las bibliotecas más simples que pueda tener y conviértalo en un proyecto experto. Luego, haga que su aplicación principal sea un proyecto simple de Maven. Una vez que funcione, comience a agregar dependencias simples, luego divida su primer módulo y así sucesivamente.

Maven es una gran herramienta, pero también puede ser un dolor súper en el cuello, especialmente cuando las cosas no salen bien. Comenzar con todo el golpe en tu primer intento es una receta para el desastre (¡fue para mí!).

Si las cosas son un poco raras, siempre puedes usar el mvn help:effective-pomcomando para ver lo que Maven realmente entendió.

complementos

Por tu comentario entiendo mejor lo que quieres lograr. En este caso, optaría por el enfoque de complementos. Cree un proyecto que exponga la API de puntos de extensión donde desea aislar el trabajo. Luego puede usar esto como una dependencia en un nuevo proyecto que lo implementará. En su aplicación principal, simplemente agregue las dependencias adecuadas para estas implementaciones (esta vez no use módulos maven) y debería estar listo. Finalmente, el proyecto principal de la aplicación llevará casi ningún código fuente, todo lo que se haga en proyectos externos y se cargue a través de dependencias.

Sin embargo, deberá volver a implementar toda la aplicación con este enfoque, independientemente de si el núcleo cambió o no, ya que la guerra se construye estáticamente a partir de las dependencias, cambiar una de ellas implica reconstruir todo. Suena peor de lo que realmente es. En efecto, solo se generarán los nuevos cambios, el resto básicamente será una copia de los jar (s) anteriores. Pero dado que todo está en el archivo war, será necesario reconstruirlo y el servidor deberá detenerse y reiniciarse.

Si necesita ir más lejos, las cosas se vuelven un poco más complicadas, aunque no imposibles. Le recomiendo que busque en OSGI, Apache Felix podría ayudarlo a comenzar, aunque también hay otras implementaciones. Esto le permitirá tomar el jar externo y convertirlos en complementos adecuados. Obtendrá mucho más control sobre el ciclo de vida de tiempo de ejecución de los componentes que abren la puerta a recargas y actualizaciones dinámicas. Sin embargo, requerirá cambios importantes en su núcleo, así que nuevamente, probablemente no sea un buen punto de partida. Sin embargo, una vez que tenga un proyecto que esté bien separado y tenga todas las partes aisladas de la manera que desee, ese podría ser el siguiente paso natural si iniciar y detener la aplicación en la actualización es un problema importante.

La diferencia básica entre módulos y dependencias es esta:

  • Los módulos vivirán en el mismo árbol fuente que la aplicación principal, idealmente como subcarpetas.
  • Las dependencias pueden estar en cualquier parte.

Puedes encontrar la biblia aquí .

Espero que esto ayude, buena suerte.

Newtopian
fuente
En realidad, agrupar módulos a través de Maven en lugar del árbol de origen aclaró muchas preguntas que tenía. ¿Me puede decir acerca de la implementación de dicho proyecto? Una de las otras razones que estamos considerando es para que los desarrolladores puedan trabajar en su módulo requerido y realizar los cambios en tiempo real. Una cosa que queremos evitar es detener el servidor de aplicaciones y comenzar de nuevo, excepto para el módulo central. Como 2 módulos en los que puedo pensar contendrán código que cambia a menudo. Usamos tomcat como servidor de aplicaciones, balanceado por Apache. Gracias.
Somos Borg
Los módulos Maven a menudo se encuentran en el mismo árbol de origen que la aplicación principal. Usar módulos maven fuera del árbol fuente en realidad es más complicado de lo que realmente vale. Si aloja los proyectos fuera del árbol de origen, vaya a proyectos independientes normales y use dependencias normales.
Newtopian
Creo que iremos a agregar partes de nuestro proyecto directamente como dependencias de Maven. De esta manera, podemos trabajar directamente en partes del proyecto. Solo una pregunta que tuve, si agregamos uno de los subproyectos como una dependencia en POM.xml, digamos la versión 2.0.0, y luego con algunos cambios, empujamos un 2.0.1 del módulo a sonatype, ¿cómo podemos diga directamente al core-module que vaya a 2.0.1, solo cambiará el POM.xml dentro de ROOT.war y eliminará el directorio ROOT será suficiente. La intención principal es no detener el servidor. Gracias.
Somos Borg
pom.xml no tiene ninguna importancia una vez que se ha creado la guerra, es decir, Tomcat (o cualquier contenedor que use) no usa este archivo. Maven utiliza el archivo para crear un nuevo archivo de guerra, que a su vez deberá implementar en el servidor. Entonces, el ciclo es trabajar en el código, crear un archivo jar, actualizar la versión en el POM de la guerra, crear un archivo de guerra, actualizar el servidor con el nuevo archivo de guerra. Algunos servidores admitirán la reinstalación en caliente, aunque en general eso implicaría apagar la aplicación durante unos segundos.
Newtopian