W opisie narzędzi i przygotowaniu projektu wspominałem o tym, żeby utworzyć projekt Maven. W tej lekcji wyjaśnimy czym dokładnie jest maven, do czego jeszcze możemy go wykorzystać.
Maven to w uproszczeniu narzędzie do zarządzania projektem, jego zaleznościami (czyli np. bibliotekami które będziemy używać) i strukturą (np. podział na moduły). Ale to tylko mały wycinek tego, co daje nam to narzędzie. Zachęcam do zapoznania się z odnośnikami znajdującymi się na dole tej lekcji, które rzucą więcej światła na możliwości jakie oferuje Maven. Oczywiście istnieją alternatywne rozwiązania, takie jak np. starszy Ant czy nowszy Gradle. Niemniej Maven dość szybko został zaadoptowany przez firmy i nic nie wskazuje na to, żeby miało się to wkrótce zmienić, dlatego z punktu widzenia celu tego bloga Mavena należy znać. Po prostu :)
Lekcja
UWAGA! Jeśli instalowałaś inne środowisko niż STS, możesz nie mieć zainstalowanego Mavena. Sprawdź w odnośnikach jak to zrobić i upewnij się, że przed kontynuowaniem Maven jest zainstalowany na Twoim komputerze.Maven jest bardzo rozbudowanym narzędziem, jednocześnie bardzo prostym w podstawowym użyciu i użytecznym nawet w małych projektach. Cała potęga kryje się w jego budowie — wszystkie elementy, kroki i procesu są dynamiczne i konfigurowalne, dzięki czemu możemy sami wpływać na ich działanie, włączać/wyłaczać poszczególne elementy wg potrzeby i dopasowywać do swoich potrzeb. Jednoczesnie cała konfiguracja jest w jednym miejscu wewnątrz projektu, co bardzo pomaga jeśli prace przy projekcie odbywają się na kilku róznych komputerach (np. w zespole, lub pracujemy w domu i w biurze).Miej na uwadze, że przedstawione poniżej informacje to tylko wycinek, który będzie nam potrzebny do dalszej pracy. Gorąco zachęcam do zapoznania się z innymi mozliwościami tego narzędzia.
Słowniczek
Zaczniemy od wyjaśnienia kilku pojęć. Będą one używane w tej i kolejnych lekcjach i kluczowe jest, żeby je zrozumiała. W razie wątpliwości można też poszukać w internecie ich znaczenia — wiele poradników i tutoriali także opisuje znaczenie poszczególnych słów i określeń.
- artefakt — samoistna jednostka w projekcie, artefaktem jest np. każdy z modułów czy każda z zależności projektu. Można powiedzieć, że artefakt to takie zbiorcze określenie które obejmuje zarówno projekty, moduły, biblioteki, pluginy (czyli elementy całego procesu), archetypy (coś w rodzaju \‘szablonu\’ projektu, który możesz szybko skonfigurować i uruchomić) itd.
- pom.xml — główny plik z ustawieniami Maven w projekcie
- repozytorium — zbiór artefaktów. Każda instalacja Maven powoduje utworzenie lokalnego repozytorium, jest także repozytorium centralne oraz można korzystać z dowolnych innych repozytoriów (np. jakiegoś projektu)
Struktura projektu
Korzystając z Mavena projekt ma standardową strukturę (na dysku), w której możemy wyróżnić kilka elementów (w głównym katalogu projektu):
- pom.xml — główny plik konfiguracji Maven, omówimy go bardziej szczegółowo poniżej
- /src/main — katalog, gdzie znajdziemy pliki naszego programu, są tam dwa podkatalogi:
- java — tutaj trafiają wszystkie klasy (cały kod naszego modułu)
- resources — tutaj będą wszystkie pliki, które nie są kodem, np. grafiki, pliki XML, konfiguracje itp (nauczymy się z nich korzystać w kolejnych etapach kursu)
- w przypadku projektów webowych będziemy mieli także katalog webapp, który jest używany do umieszczania wszystkich treści webowych
- /src/test — ma podobną strukturę jak katalog /main z tą różnicą, że jest on wykorzystywany tylko w trakcie automatycznych testów. O automatycznych testach powiemy sobie więcej w 8 lekcji
- /target — tutaj trafia skompilowany projekt (czyli np. w postaci wykonywalnego pliku JAR lub aplikacji webowej WAR)
Poza powyższymi w naszym module oczywiście mogą się znaleźć dodatkowe pliki i katalogi, nie są one jednak ściśle związane z samym Mavenem (najczęściej).
Projekty i moduły w Mavenie
Tworząc nowy projekt w mavenie możemy wybrać jego ‘packaging’, czyli sposób, w jaki wszystkie elementy zostaną ostatecznie połaczone razem. Istnieje kilka podstawowych (oczywiście moduły i pluginy mogą rozszerzać tą listę):
- pom
- jar (domyślny)
- war (aplikacje webowe, o tym porozmawiamy w przyszłości)
Packaging JAR powoduje, że w momencie uruchomienia budowania maven wszystkie nasze klasy zostaną połączone w jeden plik JAR (który można następnie uruchamiać samodzielnie).
O plikach WAR powiemy sobie w kolejnych lekcjach, ale zatrzymajmy się na moment przy wartości POM.
Packaging POM oznacza mniej więcej tyle, że jest to projekt, który może posiadać kilka modułów (to nie jest wymagane, ale na ten moment załóżmy że to najczęstszy przypadek, w którym używamy tego ustawienia). Dla przykładu, w dowolnej dużej aplikacji najczęściej znajdziemy wiele pod-projektów (modułów, komponentów), z których każdy jest podzielony na kilka elementów (np. osobno jest kod związany z bazą danych, z logiką biznesową oraz z wyświetlaniem — warstwą prezentacji). Z punktu widzenia maven jeden taki komponent (pod-projekt) to projekt (lub moduł) który ma packaging = POM, z kolei każdy z elementów (logika biznesowa, obsługa bazy danych itp) to osobne moduły, które mają packaging JAR lub WAR i w sekcji parent ustawiony ten projekt, który ma packaging ‘POM’.
W eclipse możemy ustawić taki projekt na dwa sposoby — albo tworząc nowy moduł i podając odpowiednie dane w sekcji ‘parent’, albo otwierając plik pom.xml nadrzędnego modułu i w sekcji ‘modules’ wybierając opcję ‘create’ (opcja ‘add’ pozwala nam wybrać już istniejący moduł, którym chcemy zarządzać w ten sposób) i uzupełniając dane jak przy normalnym tworzeniu modułu Mavenowego.
Taka konfiguracja jest bardzo wygodna, ponieważ wszystkie ustawienia ‘nadrzędnego’ POMa są też dostępne w POMie podrzędnym, możemy więc z jednego miejsca zarządzać wersjami bibliotek, których używamy, używać ustawień i konfigurować pluginy. Więcej o innych zastosowaniach będziemy mówili w kolejnych lekcjach, póki co będzie to dla nas przydatne także po to, aby uporządkować nasz kod i podzielić go na moduły.
pom.xml
Plik pom.xml jest tym, co łączy projekt w Javie oraz Maven’a ;) To w nim jest cała konfiguracja związana z projektem, opis jak ma być budowany, konfiguracja pluginów itp. Nie będziemy tutaj opisywać całej struktury pliku pom, ponieważ wyznacza to znacznie poza ramy tego kursu, a jedynie nakreślimy najważniejsze elementy.To, co musi zawierać plik pom.xml, to koordynaty artefaktu, czyli groupId oraz artifactId. Jeśli projekt nie ma rodzica (tag <parent>), musimy określić także numer wersji. Identyfikator grupy to najczęściej nazwa projektu, podczas gdy identyfikator artefaktu to unikalna nazwa np. modułu — idea jest taka, że poszczególne moduły tego samego projektu mają wspólny groupId, ale unikalny artifactId. Para wartości groupId i artifactId powinna być unikalna.
Plik ten pozwala nam także określić, z jakich bibliotek i innych modułów korzysta nasz moduł. Służy do tego tag <dependencies>, który może wystąpić tylko raz — wewnątrz tego tagu możemy dodać wiele tagów <dependency>. Tag dependency może wskazywać na dowolny artefakt z repozytorium centralnego, lokalnego lub dowolnego innego skonfigurowanego w ustawieniach Maven. Musi on zawierać trzy informacje — groupId, artifactId (razem to tzw. coordinates — czyli precyzyjne określenie, o który artefakt nam chodzi) oraz version — wersję (to nie do końca prawda, w większych projektach stosuje się tzw. dependencyManagement, czyli centralne zarządzanie numerami wersji pozwalające pominąć numer wersji w tagu dependency; zainteresowanych odsyłam do dokumentacji Mavena, nie ma w tym żadnej magii i w prostych projektach jest to mało przydatne). Przykładowy plik pom.xml wygląda następujaco:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>
Jest to tzw. minimalny plik pom.xml — posiada tylko wymagane informacje.
<project>
...
<properties>
<mavenVersion>2.1</mavenVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>${mavenVersion}</version>
</dependency>
</dependencies>
...
</project>
Więcej przykładów znajdziesz na stronie Mavena, pod adresem http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
Cykl życia (domyślny)
Cała idea działania Mavena jest zbudowana wokół tzw. cyklu życia (maven build lifecycle). Każdy z kroków to kolejny element na drodze od kodów źródłowych do projektu uruchomionego na serwerze (tak, Maven może także to zrobić). Poniższy diagram przedstawia (uproszczony) domyślny cykl życia projektu.
Krótkie omówienie poszczególnych faz:
- validate — walidacja, na tym etapie sprawdzane jest, czy kod źródłowy jest poprawny, czy wszystkie pliki zawierają prawidłowe elementy (o ile Maven ma informacje, jak to sprawdzić) itp., ogólnie jest to sprawdzenie, czy projekt można skompilować
- compile — kompilacja projektu, czyli zamiana kodów źródłowych na kod zrozumiały dla maszyny wirtualnej
- test — automatyczne wykonanie testów, o których to będzie kolejna lekcja
- package — łączenie elementów stworzonych w poprzednich etapach w tzw. deliverable, czyli np. plik JAR który można uruchomić lub plik WAR który można uruchomić na serwerze
- integration-test — to kolejna seria automatycznych testów, tym razem integracyjnych. Testy integracyjne to w skrócie testy sprawdzające czy nasz komponent współpracuje z innymi w ramach większego systemu. Testy tego rodzaju nie będą omawiane w tym kursie (ale może w przyszłości pojawi się o nich parę słów na blogu w ramach luźnej notatki :) )
- verify — weryfikacja, czy stworzona paczka spełnia kryteria jakościowe (o kryteriach, metrykach itp. powiemy sobie w przyszłości)
- install — instalacja paczki wygenerowanej w kroku package. Przy czym uwaga, instalacja oznacza tyle, że artefakt (czyli wynik działania package) zostanie umieszczony w repozytorium Mavena (domyślnie lokalnym, ale możemy też umieścić je w repozytorium zdalnym) i będzie dostępny dla innych modułów (np. jako zależność)
- deploy — umieszczenie artefaktu np. na serwerze za pomocą FTP czy jakiegoś API serwera aplikacji
Maven’a uruchamiamy przechodząc do katalogu z plikiem pom.xml i wpisujac mvn <step> . Możliwości jest oczywiście więcej, możemy wykonać konkretny cel (‘podkrok’ w ramach danego kroku) ale ponieważ w tym kursie Maven posłuży nam tylko jako narzędzie dodatkowe, nie będziemy omawiać szczegółów. Zainteresowanych odsyłam do dokumentacji lub książek na temat samego Mavena :)
To, co trzeba wiedzieć, to to, że wywołaniem konkretnego kroku (np. poprzez mvn install) wykonujemy wszystkie kroki po kolei, aż do tego, który określiliśmy (w tym przypadku wszystkie kroki poza ostatnim — deploy). Najczęstszym sposobem użycia (i ten proszę sobie napisać na karteczce i nakleić na monitor) to polecenie mvn clean install — cel clean nie należy do głównego cyklu życia (ale możemy go wykonać tak jak dowolny inny krok, po prostu wstawiając go po spacji do polecenia). To polecenie najpierw usunie wszystkie stare pliki (to ważne, ponieważ czasem nieusunięcie plików może prowadzić do błędów, które trudno zlokalizować) a następnie skompiluje projekt, zapaczkuje go (stworzy artefakt) i umieści go w repozytorium (domyślnie lokalnym). Artefakt znajdziemy też oczywiście w katalogu /target jako plik .jar / .war .
Zadanie
Jeśli projekt, nad którym pracujesz, nie jest jeszcze projektem typu maven (można to poznać np. po tym, że nie ma w jego głównym katalogu pliku pom.xml), skonwertuj go na projekt Maven (klikając prawym przyciskiem myszki na projekt w Eclipse, a następnie wybierając odpowiednią opcję konwersji).Zmodyfikuj plik pom.xml tak, aby zawierał poniższe zmiany:
- Uzupełnij nazwę projektu i jego opis oraz adres URL (jeśli nie posiadasz własnej strony, jako adres URL podaj stronę tego projektu)
- Skonfiguruj projekt tak, aby plik JAR można było uruchomić bezpośrednio, klikając na niego dwukrotnie myszką (tzw. self-executable JAR). Zrób to wyłącznie poprzez modyfikacje w pliku pom.xml
- Dodaj zależność do artefaktu org.springframework:spring-core w najnowszej wersji (wyszukaj wersję w repozytorium centralnym)
Następnie dodaj moduły:
- koty-domain i przenieś do niego klasę Kot
- koty-application i umieść w nim resztę klas. Do tego modułu przenieś zależność do spring-core
Pamiętaj, że część zmian z pierwszej części zadania będziesz musiał przenieść do modułu (chodzi głównie o konfigurację executable JAR — do modułu koty-application)
Upewnij się, że nadal można skompilować projekt (dodaj zależności jeśli jest taka potrzeba).
Podpowiedzi
Pobierz rozwiązanie tego zadaniaJeśli uważasz powyższą lekcję za przydatną, mamy małą prośbę: polub nasz fanpage. Dzięki temu będziesz zawsze na bieżąco z nowymi treściami na blogu ( i oczywiście, z nowymi częściami kursu Javy). Dzięki!