Best practice per la copia di file con Maven


194

Ho file di configurazione e vari documenti che voglio copiare dall'ambiente dev alla directory dev-server usando Maven2. Stranamente, Maven non sembra forte in questo compito.

Alcune delle opzioni:

  • Utilizzare semplicemente un'attività di copia in Maven
<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>
  • Utilizzare il plug-in Ant per eseguire la copia da Ant.

    • Costruisci un artefatto di tipo zip , accanto all'artefatto "principale" del POM che di solito è di tipo jar , quindi scompatta quell'artefatto dal repository nella directory di destinazione.

    • plugin per risorse , come menzionato di seguito.

    • Plug-in Maven Assembly - ma questo sembra richiedere molte definizioni manuali, quando voglio fare le cose in modo semplice e "convenzionale".

    • Questa pagina mostra anche come creare un plugin per fare la copia!

    • maven-upload plugin, come menzionato di seguito.

    • maven-dependency-plugin con copia , come indicato di seguito.


Tutti questi sembrano inutilmente ad hoc: Maven dovrebbe eccellere nel fare questi compiti standard senza complicazioni.

Qualche consiglio?


2
Maven si basa sull'idea di un ciclo di vita con fasi, la copia di file casuali su un'attività del server remoto non si adatta davvero a questo. Pensa sempre al tuo progetto nel suo insieme.
André,

3
"Tutto ciò appare inutilmente ad hoc: Maven dovrebbe eccellere nel fare queste attività standard senza problemi e senza problemi." Quello che stai facendo non è un compito standard, di per sé. Se il tuo artefatto fosse una guerra / orecchio, questo sarebbe semplice come usare il plugin cargo (cargo.codehaus.org/Maven2+plugin#Maven2plugin-get…). Quello che stai descrivendo sembra molto specifico per come stai eseguendo le distribuzioni e non per le distribuzioni standard dei contenitori di applicazioni Java. Maven non è davvero orientato a gestire le attività del tempo di distribuzione sui server live, ma è più orientato alla creazione di attività / sviluppo.
Whaley,

67
@ André: sento ripetutamente questa discussione, ma scusate, è BS. Non c'è niente di sbagliato nel pensare al progetto nel suo insieme, ma parte di qualsiasi sistema di compilazione decente dovrebbe essere la funzionalità che mi consente di svolgere l'attività X in modo semplice, come copiare i file, e Maven non può farlo. C'è un motivo per cui così tanti progetti sono comparsi di recente che abbracciano il paradigma build-script-are-code (come Gradle, SBT o Buildr).
Matthias,

Consiglierei di avere un pom.xml per creare gli artefatti e un altro per distribuire un determinato artefatto.
Thorbjørn Ravn Andersen,

Tutti i suggerimenti sopra non sembrano ancora consentirmi di copiare un file specifico da un diverso progetto / artefatto in un progetto maven. Ho alcuni file sotto la cartella src / main / in un artefatto che diventa un vaso e ho provato a usare il plugin maven di dipendenza-copia ma non ho trovato un modo per dire quali file voglio copiare e ottengo l'intero vaso file nel file di assieme in ogni momento. Tutti gli altri suggerimenti qui, come le risorse, non sembrano permettermi di specificare un artefatto piuttosto che le risorse all'interno del progetto
Alexandre Thenorio,

Risposte:


120

Non rifuggire dal plug-in Antrun. Solo perché alcune persone tendono a pensare che Ant e Maven siano in opposizione, non lo sono. Utilizzare l'attività di copia se è necessario eseguire una inevitabile personalizzazione una tantum:

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

Nel rispondere a questa domanda, mi sto concentrando sui dettagli di ciò che hai chiesto. Come copio un file? La domanda e il nome della variabile mi portano a domande più grandi come: "Esiste un modo migliore per gestire il provisioning del server?" Usa Maven come sistema di generazione per generare artefatti distribuibili, quindi esegui queste personalizzazioni in moduli separati o da qualche altra parte. Se hai condiviso un po 'di più il tuo ambiente di costruzione, potrebbe esserci un modo migliore: ci sono plugin per il provisioning di un numero di server. Potresti collegare un assembly decompresso nella radice del server? Quale server stai usando?

Ancora una volta, sono sicuro che c'è un modo migliore.


Il descrittore di attività è ora obsoleto?
Matt

3
@Matt Sì, il taskparametro è ora obsoleto ( Antrun Plugin ). Dovresti targetinvece usare (dal 1.5). Sfortunatamente ci sono esempi che mescolano questo; ad es. targetparametro e version<1.5.
cuh

Come può essere questa la risposta accettata? Sicuramente ci dovrebbe essere una richiesta di modifica a maven per rendere la copia una cosa semplice.
Wolfgang Fahl l'

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

Grazie @Peter, è stato utile. Ora uso l'obiettivo risorse-copia-plugin plug-in anziché antrun. Quest'ultimo è in realtà molto più semplice e intuitivo da definire, ma non sono riuscito a farlo passare (versione 1.3) a tutte le proprietà personalizzate di Maven (definite nella sezione <properties>) su Antrun, quindi sono passato a plugin-risorse.
Cornel Masson,

2
Pensavo che questa fosse la risposta corretta ... fino a quando mi sono reso conto che il plugin delle risorse non ha una configurazione da saltare. Antrun è la strada da percorrere.
Mike Post,

Non dovrebbe essere difficile creare un profilo salta. Non ho usato Antrun, quindi non posso dire quale sia più facile / migliore
Vivek Chavda,

41

Per copiare un file usa:

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

Per copiare una cartella con sottocartelle utilizzare la configurazione successiva:

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

Il filtro in Maven si riferisce all'interpolazione di stringhe, quindi ometterei <filtering>per impedire modifiche indesiderate, ad esempio, per i file di script che utilizzano ${...}variabili.
Gerold Broser,

20

Il plugin per le dipendenze di Maven mi ha fatto risparmiare un sacco di tempo accarezzandomi con le attività formiche:

<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 dipendenza: copia è documentend e ha obiettivi più utili come decomprimere.


3
Non uso Ant da anni e non voglio iniziare a farlo per una cosa così semplice. Quindi grazie per questa risposta.
Gustave

18

Per una semplice attività di copia posso consigliare copy-rename-maven-plugin . È semplice e semplice da usare:

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

Se si desidera copiare più di un file, sostituire la <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>

Inoltre, se necessario, puoi specificare più esecuzioni in più fasi, il secondo obiettivo è "rinomina", che fa semplicemente quello che dice mentre il resto della configurazione rimane lo stesso. Per ulteriori esempi di utilizzo, consultare la Pagina di utilizzo .

Nota : questo plugin può solo copiare file, non directory. (Grazie a @james.garriss per aver trovato questa limitazione.)


2
Anche se mi piace questo plugin, è sorprendente che non riesca a copiare le directory.
james.garriss,

3
@ james.garriss Non ero a conoscenza di questa limitazione, ma sfortunatamente hai ragione. Lo modificherò nella mia risposta per forse salvare alcune persone il tempo di trovarlo da soli.
morten.c,

7

La soluzione di formica sopra è più semplice da configurare, ma ho avuto fortuna usando il plugin maven-upload di Atlassian. Non sono riuscito a trovare una buona documentazione, ecco come lo 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>

Le variabili come "$ {jboss.host}" di cui sopra sono definite nel mio ~ / .m2 / settings.xml e sono attivate usando i profili di Maven. Questa soluzione non è vincolata a JBoss, questo è proprio quello che ho chiamato le mie variabili. Ho un profilo per dev, test e live. Quindi, per caricare il mio orecchio su un'istanza jboss in ambiente di test, eseguirei:

mvn upload:upload -P test

Ecco uno snipet da 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>
       ...

Note: Il repository maven atlantico che ha questo plugin è qui: https://maven.atlassian.com/public/

Consiglio di scaricare le fonti e di consultare la documentazione all'interno per vedere tutte le funzionalità fornite dal plugin.

`


5

Beh, Maven non dovrebbe essere bravo a svolgere compiti granulari, non è un linguaggio di scripting come bash o formica, è piuttosto dichiarativo - dici - ho bisogno di una guerra o di un orecchio e lo capisci. Tuttavia, se devi personalizzare l'aspetto della guerra o dell'orecchio all'interno, hai un problema. Non è solo procedurale come la formica, ma dichiarativo. Questo ha alcuni vantaggi all'inizio e potrebbe avere molti contro alla fine.

Immagino che il concetto iniziale fosse quello di avere dei plugin eccellenti, che "funzionassero" ma la realtà è diversa se si fanno cose non standard.

Se tuttavia fai abbastanza sforzo nei tuoi pom e in alcuni plugin personalizzati, otterrai un ambiente di costruzione molto migliore come con la formica per esempio (dipende ovviamente dal tuo progetto, ma diventa sempre più vero per i progetti più grandi).



4

Un modo generico per copiare file arbitrari consiste nell'utilizzare l' astrazione del trasporto Maven Wagon . E 'in grado di gestire diverse destinazioni tramite protocolli come file, HTTP, FTP, SCPo WebDAV.

Ci sono alcuni plugin che forniscono funzionalità per copiare i file tramite l'uso di Wagon. I più importanti sono:

  • Plug -in Maven Deploy pronto all'uso

    C'è l' deploy-fileobiettivo. È abbastanza inflessibile ma può fare il lavoro:

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

    Uno svantaggio significativo nell'uso Maven Deploy Pluginè che è progettato per funzionare con i repository Maven. Presuppone una struttura e metadati particolari. Puoi vedere che il file è posizionato sotto foo/bar/1.0/file-1.0.exte i file di checksum sono stati creati. Non c'è modo di aggirarlo.

  • Wagon Maven Plugin

    Usa l' upload-singleobiettivo :

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

    L'uso di Wagon Maven Pluginper la copia è semplice e sembra essere il più versatile.


Negli esempi sopra riportati <url>può essere presente qualsiasi protocollo supportato. Consulta l'elenco dei provider Wagon esistenti . Per esempio

  • copiare il file localmente: file:///copy/to
  • copia del file sull'host remoto in esecuzione SSH:scp://host:22/copy/to


Gli esempi precedenti passano i parametri del plugin nella riga di comando. In alternativa, i plugin possono essere configurati direttamente in POM. Quindi l'invocazione sarà semplicemente come mvn deploy:deploy-file@configured-execution-id. Oppure può essere legato a una particolare fase di costruzione.


Per i protocolli che SCPfunzionano, è necessario definire un'estensione in POM:

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


Se la destinazione in cui si sta copiando richiede l'autenticazione, è possibile fornire le credenziali tramite le Serverimpostazioni . repositoryId/ serverIdpassato ai plugin deve corrispondere al server definito nelle impostazioni.


3

Posso solo supporre che la tua proprietà $ {project.server.config} sia qualcosa di personalizzato e sia al di fuori del layout di directory standard.

In tal caso, utilizzerei l'attività di copia.


Diciamo che mi occupo di mettere i file nel layout di directory standard. Maven può copiarli sul bersaglio così com'è, non in una zip / jar?
Joshua Fox,

2

Un altro modo è raggruppare queste cose in un artefatto usando il plugin assembly. Quindi è possibile utilizzare il plug-in di dipendenza per decomprimere questi file dove si desidera. Ci sono anche obiettivi di copia nel plugin di dipendenza per copiare artefatti.


1

Sono stato in grado di mettere insieme un numero di fonti diverse per questa risposta:

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

Da ~/.m2/settings.xml:

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

Quindi eseguire il comando: (-X è per il debug)

mvn -X upload:upload


-1

Per riassumere alcune delle belle risposte sopra: Maven è progettato per costruire moduli e copiare i risultati in un repository Maven. Qualsiasi copia di moduli in una directory di distribuzione / input dell'installer deve essere eseguita al di fuori del contesto della funzionalità principale di Maven, ad esempio con il comando di copia Ant / Maven .


Ant appartiene alla funzionalità principale di Maven e lo stesso vale per Wagon (sebbene il plug-in che lo circonda non sia un plug-in Maven ufficiale).
Gerold Broser,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.