Najlepsze praktyki dotyczące kopiowania plików za pomocą Maven

193

Mam pliki konfiguracyjne i różne dokumenty, które chcę skopiować ze środowiska programistycznego do katalogu dev-server za pomocą Maven2. O dziwo, Maven nie wydaje się silny w tym zadaniu.

Niektóre opcje:

  • Proste użycie zadania kopiowania w Maven
<copy file="src/main/resources/config.properties" tofile="${project.server.config}/config.properties"/>
  • Użyj wtyczki Ant, aby wykonać kopię z Ant.

    • Skonstruuj artefakt typu zip obok „głównego” artefaktu POM, który zwykle jest typu jar , a następnie rozpakuj ten artefakt z repozytorium do katalogu docelowego.

    • Wtyczka maven-resources , jak wspomniano poniżej.

    • Wtyczka Maven Assembly - ale wydaje się, że wymaga to wielu ręcznych definicji, gdy chcę robić rzeczy prosto i „konwencjonalnie”.

    • Ta strona pokazuje nawet, jak zbudować wtyczkę do kopiowania!

    • wtyczka maven-upload , jak wspomniano poniżej.

    • Wtyczka maven-dependence z kopią , jak wspomniano poniżej.


Wszystko to wydaje się niepotrzebnie ad hoc: Maven ma się doskonale wykonywać tych standardowych zadań bez kłopotów i kłopotów.

Jakakolwiek rada?

Joshua Fox
źródło
2
Maven opiera się na idei cyklu życia z fazami, kopiowanie losowych plików do zadania zdalnego serwera tak naprawdę nie pasuje do tego. Zawsze myśl o swoim projekcie jako całości.
André
3
„Wszystko to wydaje się niepotrzebnie ad hoc: Maven powinien celować w wykonywaniu tych standardowych zadań bez kłopotów i kłopotów.” To, co robisz, nie jest standardowym zadaniem. Jeśli twoim artefaktem była wojna / ucho, byłoby to tak proste, jak użycie wtyczki cargo (cargo.codehaus.org/Maven2+plugin#Maven2plugin-get…). To, co opisujesz, brzmi bardzo specyficznie dla tego, jak robisz wdrożenia, a nie standardowe wdrożenia kontenera aplikacji Java. Maven nie jest tak naprawdę nastawiony na obsługę działań związanych z wdrażaniem czasu na serwerach działających na żywo - jest raczej nastawiony na działania związane z budowaniem / tworzeniem.
whaley
67
@ André: Ciągle słyszę ten argument, ale przepraszam, to BS. Nie ma nic złego w myśleniu o projekcie jako całości, ale częścią każdego porządnego systemu kompilacji powinna być funkcjonalność, która pozwoli mi osiągnąć zadanie X w prosty sposób, na przykład kopiowanie plików, a Maven nie może tego zrobić. Jest powód, dla którego ostatnio pojawiło się tak wiele projektów, które obejmują paradygmat build-scripts-are-code (takich jak Gradle, SBT lub Buildr).
Matthias,
Poleciłbym mieć plik pom.xml do budowania artefaktów i inny do wdrażania danego artefaktu.
Thorbjørn Ravn Andersen
Wszystkie powyższe sugestie nadal nie pozwalają mi skopiować konkretnego pliku z innego projektu / artefaktu do projektu maven. Mam kilka plików w folderze src / main / w artefakcie, który staje się słoikiem, i próbowałem użyć wtyczki maven do kopiowania zależności, ale nie znalazłem sposobu, aby powiedzieć, które pliki chcę skopiować, i otrzymuję cały słoik plik w pliku zestawu cały czas. Wszystkie pozostałe sugestie, takie jak zasoby, nie pozwalają mi na określenie artefaktu, a nie zasobów wewnątrz projektu
Alexandre Thenorio,

Odpowiedzi:

119

Nie wahaj się przed wtyczką Antrun. Tylko dlatego, że niektórzy ludzie myślą, że Ant i Maven są w opozycji, nie są. Użyj zadania kopiowania, jeśli chcesz wykonać pewne nieuniknione jednorazowe dostosowanie:

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

Odpowiadając na to pytanie, skupiam się na szczegółach tego, o co pytałeś. Jak skopiować plik? Pytanie i nazwa zmiennej prowadzą mnie do większych pytań, takich jak: „Czy istnieje lepszy sposób radzenia sobie z udostępnianiem serwerów?” Użyj Maven jako systemu kompilacji do wygenerowania artefaktu, który można rozmieścić, a następnie wykonaj te dostosowania w oddzielnych modułach lub w innym miejscu całkowicie. Jeśli udostępniłeś nieco więcej swojego środowiska kompilacji, może istnieć lepszy sposób - istnieją wtyczki do obsługi wielu serwerów. Czy możesz dołączyć zestaw, który jest rozpakowany w katalogu głównym serwera? Z jakiego serwera korzystasz?

Znów jestem pewien, że jest lepszy sposób.

Tim O'Brien
źródło
Czy deskryptor zadania jest teraz przestarzały?
Matt
3
@Matt Tak, taskparametr jest teraz przestarzały ( wtyczka Antrun ). Zamiast tego powinieneś użyć target(od 1.5). Niestety istnieją przykłady, które to pomieszają; np. targetparametr i version<1,5.
cuh
Jak to może być zaakceptowana odpowiedź? Zdecydowanie powinna pojawić się prośba o zmianę do maven, aby uczynić kopiowanie prostą rzeczą.
Wolfgang Fahl,
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>
kay - SE jest złe
źródło
Dzięki @Peter, to było przydatne. Teraz używam celu kopiowania zasobów wtyczki zasobów zamiast antrun. To ostatnie jest w rzeczywistości o wiele prostsze i intuicyjne do zdefiniowania, ale nie mogłem zmusić go (wersja 1.3) do przekazania wszystkich niestandardowych właściwości Maven (zdefiniowanych w sekcji <properties>) do antrun, więc przełączyłem się na wtyczkę zasobów.
Cornel Masson
2
Kiedyś myślałem, że to poprawna odpowiedź ... dopóki nie zdałem sobie sprawy, że wtyczka zasobów nie ma konfiguracji pomijania. Antrun jest właściwą drogą.
Mike Post,
Utworzenie profilu pomijania nie powinno być trudne. Nie korzystałem z antrun, więc nie mogę powiedzieć, które jest łatwiejsze / lepsze
Vivek Chavda
40

Aby skopiować plik, użyj:

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

Aby skopiować folder z podfolderami, użyj następnej konfiguracji:

           <configuration>
              <outputDirectory>${basedir}/target-folder</outputDirectory>
              <resources>          
                <resource>
                  <directory>/source-folder</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>              
            </configuration>  
Alexander Drobyshevsky
źródło
Filtrowanie w Maven odnosi się do interpolacji ciągów, więc pominąłem <filtering>zapobieganie niepożądanym zmianom np. Plików skryptowych, które używają ${...}zmiennych.
GeroldBroser przywraca Monikę
20

Wtyczka zależności maven pozwoliła mi zaoszczędzić wiele czasu na męczeniu się zadaniami mrówek:

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

Zależność: kopia jest documentend i ma bardziej użytecznych celów, takich jak rozpakować.

Opony
źródło
3
Nie używałem Anta od lat i nie chcę zaczynać od tak prostej rzeczy. Dziękuję za tę odpowiedź.
Gustave
17

W przypadku prostych zadań kopiowania mogę polecić wtyczkę copy-rename-maven-plugin . Jest prosty i łatwy w użyciu:

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

Jeśli chcesz skopiować więcej niż jeden plik, zamień <sourceFile>...</destinationFile>część na

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

Ponadto w razie potrzeby możesz określić wiele wykonań w wielu fazach, drugim celem jest „zmiana nazwy”, która po prostu robi to, co mówi, podczas gdy reszta konfiguracji pozostaje taka sama. Więcej przykładów użycia znajduje się na stronie użytkowania .

Uwaga : ta wtyczka może kopiować tylko pliki, a nie katalogi. (Podziękowania dla @ james.garriss za znalezienie tego ograniczenia).

morten.c
źródło
2
Chociaż podoba mi się ta wtyczka, zdumiewające jest to, że nie można skopiować katalogów.
james.garriss
3
@ james.garriss Nie byłem świadomy tego ograniczenia, ale niestety masz rację. Przeredaguję to w mojej odpowiedzi, aby być może zaoszczędzić niektórym ludziom czasu na samodzielne znalezienie tego.
morten.c
7

Powyższe rozwiązanie mrówki jest najłatwiejsze do skonfigurowania, ale miałem szczęście, używając wtyczki maven-upload-plug-in od Atlassian. Nie udało mi się znaleźć dobrej dokumentacji, oto jak z niej korzystam:

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

Zmienne, takie jak „$ {jboss.host}”, o których mowa powyżej, są zdefiniowane w moim ~ / .m2 / settings.xml i są aktywowane za pomocą profili maven. To rozwiązanie nie jest ograniczone do JBoss, to właśnie nazwałem moje zmienne. Mam profil dla programistów, testów i na żywo. Aby przesłać moje ucho do instancji jboss w środowisku testowym, wykonałbym:

mvn upload:upload -P test

Oto fragment z 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>
       ...

Uwagi: Repozytorium Atlassian maven z tą wtyczką znajduje się tutaj: https://maven.atlassian.com/public/

Polecam pobrać źródła i przejrzeć dokumentację w środku, aby zobaczyć wszystkie funkcje wtyczki.

`

Kyle Renfro
źródło
5

Cóż, maven nie powinien być dobry w wykonywaniu drobnych, szczegółowych zadań, nie jest to język skryptowy, taki jak bash czy mrówka, jest raczej deklaratywny - mówisz - potrzebuję wojny lub ucha, i rozumiesz. Jeśli jednak chcesz dostosować wygląd wojny lub ucha, masz problem. To po prostu nie jest proceduralne jak mrówka, ale deklaratywne. Na początku ma to pewne zalety, a na koniec może mieć wiele wad.

Wydaje mi się, że początkową koncepcją było posiadanie świetnych wtyczek, które „po prostu działają”, ale rzeczywistość jest inna, jeśli robisz niestandardowe rzeczy.

Jeśli jednak włożysz wystarczająco dużo wysiłku w swoje poms i kilka niestandardowych wtyczek, otrzymasz znacznie lepsze środowisko kompilacji, jak na przykład w przypadku mrówki (zależy oczywiście od twojego projektu, ale staje się coraz bardziej prawdziwe w przypadku większych projektów).

Siddhadev
źródło
4

Mam bardzo dobre doświadczenia z wtyczką copy-maven . Ma znacznie wygodniejszą i zwięzłą składnię w porównaniu do wtyczki maven-resources.

azerol
źródło
8
Niestety, copy-maven-plugin nie jest kompatybilny z maven 3.1.x
Hakan
2
Problem śledzenia zgodności z maven 3.1 jest następujący: github.com/evgeny-goldin/maven-plugins/issues/10
koppor
Zapomnij o tej wtyczce ... Poszukaj jej widelców
Kukeltje
4

Ogólny sposób kopiowania dowolnych plików polega na wykorzystaniu abstrakcji transportu Maven Wagon . Może obsługiwać różne cele poprzez protokoły podoba file, HTTP, FTP, SCPlub WebDAV.

Istnieje kilka wtyczek, które umożliwiają kopiowanie plików przy użyciu Wagon. Najbardziej godne uwagi są:

  • Out-of-the-box Maven Deploy Plugin

    Jest deploy-filecel. Jest dość mało elastyczny, ale może wykonać zadanie:

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

    Istotną wadą korzystania z Maven Deploy Pluginniego jest to, że jest przeznaczony do pracy z repozytoriami Maven. Zakłada szczególną strukturę i metadane. Możesz zobaczyć, że plik jest umieszczony foo/bar/1.0/file-1.0.exti tworzone są pliki sum kontrolnych. Nie można tego obejść.

  • Wtyczka Wagon Maven

    Użyj upload-singlecelu :

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

    Zastosowanie Wagon Maven Plugindo kopiowania jest proste i wydaje się najbardziej wszechstronne.


W powyższych przykładach <url>może być dowolny obsługiwany protokół. Zobacz listę istniejących dostawców wagonów . Na przykład

  • kopiowanie pliku lokalnie: file:///copy/to
  • kopiowanie pliku do uruchomionego zdalnego hosta SSH:scp://host:22/copy/to


Powyższe przykłady przekazują parametry wtyczki w wierszu poleceń. Alternatywnie wtyczki można skonfigurować bezpośrednio w POM. Wtedy wywołanie będzie po prostu jak mvn deploy:deploy-file@configured-execution-id. Lub może być związany z określoną fazą kompilacji.


Pamiętaj, że dla protokołów takich jak SCPpraca musisz zdefiniować rozszerzenie w POM:

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


Jeśli miejsce docelowe, do którego kopiujesz, wymaga uwierzytelnienia, poświadczenia można podać za pomocą Serverustawień . repositoryId/ serverIdprzekazane do wtyczek musi pasować do serwera zdefiniowanego w ustawieniach.

ᄂ ᄀ
źródło
3

Mogę tylko założyć, że twoja właściwość $ {project.server.config} jest czymś niestandardowym i nie mieści się w standardowym układzie katalogów.

Jeśli tak, skorzystam z zadania kopiowania.

wieloryb
źródło
Powiedzmy, że dbam o umieszczenie plików w standardowym układzie katalogów. Czy Maven może skopiować je do celu w stanie, w jakim się znajduje, a nie w pliku zip / jar?
Joshua Fox
2

Innym sposobem jest spakowanie tych rzeczy w artefakt za pomocą wtyczki asemblera. Następnie możesz użyć wtyczki zależności, aby rozpakować te pliki w dowolnym miejscu. Istnieją również cele kopiowania we wtyczce zależności do kopiowania artefaktów.

Brian Fox
źródło
1

Udało mi się zebrać kilka różnych źródeł tej odpowiedzi:

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

Od ~/.m2/settings.xml:

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

Następnie uruchom polecenie: (-X służy do debugowania)

mvn -X upload:upload

Brett Dutton
źródło
-1

Podsumowując niektóre z powyższych dobrych odpowiedzi: Maven służy do budowania modułów i kopiowania wyników do repozytorium Maven. Wszelkie kopiowanie modułów do katalogu wdrażania / instalatora-wprowadzania musi odbywać się poza kontekstem podstawowej funkcjonalności Maven, np. Za pomocą polecenia kopiowania Ant / Maven .

Joshua Fox
źródło
Ant należy do podstawowej funkcjonalności Maven, podobnie jak Wagon (chociaż otaczająca go wtyczka nie jest oficjalną wtyczką Maven).
GeroldBroser przywraca Monikę