¿Cómo especificar la organización de distribución de Maven en toda la organización?

110

Estoy tratando de descubrir cómo organizar muchos (alrededor de 50+) proyectos maven2, para que puedan implementarse en un repositorio central de nexus. Al usar el mvn deployobjetivo, es necesario especificar el objetivo en la etiqueta distributionManagement de esta manera:

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

Ahora, no quiero que cada pom.xml (de esos 50+) contenga este bloque una y otra vez. Mi primer pensamiento sería el settings.xmlarchivo, pero parece que no es posible (por diseño) definirlo allí. Entonces, la primera pregunta sería, ¿por qué es así? Si fuera posible, podría especificarlo en settings.xml en la distribución maven2, que podría distribuirse a todos los desarrolladores.

La única solución posible que encontré fue crear un proyecto de master-pom para toda la organización, que contenga estas configuraciones, y hacer que todos los demás pom.xml dependan de este master-pom a través de la <parent>etiqueta. Pero esto parece un poco extraño en compilaciones de varios 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)

Por lo general, leo en toda la documentación que los poms del módulo deben usar el pom principal, no uno diferente. Pero después de leer el sitio web de Maven sobre Herencia v. Agregación, está escrito que de hecho es posible.

Un problema que encontré fue con la generación del sitio maven, que parece tener problemas con esta configuración (los módulos no se vinculan correctamente si no tienen una referencia directa)

Entonces, ¿es este un enfoque válido? ¿Alguna otra solución más obvia y sencilla al problema?

mglauche
fuente
5
@OhadR: Solo escriben cómo escribirlo en un proyecto. El punto es que no quería duplicarlo unas 500 veces ...
mglauche
1
Veo. punto a favor. Entonces, como dijo el que respondió, puede tener un pom principal para el proyecto, que contendrá el 'distribMngmnt' ...
OhadR

Respuestas:

144

La mejor solución para esto es crear un proyecto de archivo pom principal simple (con empaquetado 'pom') genéricamente para todos los proyectos de su organización.

<?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>

Esto se puede construir, lanzar e implementar en su nexo local para que todos tengan acceso a su artefacto.

Ahora, para todos los proyectos que desee utilizar, simplemente incluya esta sección:

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

Esta solución le permitirá agregar fácilmente otras cosas comunes a todos los proyectos de su empresa. Por ejemplo, si quisiera estandarizar el uso de JUnit a una versión específica, este sería el lugar perfecto para eso.

Si tiene proyectos que utilizan estructuras de varios módulos que tienen su propio padre, Maven también admite el encadenamiento de la herencia, por lo que es perfectamente aceptable hacer que el archivo pom principal de su proyecto se refiera al pom principal de su empresa y que los módulos secundarios del proyecto ni siquiera conozcan su matriz de la empresa.

Veo en la estructura de su proyecto de ejemplo que está intentando poner su proyecto principal al mismo nivel que su pom agregador. Si su proyecto necesita su propio padre, el mejor enfoque que he encontrado es incluir el padre al mismo nivel que el resto de los módulos y tener su archivo agregador pom.xml en la raíz de donde existen todos los directorios de sus módulos.

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

Lo que hace con esta estructura es incluir su módulo principal en el agregador y compilar todo con un mvn installdesde el directorio raíz.

Usamos esta solución exacta en mi organización y ha resistido la prueba del tiempo y funcionó bastante bien para nosotros.

Jesse Webb
fuente
Aquí hay otra respuesta en la que describo la herencia del proyecto con más detalle y cómo administrar su complejidad heredada, perdón por el juego de palabras. ;) stackoverflow.com/questions/6347913
Jesse Webb
7
Solo una pequeña nota: para conocer las razones por las que la empresa matriz es la mejor solución, consulte la discusión No se puede especificar la administración de distribución en settings.xml de la lista de usuarios de Maven.
Premek Brada
En el modelo de consultoría clásico, en el que "el cliente es el propietario del código", mi equipo de desarrollo deberá trabajar en el proyecto fuera del sitio y luego llevar el último código al sitio del cliente y volver a construirlo. En mi situación, trabajando con un proyecto de varios módulos, si hago referencia al POM de la empresa en el POM principal del proyecto, tendré que actualizar esa referencia para que apunte al POM de la empresa del cliente. Prefiero esforzarme por mantener todas las configuraciones específicas del entorno en settings.xml si puedo evitarlo. ¿Cuál es el enfoque recomendado para mi situación?
Usuario web
2
@WebUser Su problema suena más como una situación en la que necesita diferentes valores en sus archivos POM en lugar de lo que aborda esta respuesta: evitar configuraciones duplicadas en múltiples módulos. Creo que debería intentar inyectar propiedades a través de un archivo settings.xml . Si eso no le ayuda, haga una nueva pregunta aquí en SO, enlace aquí, y trataré de ayudarlo más.
Jesse Webb
Gracias @JesseWebb Terminé probándolo y es útil abstraer esos valores del POM para la situación que describí. Para mis necesidades, agregué propiedades relevantes debajo del perfil activo y las resueltas en el POM.
Usuario web
36

No es necesario un POM padre.

Puede omitir la parte de DistributionManagement por completo en sus poms y configurarla en su servidor de compilación o en settings.xml.

Para hacerlo en el servidor de compilación, simplemente pase al 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 obtener detalles sobre las opciones que se pueden configurar.

También es posible configurar esto en su settings.xml.

Simplemente cree un perfil allí que esté habilitado y contenga la propiedad.

Ejemplo settings.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>

Asegúrese de que las credenciales para "instantáneas" y "versiones" estén en la <servers>sección de su configuración.xml

Las propiedades altSnapshotDeploymentRepository y altReleaseDeploymentRepository se introducen con maven-deploy-plugin versión 2.8. Las versiones anteriores fallarán con el mensaje de error

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

Para solucionar este problema, puede aplicar una versión más reciente del complemento:

        <build>
          <pluginManagement>
            <plugins>
              <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8</version>
              </plugin>
            </plugins>
          </pluginManagement>
        </build>
Michael Wyraz
fuente
Estoy continuamente probando esta solución, pero solo funciona la propiedad altDeploymentRepository . altReleaseDeploymentRepository y altSnapshotDeploymentRepository no se reconocen y aparece este error: Error de implementación: el elemento del repositorio no se especificó en el POM dentro del elemento distributionManagement o en el parámetro -DaltDeploymentRepository = id :: layout :: url. Cualquier sugerencia ayudaría. Gracias
Shabirmean
@Shabirmean El motivo es una versión demasiado antigua del complemento de implementación. He ampliado mi respuesta con una solución.
Michael Wyraz
Sí, lo imaginé. Muchas gracias :)
Shabirmean