Konfiguracja wtyczek w Apache Maven 2
Z Jacek Laskowski - Wiki Projektanta Java EE
Dzisiaj przyszło mi zmagać się z tematem, który od dawna mnie nurtował, ale nigdy nie znalazłem dostatecznie dużo czasu, aby go rozpracować. Tym razem się udało i ostatecznie mogłem kolejny temat wykreślić z listy "Do Zrobienia". Tym tematem była konfiguracja wtyczek w Apache Maven 2 (dalej zwanego jako M2). Ktoś mógłby powiedzieć, że wtyczki to fundamentalne pojęcie w M2 i znajomość konfiguracji wtyczek jest niezbędna, ale jak widać jestem przykładem osoby, która od lat korzysta z M2, a jednak temat konfiguracji męczył mnie, ale nie na tyle, aby rozpracować go raz, a dobrze. Potwierdza się opinia, że korzystajmy z narzędzi, a nie uczmy się ich na wylot, ale z drugiej strony widzę jak wiele czasu straciłem na zadania, które mogłem wykonać zdecydowanie szybciej, gdybym tylko miał zacięcie do przeczytania dostępnej dokumentacji.
Do zapamiętania: Zawsze przestudiować dostępną dokumentację zanim rozpocznie się pracę z narzędziem.
Moje prezentacje M2 możesz znaleźć w następujących artykułach:
- Tworzenie aplikacji Java EE 5 z Apache Maven 2 i Glassfish
- Pakunki OSGi w projekcie wielomodułowym Apache Maven 2 z maven-bundle-plugin
- Nauka Java Persistence z Apache Maven 2 i dostawcami JPA: OpenJPA, Hibernate i TopLink
oraz w Notatniku Projektanta Java EE pod kategorią maven2. Szczególnie polecany jest artykuł Podstawowe pojęcia Maven2: sekwencje, etapy, wtyczki i zadania i Zarządzanie projektem za pomocą Apache Maven 2, które gruntownie wprowadzają w temat M2.
Koncepcję konfiguracji wtyczek przedstawię na przykładzie wtyczki maven-antrun-plugin (dalej zwanej jako wtyczka antrun, albo po prostu antrun). Postaram się prezentować przykłady, które będę omawiał (co będzie miało tę zaletę, że będzie podstawą dla kolejnego tematu do prezentacji na spotkaniu Warszawa JUG ;-)). Nie czekając ani dłużej przejdźmy do konkretów.
Zaczniemy od stworzenia projektu zarządzanego przez M2.
$ mvn archetype:create -DgroupId=pl.jaceklaskowski.m2 -DartifactId=artykul
Wszystkie kolejne czynności będą wykonywane w katalogu artykul.
Następny krok to poznanie wszystkich dostępnych zadań jakie udostępnia wtyczka antrun. Mamy dwa wyjścia - polegać na dokumentacji (która może być niepełna, ale z ciekawymi i często niebanalnymi przykładami) - maven-antrun-plugin, albo skorzystać z innej wtyczki, która odczyta dostępne zadania korzystając z mechanizmów M2, tj. maven-help-plugin. Oba podejścia mają swoje wady i zalety, więc rozpoczniemy od rozpoznania tematu od lektury dokumentacji wtyczki.
Dokumentacja wtyczek jest tworzona narzędziami M2, więc korzystają z tych samych szablonów do jej tworzenia i zauważyć można ich duże podobieństwo. Znacząco upraszcza to poznawanie nowej wtyczki (kolejne wdrożenie idei Configuration by Convention znane z Ruby on Rails albo Configuration by Exception znane z Java Persistence API, gdzie polegamy na ustawieniach domyślnych, a modyfikacje konfiguracji wprowadzamy rzadko i wyłącznie w szczególnych przypadkach). Z dokumentacji antrun dowiadujemy się, że jej celem jest wykonywanie zadań innego projektu do zarządzania projektem, protoplasty M2 - Apache Ant i stąd dostępne jest wyłącznie jedno zadanie - run.
Dla potwierdzenia, możemy skorzystać z wtyczki maven-help-plugin, aby rozpoznać dostępne zadania antrun.
$ mvn help:describe -Dplugin=antrun -Dfull=true [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'help'. [INFO] ---------------------------------------------------------------------------- [INFO] Building artykul [INFO] task-segment: [help:describe] (aggregator-style) [INFO] ---------------------------------------------------------------------------- [INFO] [help:describe] [INFO] Plugin: 'org.apache.maven.plugins:maven-antrun-plugin:1.1' ----------------------------------------------- Group Id: org.apache.maven.plugins Artifact Id: maven-antrun-plugin Version: 1.1 Goal Prefix: antrun Description: Runs ant scripts embedded in the POM Mojos: =============================================== Goal: 'run' =============================================== Description: Maven AntRun Mojo. This plugin provides the capability of calling ant tasks from a POM. It is encouraged to move the actual tasks to a separate build.xml file and call that file with an <ant/> task. Implementation: org.apache.maven.plugin.antrun.AntRunMojo Language: java
, czyli tym razem dostępna dokumentacja odzwierciedla stan faktyczny.
Rozpoczniemy od wykonania M2 z wywołaniem wtyczki antrun.
$ mvn antrun:run [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'antrun'. [INFO] ---------------------------------------------------------------------------- [INFO] Building artykul [INFO] task-segment: [antrun:run] [INFO] ---------------------------------------------------------------------------- [INFO] [antrun:run] [INFO] Executing tasks [INFO] Executed tasks [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: < 1 second [INFO] Finished at: Thu Apr 19 14:43:53 CEST 2007 [INFO] Final Memory: 2M/254M [INFO] ------------------------------------------------------------------------
Wszystko działa poprawnie, bo brak zadań Ant do wykonania przez wtyczkę antrun to również zadanie tyle, że puste, więc wszystko kończy się pomyślnie.
Sprawmy, aby antrun wykonał zadanie echo. Sercem projektu zarządzanego przez M2 jest plik konfiguracyjny pom.xml (obiektowy model projektu, ang. project object model) opisany w POM Reference. Konfiguracja wtyczek dla projektu odbywa się właśnie w pom.xml. Sekcją, która najczęściej służy do tego celu jest build, w której umieszczamy konfigurację wtyczek dla domyślnego uruchomienia M2 w projekcie (istnieje również możliwość zdefiniowania profili czy konfiguracji głównej wtyczek za pomocą pluginManagement, która będzie dziedziczona przez projekty pochodne, ale tych metod nie będziemy wykorzystywać).
Dodajmy do pom.xml konfigurację antrun i zadanie do wykonania echo (w międzyczasie możemy skorzystać z wtyczki eclipse i stworzyć pliki projektowe dla Eclipse IDE, w którym będziemy edytowali pom.xml, ale nie jest to konieczne).
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <configuration> <tasks> <echo>Witaj!</echo> </tasks> </configuration> </plugin> </plugins> </build> </project>
Zbadajmy wpływ konfiguracji wtyczki w pom.xml na jej wykonanie.
$ mvn antrun:run
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'antrun'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [antrun:run]
[INFO] ----------------------------------------------------------------------------
[INFO] [antrun:run]
[INFO] Executing tasks
[echo] Witaj!
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: < 1 second
[INFO] Finished at: Thu Apr 19 18:05:08 CEST 2007
[INFO] Final Memory: 2M/254M
[INFO] ------------------------------------------------------------------------
Poznaliśmy pierwszą część konfiguracji wtyczki. Nie jest ona związana z żadnym etapem M2 i zostanie wywołana jedynie, kiedy zażądamy tego explicite. Jak można było przeczytać w zacytowanej literaturze, M2 to motor wtyczek i niektóre są domyślnie związane z etapami. Etapy M2 odpowiadają etapom w życiu projektu informatycznego - kompilacja projektu (etap compile), wykonanie testów jednostkowych (etap test), instalacja w lokalnym repozytorium M2 (etap install), przygotowanie wersji dystrybucyjnej (etap package), itd. Wykonanie etapu to wykonanie zestawu wtyczek. Co jeśli chcielibyśmy zmienić listę wtyczek związanych z danym etapem? Zobaczmy.
$ mvn compile [INFO] Scanning for projects... [INFO] ---------------------------------------------------------------------------- [INFO] Building artykul [INFO] task-segment: [compile] [INFO] ---------------------------------------------------------------------------- [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Nothing to compile - all classes are up to date [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: < 1 second [INFO] Finished at: Thu Apr 19 18:19:52 CEST 2007 [INFO] Final Memory: 3M/254M [INFO] ------------------------------------------------------------------------
Domyślnie etap compile to wykonanie dwóch wtyczek resources oraz compiler - są one wypisane w nawiasach kwadratowych wraz z nazwą zadania po dwukropku. Etapów może być więcej niż wtyczek z nimi związanych tak, że pojedyńczy etap nie będzie domyślnie związany z żadną wtyczką. Może być również na odwrót - będzie więcej wtyczek niż etapów tak, że pojedyńczy etap będzie miał wiele wtyczek z nim związanych.
Zwiążmy wykonanie zadania run wtyczki antrun z etapem compile.
Powracamy do naszego pliku konfiguracyjnego pom.xml, w którym umieszczamy element executions jako definicję wykonania wtyczki i zadania z danym etapem.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <goals> <goal>run</goal> </goals> <phase>compile</phase> </execution> </executions> <configuration> <tasks> <echo>Witaj!</echo> </tasks> </configuration> </plugin> </plugins> </build> </project>
I pora na uruchomienie M2.
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
[echo] Witaj!
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 18:30:36 CEST 2007
[INFO] Final Memory: 3M/254M
[INFO] ------------------------------------------------------------------------
Zwróćmy uwagę na linię [antrun:run {execution: default}]. Ciąg znaków, jaki pojawia się po execution to nazwa jaką nadajemy definicji wykonania w sekcji execution w elemencie id.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>run-witaj</id> <goals> <goal>run</goal> </goals> <phase>compile</phase> </execution> </executions> <configuration> <tasks> <echo>Witaj!</echo> </tasks> </configuration> </plugin> </plugins> </build> </project>
Ponowne wykonanie powinno uwzględnić zmianę.
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Witaj!
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 18:33:30 CEST 2007
[INFO] Final Memory: 3M/254M
[INFO] ------------------------------------------------------------------------
Mamy możliwość wykonania wielu zadań wtyczki w jednym wykonaniu, co w przypadku wtyczki antrun nie może być niestety zademonstrowane ze względu na istnienie wyłącznie pojedyńczego zadania wtyczki - run. Skorzystajmy z innej wtyczki, która udostępnia więcej zadań, tj. exec-maven-plugin.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>run-witaj</id> <goals> <goal>run</goal> </goals> <phase>compile</phase> </execution> </executions> <configuration> <tasks> <echo>Witaj!</echo> </tasks> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <execution> <id>exec-m2-version</id> <goals> <goal>exec</goal> <goal>java</goal> </goals> <phase>compile</phase> </execution> </executions> <configuration> <executable>mvn</executable> <arguments> <argument>-v</argument> </arguments> <mainClass>org.codehaus.classworlds.Launcher</mainClass> </configuration> </plugin> </plugins> </build> </project>
Wykonanie ujawni działanie podwojenia zadań w sekcji goals.
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Witaj!
[INFO] Executed tasks
[INFO] [exec:exec {execution: exec-m2-version}]
[INFO] Maven version: 2.0.6
[INFO] Preparing exec:java
[WARNING] Removing: java from forked lifecycle, to prevent recursive invocation.
[INFO] No goals needed for project - skipping
[INFO] [exec:java {execution: exec-m2-version}]
Maven version: 2.0.6
Jednakże konfiguracja domyślna zadań w sekcji configuration jest dla wszystkich zadań jednakowa. W naszym przypadku wykonując zadanie exec wtyczki exec przekazywane parametry były takie same jak dla zadania java. Oczywiście nie jest to pożądana sytuacja, szczególnie jeśli dla jednego zadania chcielibyśmy przekazać inne, dedykowane parametry niż dla pozostałych zadań tej samej wtyczki. Rozwiązanie to "przesunięcie" sekcji configuration w zasięg elementu execution i odłączenie zadań exec i java z pojedyńczej sekcji execution, w zamian oferując osobne sekcje.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>run-witaj-bez-configuration</id> <goals> <goal>run</goal> </goals> <phase>compile</phase> </execution> <execution> <id>run-witaj</id> <goals> <goal>run</goal> </goals> <phase>compile</phase> <configuration> <tasks> <echo>Specyficzne Witaj!</echo> </tasks> </configuration> </execution> </executions> <configuration> <tasks> <echo>Domyslne Witaj!</echo> </tasks> </configuration> </plugin> </plugins> </build> </project>
Zauważmy znaczenie domyślnej sekcji configuration dla wszystkich uruchomień wtyczki, w ramach której została zdefiniowana. Jeśli uruchomimy mvn compile, wykonana zostanie wtyczka antrun z domyślną konfiguracją, gdyż nie podano elementu configuration w ramach execution, po której zostanie wykonana wtyczka antrun z konfiguracją specyficzną (przesłaniającą domyślną sekcję configuration).
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [antrun:run {execution: run-witaj-bez-configuration}]
[INFO] Executing tasks
[echo] Domyslne Witaj!
[INFO] Executed tasks
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Specyficzne Witaj!
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 20:09:02 CEST 2007
[INFO] Final Memory: 4M/254M
[INFO] ------------------------------------------------------------------------
Może pojawić się pytanie o kolejność wykonywania wtyczek i poszczególnych wykonań. Kolejność wyznaczana jest analogicznie do kolejności wystąpień definicji w ramach pliku pom.xml. Zmieńmy kolejność sekcji execution dla antrun.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>run-witaj</id> <goals> <goal>run</goal> </goals> <phase>compile</phase> <configuration> <tasks> <echo>Specyficzne Witaj!</echo> </tasks> </configuration> </execution> <execution> <id>run-witaj-bez-configuration</id> <goals> <goal>run</goal> </goals> <phase>compile</phase> </execution> </executions> <configuration> <tasks> <echo>Domyslne Witaj!</echo> </tasks> </configuration> </plugin> </plugins> </build> </project>
i otrzymamy inną kolejność wykonywania
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Specyficzne Witaj!
[INFO] Executed tasks
[INFO] [antrun:run {execution: run-witaj-bez-configuration}]
[INFO] Executing tasks
[echo] Domyslne Witaj!
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 20:13:16 CEST 2007
[INFO] Final Memory: 4M/254M
[INFO] ------------------------------------------------------------------------
Możnaby zapytać o możliwość poprzedzenia wykonania wtyczek przed wtyczkami związanymi z poszczególnymi etapami, np. compiler. Każdy z etapów, ma swojego poprzednika (z oczywistych względów nie ma tego etap początkowy - validate). Przed wykonaniem etapu compile wykonywane są wtyczki związane z etapem validate, generate-sources, process-sources, generate-resources oraz process-resources w kolejności od najwcześniej wykonywanego do poprzedzającego compile. Związanie wtyczki z etapem poprzednim daje zamierzony efekt.
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Specyficzne Witaj!
[INFO] Executed tasks
[INFO] [antrun:run {execution: run-witaj-bez-configuration}]
[INFO] Executing tasks
[echo] Domyslne Witaj!
[INFO] Executed tasks
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 22:15:36 CEST 2007
[INFO] Final Memory: 3M/254M
[INFO] ------------------------------------------------------------------------
Oczywiście możliwe jest wykonanie antrun w różnych etapach z różnymi konfiguracjami.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>run-witaj</id> <phase>process-resources</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>Specyficzne Witaj!</echo> </tasks> </configuration> </execution> <execution> <id>run-witaj-bez-configuration</id> <phase>validate</phase> <goals> <goal>run</goal> </goals> </execution> </executions> <configuration> <tasks> <echo>Domyslne Witaj!</echo> </tasks> </configuration> </plugin> </plugins> </build> </project>
co przedstawia się następująco:
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [antrun:run {execution: run-witaj-bez-configuration}]
[INFO] Executing tasks
[echo] Domyslne Witaj!
[INFO] Executed tasks
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Specyficzne Witaj!
[INFO] Executed tasks
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 22:16:55 CEST 2007
[INFO] Final Memory: 3M/254M
[INFO] ------------------------------------------------------------------------
W M2 występuje kilka fundamentalnych pojęć. Poza wtyczką, korzystaliśmy również z pojęcia etapu. Etapy składają się na sekwencje, gdzie default jest nazwą domyślnej sekwencji. Omówienie podstawowych pojęć M2 znajduje się w Notatniku jako wpis zatytułowany Podstawowe pojęcia Maven2: sekwencje, etapy, wtyczki i zadania. W artykule znajdziemy informacje o wtyczkach związanych z poszczególnymi etapami. Pytanie jakie może się nasunąć, to możliwość konfiguracji wtyczki, która już została związana z etapem, np. compiler z etapem compile. Jednymi z parametrów wtyczki compiler, które są stosunkowo często wykorzystywane są source oraz target. Domyślnie jest to wersja 1.3 podczas, gdy większość z dzisiejszych projektów korzysta z Java SE 5. Podniesienie wersji kompilatora, a tym samym konfiguracja wtyczki compiler to skorzystanie z sekcji configuration bez konieczności związania konfiguracji z sekcją execution. Wykonanie zostało już zdefiniowane przez M2, więc wpływamy jedynie na konfigurację wtyczki, a nie samego wykonania.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>pl.jaceklaskowski.m2</groupId> <artifactId>artykul</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>artykul</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>run-witaj</id> <phase>process-resources</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>Specyficzne Witaj!</echo> </tasks> </configuration> </execution> <execution> <id>run-witaj-bez-configuration</id> <phase>validate</phase> <goals> <goal>run</goal> </goals> </execution> </executions> <configuration> <tasks> <echo>Domyslne Witaj!</echo> </tasks> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration>
Niepoprawny język.
Musisz wybrać język w następujący sposób: <source lang="html4strict">...</source>
Języki obsługiwane w podświetlaniu składni:
abap, actionscript, actionscript3, ada, apache, applescript, apt_sources, asm, asp, autoit, avisynth, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_mac, caddcl, cadlisp, cfdg, cfm, cil, cmake, cobol, cpp, cpp-qt, csharp, css, d, dcs, delphi, diff, div, dos, dot, eiffel, email, erlang, fo, fortran, freebasic, genero, gettext, glsl, gml, gnuplot, groovy, haskell, hq9plus, html4strict, idl, ini, inno, intercal, io, java, java5, javascript, kixtart, klonec, klonecpp, latex, lisp, locobasic, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, make, matlab, mirc, modula3, mpasm, mxml, mysql, nsis, oberon2, objc, ocaml, ocaml-brief, oobas, oracle11, oracle8, pascal, per, perl, php, php-brief, pic16, pixelbender, plsql, povray, powershell, progress, prolog, properties, providex, python, qbasic, rails, rebol, reg, robots, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, tcl, teraterm, text, thinbasic, tsql, typoscript, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xml, xorg_conf, xpp, z80
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Samo wykonanie M2 nie ujawni konfiguracji wtyczki
$ mvn compile
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building artykul
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] [antrun:run {execution: run-witaj-bez-configuration}]
[INFO] Executing tasks
[echo] Domyslne Witaj!
[INFO] Executed tasks
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [antrun:run {execution: run-witaj}]
[INFO] Executing tasks
[echo] Specyficzne Witaj!
[INFO] Executed tasks
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to c:\projs\sandbox\artykul\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Thu Apr 19 22:29:20 CEST 2007
[INFO] Final Memory: 3M/254M
[INFO] ------------------------------------------------------------------------
, ale prześledzenie uruchomienia M2 korzystając z opcji -X już tak i ujawnia przekazane parametry dla wtyczki compiler (UWAGA: ilość informacji w trybie śledzenia może spowodować ból głowy nawet dla wykonania prostego projektu jak nasz).
$ mvn -X compile ... [DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-compiler-plugin:2.0.2:compile' --> [DEBUG] (f) basedir = c:\projs\sandbox\artykul [DEBUG] (f) buildDirectory = c:\projs\sandbox\artykul\target [DEBUG] (f) classpathElements = [c:\projs\sandbox\artykul\target\classes] [DEBUG] (f) compileSourceRoots = [c:\projs\sandbox\artykul\src\main\java] [DEBUG] (f) compilerId = javac [DEBUG] (f) debug = true [DEBUG] (f) failOnError = true [DEBUG] (f) fork = false [DEBUG] (f) optimize = false [DEBUG] (f) outputDirectory = c:\projs\sandbox\artykul\target\classes [DEBUG] (f) outputFileName = artykul-1.0-SNAPSHOT [DEBUG] (f) projectArtifact = pl.jaceklaskowski.m2:artykul:jar:1.0-SNAPSHOT [DEBUG] (f) showDeprecation = false [DEBUG] (f) showWarnings = false [DEBUG] (f) source = 1.5 [DEBUG] (f) staleMillis = 0 [DEBUG] (f) target = 1.5 [DEBUG] (f) verbose = false [DEBUG] -- end configuration -- [INFO] [compiler:compile] [DEBUG] Using compiler 'javac'. [DEBUG] Source directories: [c:\projs\sandbox\artykul\src\main\java] [DEBUG] Classpath: [c:\projs\sandbox\artykul\target\classes] [DEBUG] Output directory: c:\projs\sandbox\artykul\target\classes
Uruchomienie M2 z opcją -X jest rekomendowane wyłącznie w sytuacjach awaryjnych.
Na koniec chciałbym wspomnieć o możliwości związania wtyczki z określonym etapem przez samego autora wtyczki. Temat tworzenia wtyczki pozostawiam na osobny artykuł, jednakże teraz warto pamiętać, że mimo braku domyślnego związania wtyczki z sekwencją w M2, autor wtyczki może zdecydować, że konfiguracja wtyczki (tym samym jej uaktywnienie w projekcie) będzie implikowało wykonanie jest w pewnym etapie, który stanie się etapem domyślnym dla niej.
Inną istotną kwestią związaną z wtyczkami jest związanie wtyczek z typami projektów (znacznik packaging w pom.xml). Domyślnym typem jest jar, ale bardzo popularnym jest również pom, który służy do zgrupowania konfiguracji wspólnej dla wielu projektów. Warto pamiętać, że typ projektu może wpływać na zestaw uruchamianych wtyczek.
Miłej pracy z M2!
