Czytając początkowe zdania artykułu, Twoją uwagę mogły przykuć angielskie terminy w nawiasach - lifecycle, phase, plugin oraz goal. Wplotłem je świadomie, ponieważ reprezentują podstawowe pojęcia Maven2, które odpowiadają pojęciom projektowym - sekwencja (również cykl), etap, wtyczka (również narzędzie) oraz zadanie, odpowiednio. Zrozumienie działania Maven2 to zrozumienie istoty tych pojęć. Usystematyzowanie działań podczas tworzenia oprogramowania, wprowadzone wdrożeniem Maven2, ma zauważalnie pozytywny efekt na kondycję i postępy projeku. Pozwala skorzystać z dobrych praktyk projektowych i programistycznych bez dodatkowych nakładów czasowych oraz finansowych na ich dogłębne poznanie. Prostota korzystania z Maven2 ma niebagatelne znaczenie do osiągnięcia zamierzonego celu - ukończenia projektu na czas z jakością tworzenia "z górnej półki". I wszystko za darmo (pomijając aspekt czasu, który wierzę, że dzięki temu artykułowi spadnie do niezbędnego minimum).
Jako narzędzie pretendujące do miana narzędzia wspierającego zarządzanie projektem informatycznym, Maven2 dostarcza 3 predefiniowanie sekwencje projektowe: default, clean oraz site. Każda sekwencja składa się z etapów. Ilość etapów jest specyficzna dla sekwencji, ale istnieje możliwość ich zmiany. Poniższa tabela przedstawia nazwy etapów dla predefiniowanych sekwencji projektowych w Maven2.
Sekwencja | Etap | |||||||||||||||||||||
default |
| |||||||||||||||||||||
clean |
| |||||||||||||||||||||
site |
|
Z sekwencją i poszczególnym jej etapem związane są pewne wtyczki i ich zadania (aka czynności). Jednym z bardzo trafnych stwierdzeń z jakim się spotkałem to określenie Maven jako środowiska do uruchamiania wtyczek, które z kolei dostarczają zadań (porównać to można do wirtualnej maszyny Javy, która jest środowiskiem uruchomieniowym klas, bądź też do kontenera serwletów, które jest środowiskiem dla serwletów). Etap może nie posiadać przypisanego zadania wtyczki, albo może istnieć ich więcej. Istnieje dodatkowo możliwość przypisania zadania wtyczki do etapu sekwencji w konfiguracji projektu (pom.xml) za pomocą znacznika execution (który będzie tematem przewodnim kolejnego artykułu). Sam typ projektu (wartość znacznika packaging, tj. pom, jar, maven-plugin, ejb, war, ear, rar, par, ejb3) również wyznacza określone wtyczki i ich zadania do poszczególnych etapów. Poniższa tabela przedstawia nazwy etapów dla wspomnianych typów packaging.
packaging | sekwencja | etap | wtyczka:zadanie | ||
pom | default | package | org.apache.maven.plugins:maven-site-plugin:attach-descriptor | ||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
jar | default | process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-test-resources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package | org.apache.maven.plugins:maven-jar-plugin:jar | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
maven-plugin | default | generate-resources | org.apache.maven.plugins:maven-plugin-plugin:descriptor | ||
process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-test-resources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package |
| ||||
install |
| ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
ejb | default | process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-test-resources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package | org.apache.maven.plugins:maven-ejb-plugin:ejb | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
war | default | process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-test-resources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package | org.apache.maven.plugins:maven-war-plugin:war | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
ear | default | generateresources | org.apache.maven.plugins:maven-ear-plugin:generate-application-xml | ||
process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||||
package | org.apache.maven.plugins:maven-ear-plugin:ear | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
rar | default | process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-test-resources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package | org.apache.maven.plugins:maven-rar-plugin:rar | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
par | default | process-resources | org.apache.maven.plugins:maven-resources-plugin:resources | ||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-test-resources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package | org.apache.maven.plugins:maven-par-plugin:par | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy | ||||
ejb3 | default | processresources | org.apache.maven.plugins:maven-resources-plugin:resources | ||
compile | org.apache.maven.plugins:maven-compiler-plugin:compile | ||||
process-testresources | org.apache.maven.plugins:maven-resources-plugin:testResources | ||||
test-compile | org.apache.maven.plugins:maven-compiler-plugin:testCompile | ||||
test | org.apache.maven.plugins:maven-surefire-plugin:test | ||||
package | org.apache.maven.plugins:maven-ejb3-plugin:ejb3 | ||||
install | org.apache.maven.plugins:maven-install-plugin:install | ||||
deploy | org.apache.maven.plugins:maven-deploy-plugin:deploy |
Rozpoczynając pracę, Maven2 rozpoczyna od wyznaczenia sekwencji i jej etapów. Następnie mapuje je na odpowiednie zadania wtyczek (w tym celu odczytuje predefiniowaną konfigurację sekwencji i nakłada na to definicję etapów związaną z packaging i executions) i ostatecznie wykonuje zadania zgodnie z ich kolejnością wyznaczoną przez etapy w sekwencji. Kolejność wykonywania zadań można prześledzić podczas uruchomienia mvn, gdzie każda wtyczka i jej zadanie wypisywane są w schemacie [INFO] [wtyczka:zadanie], np. [INFO] [jar:jar]. Poza wyspecyfikowaniem etapu istnieje również możliwość uruchomienia Maven2 z konkretnym zadaniem wtyczki. Definicja domyślnie wykonywanego zadania bądź etapu w projekcie może również zostać wyspecyfikowana w sekcji <build> jako <defaultGoal> w pom.xml. Jeśli nie podano etapu bądź zadania na linii poleceń, Maven2 oczekuje wspomnianej konfiguracji projektu w sekcji <defaultGoal>.
Przyjrzyjmy się kilku przykładom dla zobrazowania przedstawionego materiału. Zakłada się, że wykonanie poniższych poleceń odbywa się w projekcie obsługiwanym przez Maven2 (innymi słowy istnieje plik pom.xml).
- Uruchamiamy polecenie mvn bez wyspecyfikowanego etapu bądź zadania wtyczki.
$ mvn
Osobiście uważam, że komunikat jest mylący, gdyż install nie jest zadaniem (goal), ale etapem (phase) w sekwencji (lifecycle) default. Należy zatem rozumieć ten komunikat jako wskazanie do wykonania wszystkich zadań przypisanych do etapów w sekwencji default, począwszy od pierwszego a skończywszy na install.
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ----------------------------------------------------------------------------
[INFO] You must specify at least one goal. Try 'install'
[INFO] ----------------------------------------------------------------------------
...
Sprawdźmy, czy istnieje Polskie tłumaczenie, które może być bardziej adekwatne.$ mvn -Duser.language=pl_PL
Niestety w tym przypadku takie tłumaczenie nie istnieje i uruchomienie z opcją -e również nie dostarcza więcej informacji. Niektóre jednak komentarze Maven2 zostały spolonizowane.
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ----------------------------------------------------------------------------
[INFO] You must specify at least one goal. Try 'install'
[INFO] ----------------------------------------------------------------------------
... - Uruchommy polecenie mvn z nazwą nieistniejącego etapu, np. etap.
$ mvn etap
Komunikat jest tym razem bardziej dokładny i dowiadujemy się, że konieczne jest podanie istniejącego etapu bądź zadania w odpowiednim formacie (temat wtyczek będzie tematem jednego z kolejnych artykułów).
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ----------------------------------------------------------------------------
[INFO] Invalid task 'etap': you must specify a valid lifecycle phase, or a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal
[INFO] ----------------------------------------------------------------------------
... - Uruchommy polecenie mvn z poprawnym etapem w sekwencji default, np. test.
$ mvn test
Jak można zauważyć wykonanie etapu test zakończy się pomyślnie, a w trakcie wykonywania kolejnych etapów zostaną wykonane zadania wtyczek przypisanych do nich.
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building Projekt Demonstracyjny Maven2
[INFO] task-segment: [test]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
...
[INFO] [compiler:compile]
...
[INFO] [resources:testResources]
...
[INFO] [compiler:testCompile]
...
[INFO] [surefire:test]
...
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
... - Uruchommy powyższe polecenie ponownie zmodyfikowawszy wartość packaging w pom.xml, np. maven-plugin.
$ mvn test
Tym razem wykonane zadania różnią się o początkową wtyczkę plugin. Jest to potwierdzenie wpływu konfiguracji sekcji packaging na listę zadań do wykonania.
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building Projekt Demonstracyjny Maven2
[INFO] task-segment: [test]
[INFO] ----------------------------------------------------------------------------
...
[INFO] [plugin:descriptor]
...
[INFO] [resources:resources]
...
[INFO] [compiler:compile]
...
[INFO] [resources:testResources]
...
[INFO] [compiler:testCompile]
...
[INFO] [surefire:test]
...
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ---------------------------------------------------------------------------- - Uruchommy polecenie mvn z podaniem wtyczki surefire bez wskazania jej zadania.
$ mvn surefire
Zgodnie z komunikatem parametr bez dwukropka traktowany jest jako nazwa etapu, a skoro taki nie istnieje Maven2 kończy działanie z komunikatem błędu.
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ----------------------------------------------------------------------------
[INFO] Invalid task 'surefire': you must specify a valid lifecycle phase, or a goal in the format plugin:goal or pluginGroupId:pluginArtifactId:pluginVersion:goal
[INFO] ----------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ---------------------------------------------------------------------------- - Uruchommy polecenie mvn z wyspecyfikowaną wtyczką surefire z zadanym zadaniem, np. test, który mogliśmy zauważyć uruchamiany we wcześniejszych przykładach (wraz z innymi poprzedzającymi zadaniami).
$ mvn surefire:test
Na uwagę zasługuje fakt, że wykonanie wtyczki nie zostało poprzedzone wykonaniem żadnego innego zadania, co pozwala na uruchomienie wtyczek pojedyńczo. Jest to szczególnie przydatne z wtyczkami, które nie są przypisane do żadnej sekwencji.
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'surefire'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building Projekt Demonstracyjny Maven2
[INFO] task-segment: [surefire:test]
[INFO] ----------------------------------------------------------------------------
[INFO] [surefire:test]
...
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ---------------------------------------------------------------------------- - Na koniec uruchommy polecenie mvn z 2 etapami należącymi do różnych sekwencji oraz zadanie wtyczki, której wykonanie jest częścią uruchamiania etapów.
$ mvn clean package surefire:test
Wszystkie etapy oraz zadanie zostały poprawnie rozpoznane przez Maven2. Wykonanie etapów wiąże się z wyznaczeniem wtyczek i ich zadań, a następnie uruchomieniu zgodnie z kolejnością związanych z nimi etapów. Wyjątek stanowi wykonanie zadania surefire:test, który jest wykonany zgodnie z jego pozycją na linii poleceń, czyli po pomyślnym uruchomieniu zadań związanych z etapami.
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'surefire'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building Projekt Demonstracyjny Maven2
[INFO] task-segment: [clean, package, surefire:test]
[INFO] ----------------------------------------------------------------------------
[INFO] [clean:clean]
...
[INFO] [plugin:descriptor]
...
[INFO] [resources:resources]
...
[INFO] [compiler:compile]
...
[INFO] [resources:testResources]
...
[INFO] [compiler:testCompile]
...
[INFO] [surefire:test]
...
[INFO] [jar:jar]
...
[INFO] [plugin:addPluginArtifactMetadata]
[INFO] [surefire:test]
...
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
Znajomość wtyczek i dostarczanych przez nie zadań jest istotnym elementem zrozumienia działania Apache Maven. Wersja druga projektu - Maven2 - wprowadza kolejne pojęcia - sekwencja (lifecycle) oraz etap (phase). Wyróżniamy 3 predefiniowane sekwencje z zadanymi etapami, do których przypisane są zadania wtyczek. Dzięki takiemu podejściu projekty mogą skorzystać z dobrych praktyk inżynierskich podnoszących jakość projektu niewielkim kosztem. Znajomość Maven2 i jego konfiguracji oraz umiejętność zrozumienia zawartości pom.xml pozwala na łatwe wdrożenie nowych osób do projektu z punktu widzenia jego zarządzania. Poza samym tworzeniem elementów składowych projektu - klasy, konfiguracje, modele, etc. - jest to kluczowy składnik wpływający na czasowe zakończenie projektu. Znosi to również konieczność wprowadzania tych samych ustawień z projektu na projekt (nawet mimo możliwości ich kopiowania, które zazwyczaj kończy się błędami trudnymi do zdiagnozowania). Temat jest stosunkowo zawiły, ale sądzę, że lektura artykułu pozwoli na łatwiejsze zrozumienie działania Maven2.
ADNOTACJA: Nie spotkałem się jeszcze z polskimi odpowiednikami pojęć - lifecycle, phase oraz goal w kontekście Maven, więc pokusiłem się na ich własne spolszczenie. Jeśli znasz lepsze dla nich polskie tłumaczenia, koniecznie się ze mną skontaktuj. Jako rekompensatę mogę jedynie obiecać opublikowanie imienia i nazwiska wraz z ciekawymi propozycjami w kolejnych artykułach.
Komentarze, spostrzeżenia mile widziane. Skorzystaj z możliwości komentowania artykułu, poniżej, albo wyślij komentarz na moją skrzynkę.