Mejores prácticas para copiar archivos con Maven

Tengo archivos de configuración y varios documentos que quiero copiar desde el entorno de desarrollo al directorio del servidor de desarrollo usando Maven2. Curiosamente, Maven no parece fuerte en esta tarea.

Algunas de las opciones:

  • Uso simple a copia tarea en Maven
<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>
  • Utilice el complemento Ant para ejecutar copia de Ant.

    • Construye un artefacto de tipo Código Postal, junto con el artefacto "principal" del POM, que suele ser de tipo tarro, entonces deshacer ese artefacto del repositorio al directorio de destino.

    • recursos-maven plugin, como se menciona a continuación.

    • Complemento Maven Assembly, pero esto parece requerir muchas definiciones manuales, cuando quiero hacer las cosas de manera simple y "convencional".

    • En esta página ¡incluso muestra cómo crear un complemento para realizar copias!

    • carga de maven plugin, como se menciona a continuación.

    • complemento de dependencia de maven con copia, Como se menciona abajo.


Todo esto parece innecesariamente ad hoc: se supone que Maven sobresale en realizar estas tareas estándar sin problemas ni molestias.

¿Algún consejo?

preguntado el 25 de febrero de 09 a las 12:02

Maven se basa en la idea de un ciclo de vida con fases, la copia de archivos aleatorios a una tarea de servidor remoto no encaja realmente en esto. Piense siempre en su proyecto como un todo. -

"Todo esto parece innecesariamente ad hoc: se supone que Maven sobresale en realizar estas tareas estándar sin problemas y molestias". Lo que está haciendo no es una tarea estándar, per se. Si su artefacto fue una guerra / oído, entonces esto sería tan simple como usar el complemento de carga (cargo.codehaus.org/Maven2+plugin#Maven2plugin-get…). Lo que está describiendo suena muy específico a cómo está realizando las implementaciones y no a las implementaciones estándar de contenedores de aplicaciones Java. Maven no está realmente orientado a manejar las actividades de tiempo de implementación en servidores en vivo, sino más bien a las actividades de construcción / desarrollo. -

@ André: Escucho ese argumento una y otra vez, pero lo siento, eso es una tontería. No hay nada de malo en pensar en el proyecto como un todo, pero parte de cualquier sistema de compilación decente debe ser una funcionalidad que me permita realizar la tarea X de una manera sencilla, como copiar archivos, y Maven no puede hacer eso. Hay una razón por la que han aparecido tantos proyectos últimamente que adoptan el paradigma build-scripts-are-code (como Gradle, SBT o Buildr). -

Recomendaría tener un pom.xml para edificio los artefactos y otro para Desplegando un artefacto dado. -

Todas las sugerencias anteriores todavía no parecen permitirme copiar un archivo específico de un proyecto / artefacto diferente en un proyecto maven. Tengo algunos archivos en la carpeta src / main / en un artefacto que se convierte en un jar y he intentado usar el complemento maven de copia de dependencia, sin embargo, no he encontrado una manera de decir qué archivos quiero copiar y obtengo el jar completo archivo en el archivo de ensamblaje todo el tiempo. Todas las otras sugerencias aquí, como los recursos, no parecen permitirme especificar un artefacto en lugar de los recursos dentro del proyecto.

14 Respuestas

No evite el complemento Antrun. Solo porque algunas personas tienden a pensar que Ant y Maven están en oposición, no es así. Utilice la tarea de copia si necesita realizar alguna personalización única e inevitable:

<project>
  [...]
  <build>
    <plugins>
      [...]
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <phase>deploy</phase>
            <configuration>
              <target>

                <!--
                  Place any Ant task here. You can add anything
                  you can add between <target> and </target> in a
                  build.xml.
                -->

              </target>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

Al responder a esta pregunta, me centraré en los detalles de lo que preguntaste. ¿Cómo copio un archivo? La pregunta y el nombre de la variable me llevan a preguntas más amplias como: "¿Existe una mejor manera de lidiar con el aprovisionamiento de servidores?" Use Maven como un sistema de compilación para generar artefactos desplegables, luego realice estas personalizaciones en módulos separados o en otro lugar completamente. Si compartió un poco más de su entorno de compilación, podría haber una mejor manera: hay complementos para aprovisionar varios servidores. ¿Podría adjuntar un ensamblaje que se desempaqueta en la raíz del servidor? ¿Qué servidor estás usando?

Una vez más, estoy seguro de que hay una forma mejor.

Respondido 14 Feb 21, 14:02

¿Está ahora obsoleto el descriptor de tareas? - Matt

@ Matt Sí, el task el parámetro ahora está en desuso (Complemento Antrun). Deberías usar target en su lugar (desde 1.5). Lamentablemente, hay ejemplos que confunden esto; p.ej target parámetro y version <1.5. - cuh

¿Cómo puede ser esta la respuesta aceptada? Definitivamente debería haber una solicitud de cambio a maven para hacer que la copia sea algo simple. - Wolfgang Fahl

<build>
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.3</version>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include> **/*.properties</include>
            </includes>
        </resource>
    </resources>
    ...
</build>

Respondido 10 Oct 14, 15:10

Gracias @Peter, eso fue útil. Ahora uso el objetivo de recursos de copia de recursos en lugar de antrun. Este último es en realidad mucho más simple e intuitivo de definir, pero no pude lograr que (versión 1.3) pasara todas las propiedades personalizadas de Maven (definidas en section) a antrun, así que cambié a resources-plugin. - cornel mason

Solía ​​pensar que esta era la respuesta correcta ... hasta que me di cuenta de que el complemento de recursos no tiene una configuración de omisión. Antrun es el camino a seguir. - mike mensaje

No debería ser difícil crear un perfil de omisión. No he usado antrun, así que no puedo decir cuál es más fácil / mejor. vivek chavda

Para copiar un archivo use:

        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
                <execution>
                    <id>copy-resource-one</id>
                    <phase>install</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>

                    <configuration>
                        <outputDirectory>${basedir}/destination-folder</outputDirectory>
                        <resources>
                            <resource>
                                <directory>/source-folder</directory>
                                <includes>
                                    <include>file.jar</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
           </executions>
        </plugin>

Para copiar la carpeta con subcarpetas, utilice la siguiente configuración:

           <configuration>
              <outputDirectory>${basedir}/target-folder</outputDirectory>
              <resources>          
                <resource>
                  <directory>/source-folder</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>              
            </configuration>  

Respondido 15 Jul 19, 12:07

Filtración en Maven se refiere a la interpolación de cadenas, por lo que omitiría <filtering> para evitar cambios no deseados en, por ejemplo, archivos de script que utilizan ${...} variables - Geroldo Broser

El complemento de dependencia de maven me ahorró mucho tiempo jugando con tareas de hormigas:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>install-jar</id>
            <phase>install</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>...</groupId>
                        <artifactId>...</artifactId>
                        <version>...</version>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>...</outputDirectory>
                <stripVersion>true</stripVersion>
            </configuration>
        </execution>
    </executions>
</plugin>

La dependencia: copiar está documentado y tiene objetivos más útiles como descomprimir.

Respondido el 15 de diciembre de 17 a las 16:12

No usé Ant durante años y no quiero comenzar a hacerlo por algo tan simple. Así que gracias por esta respuesta. - Gustave

Para una tarea de copia simple, puedo recomendar copiar-renombrar-maven-plugin. Es sencillo y fácil de usar:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>com.coderplus.maven.plugins</groupId>
        <artifactId>copy-rename-maven-plugin</artifactId>
        <version>1.0</version>
        <executions>
          <execution>
            <id>copy-file</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <sourceFile>src/someDirectory/test.environment.properties</sourceFile>
              <destinationFile>target/someDir/environment.properties</destinationFile>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Si desea copiar más de un archivo, reemplace el <sourceFile>...</destinationFile> parte con

<fileSets>
  <fileSet>
    <sourceFile>src/someDirectory/test.environment.properties</sourceFile>
    <destinationFile>target/someDir/environment.properties</destinationFile>
  </fileSet>
  <fileSet>
    <sourceFile>src/someDirectory/test.logback.xml</sourceFile>
    <destinationFile>target/someDir/logback.xml</destinationFile>
  </fileSet>                
</fileSets>

Además, puede especificar múltiples ejecuciones en múltiples fases si es necesario, el segundo objetivo es "cambiar el nombre", que simplemente hace lo que dice mientras el resto de la configuración permanece igual. Para obtener más ejemplos de uso, consulte la Página de uso.

Nota:: Este complemento solo puede copiar archivos, no directorios. (Gracias a @ james.garriss por encontrar esta limitación).

contestado el 26 de mayo de 17 a las 12:05

Aunque me gusta este complemento, es asombroso que no pueda copiar directorios. - james.garriss

@ james.garriss No estaba al tanto de esta limitación, pero lamentablemente tienes razón. Editaré esto en mi respuesta para tal vez ahorrarles a algunas personas el tiempo de encontrarlo por sí mismos. - morten.c

La solución de hormigas anterior es la más fácil de configurar, pero he tenido suerte con el complemento maven-upload-plugin de Atlassian. No pude encontrar una buena documentación, así es como la uso:

<build>
  <plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
    <configuration>
       <resourceSrc>
             ${project.build.directory}/${project.build.finalName}.${project.packaging}
       </resourceSrc>
       <resourceDest>${jboss.deployDir}</resourceDest>
       <serverId>${jboss.host}</serverId>
       <url>${jboss.deployUrl}</url>
     </configuration>
  </plugin>
</build>

Las variables como "$ {jboss.host}" a las que se hace referencia arriba se definen en mi ~ / .m2 / settings.xml y se activan usando perfiles de maven. Esta solución no está restringida a JBoss, esto es solo lo que llamé a mis variables. Tengo un perfil para desarrollo, prueba y en vivo. Entonces, para cargar mi oído en una instancia de jboss en el entorno de prueba, ejecutaría:

mvn upload:upload -P test

Aquí hay un fragmento de settings.xml:

<server>
  <id>localhost</id>
  <username>username</username>
  <password>{Pz+6YRsDJ8dUJD7XE8=} an encrypted password. Supported since maven 2.1</password>
</server>
...
<profiles>
  <profile>
    <id>dev</id>
    <properties>
      <jboss.host>localhost</jboss.host> 
      <jboss.deployDir>/opt/jboss/server/default/deploy/</jboss.deployDir>
      <jboss.deployUrl>scp://root@localhost</jboss.deployUrl>
    </properties>
  </profile>
  <profile>
    <id>test</id>
    <properties>
       <jboss.host>testserver</jboss.host>
       ...

Notas: El repositorio de Atlassian maven que tiene este complemento está aquí: https://maven.atlassian.com/public/

Recomiendo descargar las fuentes y mirar la documentación en el interior para ver todas las características que proporciona el complemento.

`

Respondido 23 Abr '09, 15:04

Bueno, se supone que maven no es bueno para hacer tareas finas y granulares, no es un lenguaje de scripting como bash o ant, es más bien declarativo, dices, necesito una guerra, o un oído, y lo entiendes. Sin embargo, si necesita personalizar cómo debería verse la guerra o la oreja por dentro, tiene un problema. Simplemente no es procedimental como una hormiga, sino declarativa. Esto tiene algunas ventajas al principio y podría tener muchas desventajas al final.

Supongo que el concepto inicial era tener complementos finos, que "simplemente funcionan", pero la realidad es diferente si haces cosas no estándar.

Sin embargo, si pone suficiente esfuerzo en sus poms y pocos complementos personalizados, obtendrá un entorno de construcción mucho mejor como con ant, por ejemplo (depende de su proyecto, por supuesto, pero se vuelve cada vez más cierto para proyectos más grandes).

respondido 06 mar '09, 11:03

He tenido muy buena experiencia con copia-maven-plugin. Tiene una sintaxis mucho más conveniente y concisa en comparación con maven-resources-plugin.

respondido 29 mar '13, 16:03

Desafortunadamente, copy-maven-plugin no es compatible con maven 3.1.x - Hakan

El problema que rastrea la compatibilidad con maven 3.1 está ahí: github.com/evgeny-goldin/maven-plugins/issues/10 - koppor

Olvídate de este plugin ... busca sus bifurcaciones - Kukeltje

Una forma genérica de copiar archivos arbitrarios es utilizar Vagón Maven abstracción de transporte. Puede manejar varios destinos a través de protocolos como file, HTTP, FTP, SCP or WebDAV.

Hay algunos complementos que brindan servicios para copiar archivos mediante el uso de Wagon. Los más notables son:

  • Fuera de la caja Complemento de implementación de Maven

    Aquí debe visitar el deploy-file objetivo. Es bastante inflexible pero puede hacer el trabajo:

    mvn deploy:deploy-file -Dfile=/path/to/your/file.ext -DgroupId=foo 
    -DartifactId=bar -Dversion=1.0 -Durl=<url> -DgeneratePom=false
    

    Desventaja significativa de usar Maven Deploy Plugin es que está diseñado para trabajar con repositorios de Maven. Asume una estructura y metadatos particulares. Puede ver que el archivo se coloca debajo foo/bar/1.0/file-1.0.ext y se crean archivos de suma de comprobación. No hay forma de evitar esto.

  • Complemento Wagon Maven

    Utilice el upload-single objetivo:

    mvn org.codehaus.mojo:wagon-maven-plugin:upload-single
    -Dwagon.fromFile=/path/to/your/file.ext -Dwagon.url=<url>
    

    El uso de Wagon Maven Plugin para copiar es sencillo y parece ser el más versátil.


En los ejemplos anteriores <url> puede ser de cualquier protocolo compatible. Ver la lista de existentes Proveedores de vagones. Por ejemplo

  • copiando archivo localmente: file:///copy/to
  • copiando archivo al host remoto en ejecución SSH: scp://host:22/copy/to


Los ejemplos anteriores pasan parámetros de complementos en la línea de comandos. Alternativamente, los complementos se pueden configurar directamente en POM. Entonces la invocación será simplemente como mvn deploy:deploy-file@configured-execution-id. O puede estar vinculado a una fase de construcción particular.


Tenga en cuenta que para protocolos como SCP para que funcione, deberá definir una extensión en su POM:

<build>
  [...]
  <extensions>
    <extension>
      <groupId>org.apache.maven.wagon</groupId>
      <artifactId>wagon-ssh</artifactId>
      <version>2.12</version>
    </extension>
  </extensions>


Si el destino al que está copiando requiere autenticación, las credenciales se pueden proporcionar a través de Server settings. repositoryId/serverId pasados ​​a los complementos deben coincidir con el servidor definido en la configuración.

Respondido el 24 de enero de 19 a las 08:01

Solo puedo asumir que su propiedad $ {project.server.config} es algo definido de manera personalizada y está fuera del diseño de directorio estándar.

Si es así, usaría la tarea de copiar.

Respondido 25 Feb 09, 17:02

Digamos que me cuido de poner los archivos en el diseño de directorio estándar. ¿Puede Maven copiarlos en el destino tal cual, no en un zip / jar? - josué zorro

Otra forma es agrupar estas cosas en un artefacto utilizando el complemento de ensamblaje. Luego, puede usar el complemento de dependencia para descomprimir estos archivos donde desee. También hay objetivos de copia en el complemento de dependencia para copiar artefactos.

respondido 31 mar '09, 18:03

Pude juntar varias fuentes diferentes para esta respuesta:

...
<repository>
    <id>atlassian</id>
    <name>Atlassian Repo</name>
    <url>https://maven.atlassian.com/content/repositories/atlassian-public</url>
</repository>
...
<dependency>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
</dependency>
...
<plugin>
    <groupId>com.atlassian.maven.plugins</groupId>
    <artifactId>maven-upload-plugin</artifactId>
    <version>1.1</version>
    <configuration>
        <serverId>jira-repo</serverId>
        <resourceSrc>
            ${project.build.directory}/${project.build.finalName}.${project.packaging}
        </resourceSrc>
        <resourceDest>opt/jira/webapps</resourceDest> <!-- note: no leading slash -->
        <url>scp://root@jira</url>
    </configuration>
</plugin>
...

Desde ~/.m2/settings.xml:

...
<servers>
  <server>
    <id>jira-repo</id>
    <username>myusername</username>
    <password>mypassword</password>
  </server>
</servers>
...

Luego ejecute el comando: (el -X es para depuración)

mvn -X upload:upload

Respondido 04 Feb 18, 20:02

Si alguien quiere un control total sobre la ruta de origen y destino, entonces use maven-antrun-plugin's copy La tarea es la mejor opción. Este enfoque le permitirá copiar entre cualquier ruta en el sistema, independientemente de que las rutas en cuestión estén dentro del mvn proyecto o no. Tuve una situación en la que tuve que hacer algunas cosas inusuales como copiar archivos fuente generados desde target directorio de vuelta al src directorio para su posterior procesamiento. En mi situación, esta fue la única opción que funcionó sin problemas. Fragmento de código de muestra de pom.xml:

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.8</version>
        <executions>
            <execution>
                <phase>process-resources</phase>
                <configuration>
                <tasks>
                    <copy file="${basedir}/target/myome/minifyJsSrcDir/myome.min.js" todir="${basedir}/src/main/webapp/app/minifyJsSrcDir"/>
                </tasks>
                </configuration>
                <goals>
                <goal>run</goal>
                </goals>
            </execution>
        </executions>
</plugin>

Respondido 02 Feb 21, 12:02

Para resumir algunas de las buenas respuestas anteriores: Maven está diseñado para crear módulos y copiar los resultados a un repositorio de Maven. Cualquier copia de módulos a un directorio de entrada de implementación / instalador debe realizarse fuera del contexto de la funcionalidad principal de Maven, por ejemplo, con Ant / Maven copia mando.

Respondido 09 Jul 17, 14:07

Ant pertenece a Funcionalidad principal de Maven y Wagon también (aunque el complemento que lo rodea no es un complemento oficial del núcleo de Maven). - Geroldo Broser

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.