maven - que - mvn package
Mejores prácticas para copiar archivos con Maven (13)
Bueno, se supone que maven no es bueno para hacer tareas finas granulares, no es un lenguaje de scripting como bash o hormiga, es bastante declarativo, dices, necesito una guerra o un oído, y lo entiendes. Sin embargo, si necesita personalizar el aspecto de la guerra o el oído, tiene un problema. Simplemente no es procedimental como la hormiga, sino declarativa. Esto tiene algunos pros al principio, y podría tener muchas desventajas al final.
Supongo que el concepto inicial fue tener complementos finos, que "simplemente funcionan", pero la realidad es diferente si haces cosas no estándar.
Sin embargo, si pones suficiente esfuerzo en tus poms y en algunos complementos personalizados, obtendrás un entorno de construcción mucho mejor que con hormiga por ejemplo (depende de tu proyecto, por supuesto, pero se vuelve cada vez más cierto para proyectos más grandes).
Tengo archivos de configuración y varios documentos que quiero copiar desde el entorno de desarrollo al directorio dev-server usando Maven2. Extrañamente, Maven no parece fuerte en esta tarea.
Algunas de las opciones:
- Uso simple de una tarea de copia en Maven
<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>
Use el plugin Ant para ejecutar la copia de Ant.
Construye un artefacto de tipo zip , junto con el artefacto "principal" del POM que generalmente es de tipo jar , luego descomprime ese artefacto del repositorio en el directorio de destino.
maven-resource plugin, como se menciona a continuación.
El complemento Maven Assembly, pero parece necesitar muchas definiciones manuales, cuando quiero hacer las cosas de manera simple y "convencional".
¡Esta página incluso muestra cómo crear un complemento para hacer copias!
maven-upload plugin, como se menciona a continuación.
maven-dependency-plugin with copy , como se menciona a continuación.
Todo esto parece innecesariamente ad hoc: se supone que Maven debe sobresalir al realizar estas tareas estándar sin problemas ni molestias.
¿Algún consejo?
El complemento de dependencia maven me ahorró mucho tiempo acariciando las tareas ant y:
<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 dependency:copy es documental y tiene objetivos más útiles, como desempaquetar.
He tenido muy buena experiencia con copy-maven-plugin . Tiene una sintaxis mucho más conveniente y concisa en comparación con maven-resources-plugin.
La solución de la hormiga anterior es más fácil de configurar, pero he tenido suerte usando 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}" mencionadas anteriormente están definidas en mi ~ / .m2 / settings.xml y se activan utilizando perfiles maven. Esta solución no está restringida a JBoss, esto es lo que llamé mis variables. Tengo un perfil para desarrollador, prueba y en vivo. Entonces, para subir mi oído a una instancia de jboss en el entorno de prueba, ejecutaría:
mvn upload:upload -P test
Aquí hay un snipet 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 repo maven de Atlassian que tiene este complemento está aquí: https://maven.atlassian.com/public/
Recomiendo descargar las fuentes y mirar la documentación interna para ver todas las características que proporciona el complemento.
`
No te intimides con el plugin Antrun. Solo porque algunas personas tienden a pensar que Ant y Maven están en oposición, no lo son. 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>
<tasks>
<!--
Place any Ant task here. You can add anything
you can add between <target> and </target> in a
build.xml.
-->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
Al contestar esta pregunta, me estoy enfocando 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: "¿Hay alguna manera mejor de lidiar con el aprovisionamiento de servidores?" Utilice Maven como un sistema de compilación para generar artefactos desplegables, luego realice estas personalizaciones en módulos separados o en otro lugar completamente distinto. Si compartió un poco más de su entorno de compilación, podría haber una forma mejor: hay complementos para aprovisionar una cantidad de servidores. ¿Podría adjuntar un conjunto desempaquetado en la raíz del servidor? ¿Qué servidor estás usando?
De nuevo, estoy seguro de que hay una mejor manera.
Otra forma es agrupar estas cosas en un artefacto usando el plugin 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.
Para copiar un archivo, use:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</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 usa la siguiente configuración:
<configuration>
<outputDirectory>${basedir}/target-folder</outputDirectory>
<resources>
<resource>
<directory>/source-folder</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
Para resumir algunas de las buenas respuestas anteriores: Maven está diseñado para construir módulos y copiar los resultados en un repositorio de Maven. Cualquier copia de módulos en un directorio de implementación / instalación de instalador debe realizarse fuera del contexto de la funcionalidad central de Maven, por ejemplo, con el comando de copia Ant / Maven.
Para un simple copy-tasks, puedo recomendar copy-rename-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 la parte <sourceFile>...</destinationFile>
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 Usage-Page .
Nota : Este complemento solo puede copiar archivos, no directorios. (Gracias a @ james.garriss por encontrar esta limitación).
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>
...
A continuación, ejecute el comando: (el -X es para depuración)
mvn -X upload:upload
Solo puedo suponer que su propiedad $ {project.server.config} es algo definido a la medida y está fuera del diseño del directorio estándar.
Si es así, entonces utilizaría la tarea de copia.
Una forma genérica de copiar archivos arbitrarios es utilizar la abstracción de transporte de Maven Wagon . Puede manejar varios destinos a través de protocolos como file
, HTTP
, FTP
, SCP
o WebDAV
.
Hay algunos complementos que proporcionan instalaciones para copiar archivos mediante el uso de Wagon
. Los más notables son:
Completo plugin de Maven Deploy
Existe el objetivo del
deploy-file
. 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
Una desventaja significativa de utilizar
Maven Deploy Plugin
es que está diseñado para funcionar con repositorios Maven. Asume una estructura y metadatos particulares. Puede ver que el archivo se coloca debajo defoo/bar/1.0/file-1.0.ext
y se crean los archivos de suma de comprobación. No hay forma de evitar esto.Complemento de Wagon Maven
Use el objetivo de
upload-single
: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. Vea la lista de proveedores de Wagon existentes. Por ejemplo
- copiando archivo localmente:
file:///copy/to
- copiando archivo al host remoto ejecutando
SSH
:scp://host:22/copy/to
Los ejemplos anteriores pasan los parámetros del complemento en la línea de comando. 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 ligado a una fase de construcción particular.
Tenga en cuenta que para que los protocolos como SCP
funcionen necesitará 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 la configuración del Server
. repositoryId
/ serverId
pasado a los complementos debe coincidir con el servidor definido en la configuración.
<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>