web-dev-qa-db-fra.com

Les meilleures pratiques pour copier des fichiers avec Maven

J'ai des fichiers de configuration et divers documents que je veux copier de l'environnement dev dans le répertoire dev-server à l'aide de Maven2. Étrangement, Maven ne semble pas très fort dans cette tâche.


Certaines des options:

  • Utilisation simple d'une tâche de copie dans Maven

<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>

  • Utilisez le plugin Ant pour exécuter une copie à partir de Ant.

  • Construisez un artefact de type Zip , à côté de l'artefact "principal" du POM qui est généralement de type jar , puis décompressez cet artefact du référentiel dans le répertoire cible.

  • maven-resources , comme mentionné ci-dessous.

  • Maven Assembly plugin - mais cela semble nécessiter beaucoup de définitions manuelles, lorsque je veux faire les choses simplement et "de manière conventionnelle".

  • Cette page montre même comment construire un plugin pour faire de la copie!

  • maven-upload , tel que mentionné ci-dessous.

  • maven-dependency-plugin avec une copie , comme indiqué ci-dessous.


Tout cela semble inutilement ad hoc: Maven est supposé exceller dans l’exécution de ces tâches standard sans complications.

Aucun conseil?

181
Joshua Fox

Ne craignez pas le plugin Antrun. Juste parce que certaines personnes ont tendance à penser que Ant et Maven sont dans l’opposition, ils ne le sont pas. Utilisez la tâche de copie si vous devez effectuer une personnalisation ponctuelle inévitable:

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

En répondant à cette question, je me concentre sur les détails de ce que vous avez demandé. Comment copier un fichier? La question et le nom de la variable m'amènent à des questions plus vastes telles que: "Existe-t-il un meilleur moyen de gérer le provisionnement des serveurs?" Utilisez Maven en tant que système de construction pour générer un artefact déployable, puis effectuez ces personnalisations dans des modules distincts ou ailleurs. Si vous partagiez un peu plus de votre environnement de construction, il existe peut-être un meilleur moyen: des plugins permettent de provisionner un certain nombre de serveurs. Pourriez-vous attacher un assembly qui est décompressé à la racine du serveur? Quel serveur utilisez-vous?

Encore une fois, je suis sûr qu'il existe un meilleur moyen.

111
Tim O'Brien
<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>
133
peter

Pour copier un fichier, utilisez:

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

Pour copier un dossier avec des sous-dossiers, utilisez la configuration suivante:

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

Le plugin maven dependency m'a permis de gagner beaucoup de temps avec les tâches liées aux fourmis:

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

Le dependency: copy est documentend et a des objectifs plus utiles comme décompresser.

18
Tires

Pour une copie simple, je peux recommander copy-rename-maven-plugin . C'est simple et simple à utiliser:

<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 vous souhaitez copier plusieurs fichiers, remplacez la partie <sourceFile>...</destinationFile> par

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

De plus, vous pouvez spécifier plusieurs exécutions en plusieurs phases si nécessaire. Le deuxième objectif est "renommer", ce qui fait simplement ce qui est indiqué tant que le reste de la configuration reste identique. Pour plus d’exemples d’utilisation, reportez-vous à sage-Page .

Remarque : Ce plugin ne peut copier que des fichiers, pas des répertoires. (Merci à @ james.garriss pour avoir trouvé cette limitation.)

15
morten.c

La solution de fourmi ci-dessus est plus facile à configurer, mais j'ai eu de la chance en utilisant le plugin maven-upload-de Atlassian. Je n'ai pas pu trouver une bonne documentation, voici comment je l'utilise:

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

Les variables telles que "$ {jboss.Host}" référencées ci-dessus sont définies dans mon ~/.m2/settings.xml et sont activées à l'aide de profils maven. Cette solution n'est pas limitée à JBoss, c'est ce que j'ai nommé mes variables. J'ai un profil pour dev, test et live. Donc, pour télécharger mon oreille sur une instance de jboss dans un environnement de test, je voudrais exécuter:

mvn upload:upload -P test

Voici un extrait 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>
       ...

Remarques: Le référentiel Atlassian Maven doté de ce plug-in est ici: https://maven.atlassian.com/public/

Je recommande de télécharger les sources et de consulter la documentation à l'intérieur pour voir toutes les fonctionnalités fournies par le plugin.

`

6
Kyle Renfro

Eh bien, Maven n’est pas censé être doué pour effectuer de bonnes tâches granulaires, ce n’est pas un langage de script comme bash ou ant, il est plutôt déclaratif - vous dites - j’ai besoin d’une guerre, ou d’une oreille, et vous l’obtenez. Cependant, si vous devez personnaliser l'apparence de la guerre ou de l'oreille, vous avez un problème. Ce n'est tout simplement pas procédural comme une fourmi, mais déclaratif. Cela a quelques avantages au début et pourrait avoir beaucoup d'inconvénients à la fin.

Je suppose que le concept initial était d'avoir de bons plugins, qui "fonctionnent", mais la réalité est différente si vous faites des choses non standard.

Cependant, si vous mettez suffisamment d'efforts dans vos poms et quelques plugins personnalisés, vous obtiendrez un environnement de construction bien meilleur, comme avec ant par exemple (cela dépend de votre projet bien sûr, mais cela devient de plus en plus vrai pour les projets plus importants).

5
siddhadev

Une manière générique de copier des fichiers arbitraires consiste à utiliser l'abstraction de transport Maven Wagon . Il peut gérer diverses destinations via des protocoles tels que file, HTTP, FTP, SCP ou WebDAV.

Il existe quelques plugins qui permettent de copier des fichiers en utilisant Wagon. Les plus notables sont:

  • Prêt à l'emploi Plugin de déploiement Maven

    Il y a l'objectif deploy-file . Il est assez inflexible mais peut faire le travail:

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

    L’inconvénient majeur de l’utilisation de _Maven Deploy Plugin_ est qu’il est conçu pour fonctionner avec les référentiels Maven. Cela suppose une structure et des métadonnées particulières. Vous pouvez voir que le fichier est placé sous _foo/bar/1.0/file-1.0.ext_ et que les fichiers de somme de contrôle sont créés. Il n'y a pas moyen de contourner cela.

  • Wagon Maven Plugin

    Utilisez l'objectif upload-single :

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

    L'utilisation de _Wagon Maven Plugin_ pour la copie est simple et semble être la plus polyvalente.


Dans les exemples ci-dessus, _<url>_ peut être n’importe quel protocole pris en charge. Voir la liste des fournisseurs de wagons existants . Par exemple

  • copie de fichier localement: _file:///copy/to_
  • copie du fichier sur l'hôte distant exécutant SSH: _scp://Host:22/copy/to_


Les exemples ci-dessus transmettent les paramètres de plug-in dans la ligne de commande. Alternativement, les plugins peuvent être configurés directement dans POM. Ensuite, l'invocation ressemblera simplement à _mvn deploy:deploy-file@configured-execution-id_. Ou il peut être lié à une phase de construction particulière.


Veuillez noter que pour que des protocoles tels que SCP fonctionnent, vous devez définir une extension dans votre POM:

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


Si la destination vers laquelle vous copiez nécessite une authentification, des informations d'identification peuvent être fournies via Server paramètres . repositoryId/serverId transmis aux plug-ins doit correspondre au serveur défini dans les paramètres.

4
user318054

J'ai eu une très bonne expérience avec copy-maven-plugin . Il a une syntaxe beaucoup plus pratique et concise par rapport à maven-resources-plugin.

4
azerole

Je ne peux que supposer que votre propriété $ {project.server.config} est définie par quelque chose de personnalisé et ne fait pas partie de la structure de répertoires standard.

Si oui, alors j'utiliserais la tâche de copie.

3
whaley

Une autre méthode consiste à regrouper ces éléments dans un artefact à l'aide du plug-in Assembly. Ensuite, vous pouvez utiliser le plugin de dépendance pour décompresser ces fichiers où vous le souhaitez. Il existe également des objectifs de copie dans le plug-in de dépendance pour copier des artefacts.

2
Brian Fox

J'ai pu rassembler différentes sources pour cette réponse:

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

De ~/.m2/settings.xml:

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

Puis exécutez la commande: (-X est pour le débogage)

mvn -X upload:upload

1
Brett Dutton