Kontynuując myśl z poprzedniego artykułu wyjaśnijmy sobie jakie są cykle życia projektu w ujęciu Mavena. Ta idea jest najistotniejsza w całym narzędziu, ponieważ definiuje proces budowania oraz dystrybucji tworzonych aplikacji. Nie przedłużając przejdźmy do przedstawienia tych cykli i sprawdźmy co się na nie składa.
Wbudowane cykle życia
W celu wdrożenia i dystrybucji docelowego projektu Maven musi go zbudować w oparciu o określony cykl życia, inaczej mówiąc lifecycle. Domyślnie dostępne są 3 takie cykle:
- default - główny lifecycle, którego odpowiedzialnością jest wdrożenie projektu
- clean - czyści projekt oraz usuwa wszystkie wygenerowane pliki z poprzedniego budowania
- site - tworzy dokumentację projektu w formie strony
Na każdy z cykli składa się kilka phases. Dla clean są to 3 phases, dla site - 4 phases, natomiast dla default aż 23 phases. Przechodząc dalej, czym są dokładnie te “fazy”?
Czym są phases Mavena?
Phase w Mavenie to inaczej krok, element składowy wybranego cyklu życia budowania projektu, który odpowiedzialny jest za wykonanie danego zadania. Przyjrzyjmy się, więc osiemu najważniejszym phases dla wcześniej poznanego default:
- validate - weryfikuje czy wszystkie niezbędne informacje do zbudowania projektu są dostępne
- compile - kompiluje kod źródłowy
- test - uruchamia wszystkie testy jednostkowe
- package - pakuje skompilowany kod do formatu dystrybucji jakim jest np. jar albo war
- verify - sprawdza czy spakowany projekt spełnia podane kryteria jakości np. checkstyle
- install - instaluje paczkę na lokalnym repozytorium
- deploy - kopiuje paczkę do zewnętrznego repozytorium
Resztę możemy znaleźć na stronie Mavena. Żeby uruchomić dany phase w wierszu poleceń musimy podać następująca komendę mvn <PHASE>
. Tylko jest tutaj istotna jedna bardzo ważna rzecz: uruchomiony zostanie nie tylko wybrany phase, ale również wszystkie go poprzedzające. Jest to bardzo logiczne, ponieważ, aby przetestować projekt trzeba go najpierw skompilować. Dla przykładu jeśli napiszemy mvn deploy
, co jest ostatnim phase w cyklu default, to wykonają się wszystkie 22 poprzedzające go kroki wraz z nim.
Wywołanie poprzedzających phases przy użyciu wybranego phase
Nie każdy phase powinien być wywołany z wiersza poleceń
Istnieją takie phases, które raczej nie powinny znaleźć się w roli komendy w konsoli. Łatwo je rozpoznać, ponieważ zaczynają się od prefiksu pre-*, post-* czy process-*. Są to raczej części składowe jakiegoś procesu, które wytwarzają pośrednie rezultaty kompletnie nieprzydatne poza nim. Z drugiej strony jeśli użyjemy phase np. integration-test bez wywołania jego części składowych to możemy otrzymać środowisko znajdujące się w stanie zawieszenia. Wtedy uruchomiony kontener Dockerowy czy serwer Tomcata może pozostać uruchomiony i Maven nie zakończy działania sam z siebie.
No dobrze, możemy pójść jeszcze dalej w rozdrabnianiu tych dostępnych komend. Z dokumentacji Mavena dowiadujemy się, że każdy phase składa się z jeszcze mniejszych części nazywanych goals.
Najmniejsza składowa, czyli goals
Goal jest najmniejszą jednostką z całej tej organizacji narzędzia. Reprezentuje on część pluginu, który został zaprogramowany do wykonania specjalistycznego zadania, którego już nie deleguje dalej. Phase grupuje w sobie goals i wykonuje je sekwencyjnie, w kolejności jakiej zostały zadeklarowane. Przyjrzyjmy się zatem kilku przykładom:
- compiler:compile - goal compile z pluginu o nazwie compiler (podpięty jest do phase compile)
- compiler:testCompile - goal testCompile z pluginu o nazwie compiler (podpięty jest do phase test-compile)
- surefire:test - goal test z pluginu o nazwie surefire (podpięty jest do phase test)
- install:install - goal install z pluginu o nazwie install (podpięty jest do phase install)
- jar:jar - goal jar z pluginu o nazwie jar (podpięty jest do phase package)
Wypada dodatkowo doprecyzować, że nazwa pluginu jak np. compiler czy surefire to tylko skrót dla pełnej nazwy - maven-compiler-plugin i maven-surefire-plugin.
Wpisując komendę mvn help:describe -Dcmd=<PHASENAME>
do wiersza poleceń, będąc w katalogu projektu z wcześniejszego artykułu, (oczywiście podmieniając PHASENAME na np. compile) otrzymamy poniższy komunikat.
'compile' is a phase corresponding to this plugin:
org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
It is a part of the lifecycle for the POM packaging 'jar'. This lifecycle includes the following phases:
* validate: Not defined
* initialize: Not defined
* generate-sources: Not defined
* process-sources: Not defined
* generate-resources: Not defined
* process-resources: org.apache.maven.plugins:maven-resources-plugin:2.6:resources
* compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
* process-classes: Not defined
* generate-test-sources: Not defined
* process-test-sources: Not defined
* generate-test-resources: Not defined
* process-test-resources: org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
* test-compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
* process-test-classes: Not defined
* test: org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
* prepare-package: Not defined
* package: org.apache.maven.plugins:maven-jar-plugin:2.4:jar
* pre-integration-test: Not defined
* integration-test: Not defined
* post-integration-test: Not defined
* verify: Not defined
* install: org.apache.maven.plugins:maven-install-plugin:2.4:install
* deploy: org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy
Potwierdziliśmy tym samy, że phase compile korzysta z pluginu maven-compiler-plugin, a dokładniej z jego goal o nazwie compile. Przy okazji dostajemy informację o reszcie phases i np. phase deploy korzysta z goal pluginu maven-deploy-plugin deploy. Muszę przyznać, że jest to zagmatwane na pierwszy rzut oka, ponieważ najczęściej wszystkie składowe mają tą samą nazwę i ciężko dojść co jest czym. Jednak mam nadzieję, że ten opis pomógł Ci to lepiej zrozumieć.
Przy okazji dodam, że phase ma zależność do goal 0..*, czyli może mieć zero, jeden albo wiele goals. Jeżeli nie ma żadnej składowej to w ogóle się nie wykona, natomiast jeśli jest już co najmniej jeden goal to taki phase wykona się na 100%.
Poszczególne części składowe komend Mavena
Wywołanie goal z konsoli
Możemy bezpośrednio wywołać dany goal nawet jeśli nie jest podpięty pod żaden phase. Dokonujemy tego przez użycie komendy mvn <PLUGIN>:<GOAL>
. Każdy plugin ma w sobie goal o nazwie help, więc dzięki wywołaniu go w konsoli przy wykorzystaniu wcześniej pokazanej składni (np. dla pluginu compiler - mvn compiler:help
) dowiadujemy się jakie goals są dostępne w danym pluginie.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--- maven-compiler-plugin:3.8.0:help (default-cli) @ my-app ---
Apache Maven Compiler Plugin 3.8.0
The Compiler Plugin is used to compile the sources of your project.
This plugin has 3 goals:
compiler:compile
Compiles application sources
compiler:help
Display help information on maven-compiler-plugin.
Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display parameter
details.
compiler:testCompile
Compiles application test sources.
Jak widać mamy 3 goals: help, compile oraz testCompile, które poznaliśmy wcześniej.
Sposób sekwencyjnego uruchamiania phases i goals z konsoli
Z wiersza poleceń możemy wywoływać poszczególne phases i goals pojedynczo, czyli np. mvn compile
, mvn install
, mvn deploy:deploy
czy mvn surefire:test
. Jednak istnieje również możliwość ich łączenia. Robimy to po prostu podając kolejne polecenia oddzielone spacją.
1
mvn clean dependency:copy-dependencies package
Na początku uruchomiony zostanie phase clean z lifecycle clean (wszystkie phases poprzedzające clean wraz z nim), następny na ogień pójdzie goal copy-dependencies z pluginu dependency i finalnie phase package (poprzedzające phases wraz z package).
Podsumowanie
Mam nadzieję, że nie zagmatwałem całej tej filozofii z uruchamianiem odpowiednich zadań Mavena. Również liczę na to, że teraz już będziesz wiedział/a co się dzieje w tle jeżeli wpiszesz mvn clean install
po raz kolejny do konsoli. W następnym artykule chciałbym zagłębić się w strukturę pliku pom.xml, na którego lekturę już teraz serdecznie Cię zapraszam!