Archiwa tagu: daj się poznać

Własny formularz logowania Spring Security

W poprzednim wpisie pokazałam, jak zabezpieczyć stronę lub widok hasłem. Korzystałam tam z domyślnego formularza logowania, który wyglądał tak:

Standardowy formularz logowania
Standardowy formularz logowania

Zawsze fajnie dostać coś za darmo, ale nie pasuje to wyglądem do reszty strony.

Co zrobiłam, żeby wymienić formularz na ładniejszy?

  1. Dopisałam odpowiednie fragmenty w metodzie configure wprowadzonej w poprzednim wpisie klasy SecurityConfiguration:
  2. Zdefiniowałam formularz w pliku login.html:
  3. Dodałam najprostszy możliwy kontroler:

Efekt wygląda tak:

Ulepszony formularz logowania
Ulepszony formularz logowania

Spring Boot: Bezpieczeństwo 101

Pora zabezpieczyć stronę – niektóre jej części chcę pokazywać tylko zalogowanym użytkownikom.

Ukrycie całej strony za hasłem

Ukrycie całej strony za hasłem jest wyjątkowo proste. Wystarczy dodać do pom.xml następującą zależność:

Strona wygląda wtedy tak:

Cała strona ukryta za hasłem
Cała strona ukryta za hasłem

Skąd wiem, jakiego podać użytkownika i hasło?

  • Jeśli nic dodatkowo nie konfigurowałam, mogę zalogować się przy użyciu nazwy użytkownika User oraz hasła zapisanego w logach serwera:
  • Mogę też podać dane logowania w pliku application.properties:

Zabezpieczenie na poziomie stron i metod

Dodaję do swojego kodu następującą klasę konfiguracyjną:

W metodzie configureAuth uzyskuję dostęp do obiektu AuthenticationManagerBuilder i definiuję parę użytkowników i nadajemy im role (użytkownika lub administratora).

W metodzie configure podaję, kto ma mieć dostęp do której części aplikacji. I tak:

  • Do adresów wymienionych w linii 17 dostęp mają wszyscy, a więc nie tylko zalogowani użytkownicy.
  • (18) Do stron pod adresem /admin i poniżej dostęp ma tylko użytkownik o prawach administratora.
  • (19) Do stron pod adresem /user i poniżej dostęp ma tylko użytkownik w roli USER.
  • (20) Do reszty stron dostęp mają tylko zalogowani użytkownicy, niezależnie od roli.
  • Włączam dodatkowo standardowy formularz logowania (21) i ustawiam adres / jako domyślne miejsce lądowania po udanym zalogowaniu bądź wylogowaniu.

Dodam jeszcze następujący fragment kodu do mojego szablonu strony:

Uwaga! Żeby silnik szablonów Thymeleaf odpowiednio przetworzył ten fragment, w pom.xml muszę dodać zależność do artefaktu thymeleaf-extras-springsecurity4.

Jak to wygląda na stronie?

Strona główna, niewymagająca logowania
Strona główna, niewymagająca logowania
Standardowy formularz logowania
Standardowy formularz logowania
Użytkownik zalogowany
Użytkownik zalogowany

Dodatkowo mogę definiować wymagania bezpieczeństwa w kodzie, przy każdej metodzie kontrolera, np.:

Kod jest dostępny w GitHubie.

Co dalej?

Pozbywam się powtarzalnych fragmentów HTML przy użyciu Thymeleaf

Każdy programista wie, że duplikacja w kodzie źródłowym to zło, gdyż:

  • jeśli zduplikowany kod zawiera błąd, trzeba naprawić go w kilku miejscach (i z reguły o którymś się zapomina),
  • długi kod trudniej się czyta.

A jednak zadanie przerzucenia powtarzanych fragmentów HTML (jak nagłówek i stopka wyświetlane na wszystkich podstronach) do osobnych, reużywalnych plików wcale nie jest trywialne!

Mój plik index.html w oryginalnej postaci zawierał 71 linii, z czego około 50 było wspólnych z innymi szablonami (nagłówek, stopka, menu, załączane skrypty js). Zależało mi na wyodrębnieniu części wspólnych do własnych plików. Chociażby po to, żeby dodanie pozycji z menu nie musiało być odwzorowywane w pięciu miejscach.

Jakie miałam możliwości?

  1. Oprogramować operację include w JavaScripcie (lub użyć czyjegoś kodu, np. z W3Schools). Wady:
    • dużo JavaScriptu,
    • metoda z gatunku nieeleganckich hacków.
  2. Użyć znaczników HTML: object, embed lub nawet iframe. Wady:
    • dwa pierwsze znaczniki zostały zaprojektowane do osadzania na stronach obiektach takich jak filmy, choć da się ich użyć tak że do wstawienia dokumentu HTML,
    • wszystkie służą do dodania do strony kompletnego dokumentu, a nie fragmentu,
    • styl CSS obowiązujący na stronie nie zadziała na załączone w ten sposób fragmenty.
  3. Skorzystać z mechanizmu udostępnianego przez silnik szablonów, w tym wypadku Thymeleaf. Wady:
    • serwer wykonuje pracę, którą mógłby wykonać klient 🙂
    • ewentualna zmiana silnika szablonów staje się jeszcze bardziej kosztowna.

Zdecydowałam się na rozwiązanie numer 3. Jak to wygląda w praktyce?

Na wszystkich moich stronach powtarzał się poniższy fragment:

Przeniosłam go (wraz z innymi podobnymi elementami) do osobnego pliku _menus.html:

Dzięki temu mogę załączać go wszędzie tam, gdzie jest potrzebny, w następujący sposób:

Pułapka 1: Na początku umieściłam atrybuty id i class we fragmencie załączanym (w _menus.html). Zostały zjedzone 🙂

A co, jeśli fragment, który chcę załączyć, nie jest otoczony sensowną parą znaczników? Mogę wtedy użyć bloku, np.:

I załączyć go w analogiczny sposób:

W obecnej chwili index.html ma tylko 32 niepuste linie i dużo zyskał na czytelności, podobnie jak inne szablony.

Pułapka 2: Po wyodrębnieniu stopki do osobnego pliku, moim oczom ukazał się taki oto widok:

Problem z kodowaniem załączonego pliku
Problem z kodowaniem załączonego pliku

Wszystkie pliki mam zakodowane w UTF-8, takie samo kodowanie deklaruję w nagłówku HTML. Poczytałam trochę o problemach z kodowaniem na linii Spring/Thymeleaf, ale ostatecznie, ponieważ na teraz jest to jedyne wystąpienie polskiego znaku na mojej stronie, po prostu zmieniłam odpowiadającą za to linię na:

 

 

 

 

Czasami coś idzie nie tak… Moja własna strona błędu

Nadal w ramach Daj się poznać.

Podobny obrazek widział chyba każdy programista aplikacji webowej. Od czasu do czasu serwer Tomcat postanawia poinformować użytkownika aplikacji, że coś poszło nie tak. Informuje dość brutalnie, przynajmniej od strony stylistycznej. Co gorsza, przy okazji potrafi wyjawić przypadkowemu użytkownikowi dość dużo informacji na temat wnętrza programu.

Informacja o błędzie wygenerowana przez serwer Tomcat. W tym wypadku żądana strona nie istnieje.
Informacja o błędzie wygenerowana przez serwer Tomcat. W tym wypadku żądana strona nie istnieje. Czasami można w tym miejscu zobaczyć ciekawszy materiał, czyli stack trace.

Tego typu informacje przydają się do debugowania aplikacji na etapie jej powstawania, ale użytkownik końcowy nie powinien ich oglądać (chociażby z powodów estetycznych).

Jak sobie z tym poradzić? Framework Spring Boot automatycznie ustawia dla nas nieco tylko ładniejszą stronę błędu:

Whitelabel Error Page, czyli strona błędu generowana przez Spring Boot
Whitelabel Error Page, czyli strona błędu generowana przez Spring Boot

Mechanizm ten można wyłączyć we właściwościach aplikacji (application.properties):

Także zmiana domyślnego ViewResolver może usunąć tę wersję informacji o błędzie i przywrócić wersję tomcatową.

Jeśli zamiast strony prezentowanej przez Springa chcesz ustawić swoją własną, musisz zerknąć do dokumentacji wybranego przez Ciebie silnika szablonów. W przypadku Thymeleaf wystarczy dodać szablon o nazwie error.html:

Szablon błędu dla silnika Thymeleaf
Szablon błędu dla silnika Thymeleaf

Dzięki temu strona błędu może wyglądać na przykład tak:

error

Czy jest ładniejsza… Pozostawiam ocenie Czytelnika 😀

Historie komórkowe

Ten tekst miał nazywać się “Mobilna wersja strony: podejście 2” w nawiązaniu do Mobilna wersja strony w Spring Boot. Potrzebowałam do niego zrzutu ekranu z mojego telefonu, a jedno spojrzenie na niego wyzwoliło całą lawinę wspomnień… Które również zamieszczam poniżej.

@media

Najpierw krótko o konkretach: w poprzednim wpisie pokazywałam, jak Spring Boot pozwala stworzyć mobilną wersję strony i zarządza jej wyświetlaniem. Wychodzi jednak na to, że w dzisiejszych czasach istnieją lepsze metody. Prym wśród nich wiodą CSS3 i reguły @media. Logika odpowiedzialna za formatowanie informacji trafia w tym modelu dokładnie tam, gdzie powinna: do arkusza stylów. W arkuszu stylów, przy użyciu reguł @media, możemy podjąć decyzję na temat sposobu wyświetlania informacji w zależności od tego, jakie urządzenie korzysta ze strony (np. ekran czy drukarka?), jaką ma orientację (pozioma czy pionowa?) bądź rozdzielczość.

Prosty przykład ze strony W3Schools:

Kolor tła zostanie zmieniony na magentę (ekhem, fuksję), jeśli szerokość wyświetlacza wyniesie co najmniej 480 pikseli.

W swojej konkursowej aplikacji postanowiłam pójść po najmniejszej linii oporu – znalazłam darmowy szablon CSS implementujący ten mechanizm 🙂 Wygląda to obecnie tak:

Przeglądarka na PC
Przeglądarka na PC
Strona wyświetlona na ekranie Samsung Galaxy Xcover 3
Strona wyświetlona na ekranie  urządzenia mobilnego o niskiej rozdzielczości

Telefony 🙂

Co do kiepskiej jakości urządzeń mobilnych… Jestem specyficznym typem użytkownika: masowo rozbijam telefony. Nie rzucam nimi ze złości (od dobrych paru lat). Same wypadają: z kieszeni, z torebki, z samochodu. Kąpią się w wannie i w napojach. Psują się.

Przedstawiony powyżej zrzut ekranu pochodzi z mojego Samsung Galaxy Xcover 3. A było tak.

W połowie ubiegłego roku doszłam do wniosku, że nie stać mnie na kupowanie co dwa miesiące nowego dobrej klasy smartfona (w obliczu śmiertelnego wypadku poprzednika). Zdecydowałam się wtedy na zakup urządzenia niskiej klasy, za to w metalowej obudowie. Przesadziłam – nie działało na nim nawet quizzwanie. Na szczęście, problem szybko rozwiązał się sam. Pierwszego dnia telefon wypadł mi z ręki, kiedy przechodziłam przez przedpokój na piętrze. Pięknym lobem poszybował w stronę krętych schodów, po czym szybem w rogu spadł aż do samej piwnicy. Kiedy bez większych nadziei zeszłam na dół, okazało się, że urządzenie nadal działa, chociaż róg ma zauważalnie wgnieciony. Nabrałam do niego nowego szacunku. Dwa dni później wypadł mi z tylnej kieszenie spodni, kiedy szukałam kluczy na podjeździe – i zbił się na amen.

Wtedy wpadłam na radykalnie odmienny pomysł: kupić drogie i dobre urządzenie, o które będę drżeć i którego wobec finansowych rozterek z pewnością nie upuszczę na podłogę. Wybrałam najnowszy model Galaxy Note. Telefon był piękny, wygodny, szybki… Tyle że trafiłam na wadliwy egzemplarz, który restartował się w losowo wybranych momentach kilka razy dziennie. Przegapiłam (tygodniowy) termin na oddanie telefonu bez wyjaśnień w lokalnym Brand Store, ponieważ od razu pojechałam z nim na wakacje. Po powrocie najpierw wmawiano mi, że wyłączyłam telefon podczas aktualizacji i dlatego działa źle. Potem kilka razy zwracano mi go jako naprawiony – pierwszą rzeczą, jaką robił po włączeniu (najpierw w domu, potem już w sklepie), był restart. Pikanterii sprawie dodawał fakt, że byłam wtedy w bardzo zaawansowanej ciąży i brak sprawnego telefonu był coraz bardziej ryzykowny. Po około miesiącu użyłam na piśmie magicznego sformułowania “Miejski Rzecznik Konsumentów” i odzyskałam pieniądze. Nie chciałam już innego egzemplarza (o który dopominałam się od początku, ustaliwszy szybko, że problem jest sprzętowy i dotyczy konkretnej sztuki w ogólności dobrego modelu), bo nie miałam ochoty na jeszcze jedno spotkanie z serwisem.

Lato 2015, Mazury. Dawid i Gałgan ćwiczą pracę wodną. Ja łapię zasięg i reinstaluję Androida
Lato 2015, Mazury. Dawid i Gałgan ćwiczą pracę wodną. Ja łapię zasięg i reinstaluję Androida

Potem chciałam tanio i dobrze kupić One Plus. Powstrzymało mnie to, że właśnie pojawił się nowy model. Kosztował dokładnie tyle, co stary, ale do zakupu wymagane było posiadanie zaproszenia. Kto normalny kupiłby starą wersję, jeśli nowa kosztowała tyle samo?! A zaproszenie ciągle nie nadchodziło…

Wtedy wygasła umowa na usługi komórkowe w organizacji, do której należę i pojawiła się możliwość uzyskania bez dopłaty cuda w postaci Samsung Galaxy Xcover 3. Na kolana powala przede wszystkim rozdzielczość (480 x 800px), ale pancerny telefon nadal działa po dziesiątkach upadków, kąpieli i ugryzień. I takiego doświadczenia życzę wszystkim!

Wdrażam moją aplikację (która nadal nic nie robi) w chmurze Pivotal Web Services

Co to za aplikacja?

W ramach konkursu Daj się poznać pracuję nad aplikacją Szafbook, na którą pomysł został naszkicowany tutaj. Moim celem jest przede wszystkim nauczenie się nowych rzeczy, dlatego sama aplikacja solidnie kuleje i, jak w tytule, naprawdę nic jeszcze nie robi. Ale już da się wdrożyć!

Co to jest Pivotal Web Services?

Pivotal to firma z, oczywiście, San Francisco. Jeden z jej produktów to chmura i oprogramowanie Pivotal Cloud Foundry . Pivotal Web Services to ich instancja dostępna publicznie. Umożliwia łatwe wdrażanie aplikacji napisanych w następujących językach i frameworkach: Java, Grails, Play, Spring, Node.js, Ruby on Rails, Sinatra, Go.

Zachęcająca grafika ze strony Pivotal Web Services
Zachęcająca grafika ze strony Pivotal Web Services

Moja aplikacja jest napisana w Spring Boot. A więc do dzieła!

Jak wdrożyć aplikację?

  1. Wchodzimy na stronę http://run.pivotal.io/. Wita nas przyjazny komunikat o 87 dolarach w prezencie od firmy na cele testowania.

    1
    Bierzemy!
  2. Rejestrujemy się w serwisie. Musimy podać numer telefonu, żeby przepisać otrzymany kod.
  3. Firma uprzejmie prowadzi nas za rękę. Teraz pora na instalację PWS CLI, czyli konsoli do zarządzania aplikacją. Po instalacji logujemy się w sposób pokazany na stronie. 2
  4. Wdrażamy!

  5. Podglądamy efekt na stronie.

    Wdrożone!
    Wdrożone!
  6. Uczymy się korzystać z konsoli tekstowej oraz z widoku www.

Ile to kosztuje?

Cena to $0.03 za GB RAM na godzinę. Na stronie http://run.pivotal.io/pricing/ mamy wygodny suwak do obliczania kosztów:

Szacunkowe koszty utrzymania aplikacji
Szacunkowe koszty utrzymania aplikacji

$87 dostałam za darmo, na chwilę powinno wystarczyć.

Co dalej?

Przydałoby się to wdrażać automatycznie z GitHuba przez jakiś serwer ciągłej integracji.

PS.

  1. Dziękuję Marcinowi M. za podpowiedzi dotyczące wdrożenia w komentarzach pod pierwszym wpisem konkursowym.
  2. Poświęciłam wcześniej chwilę na rozpoznanie chmury OpenShift, ale dokumentacja była (dla mnie) znacznie mniej czytelna.

 

 

Mobilna wersja strony w Spring Boot

Moja konkursowa aplikacja właściwie nic jeszcze nie robi – ot, wyświetla kilka widoków. Dzisiaj przetestowałam nowy drobiażdżek: wyświetlanie innej wersji strony na urządzeniach mobilnych.

Jak to zrobić? W Spring Boot to naprawdę prosta sprawa. Wystarczy:

  1. Dodać jedną zależność w pliku pom.xml
  2. Dopisać poniższą linię w pliku resources/application.properties (utworzyć plik, jeśli nie istnieje), nadpisując tym samym domyślnie ustawienie właściwości.
  3. Zapisać mobilne wersje widoków w katalogu mobile (lub innym, jeśli zmienisz domyślną wartość właściwości spring.mobile.devicedelegatingviewresolver.mobilePrefix)

    Mobilne wersje widoków
    Mobilne wersje widoków

Po takim przygotowaniu możemy już podziwiać stronę w wersji normalnej i mobilnej. W swojej wersji mobilnej na teraz dodałam tylko słówko “MOBILE”. Wygląda to tak:

Wersja mobilna strony

Urządzenie mobilne udałam przy użyciu dość badziewiastego dodatku do Firefoksa o nazwie User Agent Switcher.

UPDATE: Marcin S. podpowiedział mi, że w Chrome można udawać urządzenie mobilne bez potrzeby instalowania żadnych dodatków:

Tryb mobilny w Google Chrome

UPDATE2: Historie komórkowe

Odkrywam nową Javę przy okazji dat

Przyznaję, że ten wpis jest nieco wymuszony. Zasady Daj się poznać nakładają na mnie obowiązek wrzucania dwóch postów konkursowych tygodniowo. Tymczasem, choć informatycznie działo się u mnie sporo, projekt konkursowy w tym tygodniu leżał odłogiem. Dlaczego? Pomijając już przygody z nadgarstkiem – rozpoczęłam studia podyplomowe (przetwarzanie danych – big data)!  Wczoraj, na moim dawnym wydziale, bawiłam się SQL-em, dzisiaj R. O R mam nawet anegdotę, ale na razie nie wymyśliłam pretekstu, żeby podciągnąć ją pod temat konkursowy.

Jeśli chodzi o moją aplikację Szafbook: nadal gnębi mnie kwestia dat. Pisałam już o tym, że HTML5 udostępnia pole wejściowe input typu date.  Niektóre przeglądarki (Chrome!) wyświetlają przy nim elegancki widżet do wyboru daty z kalendarza. Inne nadal pozwalają/nakazują użytkownikowi samodzielne wpisanie wartości.

Nie byłam pewna, co z tym zrobić. Nie chcę rozbijać daty urodzenia na trzy osobne pola – za bardzo podoba mi się rozwiązanie z Chrome. Nie chcę wykrywać przeglądarki i podejmować decyzji w zależności od niej. Tak długo, jak będzie to możliwe, chcę się trzymać z dala od JavaScriptu.

Co tymczasowo wymyśliłam? Własny sposób tworzenia obiektu reprezentującego datę na podstawie danych wprowadzonych przez użytkownika, w  którym pozwalam użytkownikowi na nieco większą elastyczność niż trzymanie się jednego sztywnego formatu daty.

Kod i uwagi do niego wklejam poniżej. Przy okazji zauważyłam kilka nowych (dla mnie) rzeczy w Javie. Najbardziej spodobały mi się grupy nazwane w wyrażeniach regularnych, wprowadzone w Javie 7.  Dzięki ich istnieniu mogę wyciągnąć rok, miesiąc i dzień z tekstu dopasowanego do jednego z dwóch różnych wyrażeń regularnych. Bez nazw miałabym z tym większy problem, ponieważ numery grup (których trzeba było używać wcześniej) nie zgadzałyby się ze sobą (rok to grupa 1 w pierwszym wzorcu i grupa 3 w drugim).

W ogóle lubię wyrażenia regularne! 🙂 Na poprzednim blogu pojawił się kiedyś wpis o pułapkach regeksowych w Javie. Chyba przypomnę go w przyszłym tygodniu.

  • 8. Użycie mojego własnego kodu do zamiany wartości tekstowej na typ Calendar.
  • 17 i 18: Wyrażenia regularne mają umożliwić akceptację dat takich jak: 2016-04-10, 2016.04.10, 04/10/2014. Każde z wyrażeń definiuje 3 grupy nazwane: year, month oraz day.
  • 39-41: Odwołuję się do grup, które są obecne niezależnie od tego, który z dwóch wzorców zadziałał.
  • 43: Dość lekkie testy poprawności daty dopasowanej do wzorca. Zajrzałam do implementacji kalendarza. Podanie nieistniejącego dnia miesiąca nie powinno spowodować rzucenia wyjątku. Jeśli użytkownik będzie uparcie twierdził, że urodził się 30 lutego… Mało mnie interesuje, jaką datę ustawi mu system.
  • 45: Ustawiam odpowiednią datę w moim kalendarzu. Początkowo chciałam mieć w tym miejscu obiekt typu Date, ale zorientowałam się, że tworzenie instancji Date w oparciu o rok, miesiąc i dzień od dawna nie jest zalecane.

Na koniec pozdrawiam z Warszawy! Przyjechałam z całą rodziną na konferencję 4Developers.

HTML5 na pomoc, czyli Firefox ssie

Na konkurs wymyśliłam sobie aplikację webową, no więc dłubię w formularzach. Staram się odpowiednio opisywać model danych (w Javie), na przykład:

Jednak niektóre typy danych są tradycyjnie kłopotliwe (polecam ten angielskojęzyczny artykuł na temat walidacji adresów email w oparciu o wyrażenia regularne).

Okazało się, że standard HTML5 opisuje specjalne typy pól wejściowych dla adresu email oraz daty. W kodzie strony wygląda to tak:

Email

Najpierw email. W Firefoksie mamy:

Walidacja adresu email w przeglądarce Firefox
Walidacja adresu email w przeglądarce Firefox

W Chrome podobnie, ale dostajemy trochę więcej informacji:

Walidacja adresu email w przeglądarce Google Chrome
Walidacja adresu email w przeglądarce Google Chrome

Data

Przy datach jest jeszcze ciekawiej.

Oto Chrome:

ch1
Pole do wprowadzania daty w Chrome, widok po załadowaniu
ch2
Pole do wprowadzania daty w Chrome, widok po najechaniu myszką i rozwinięciu menu

Co na to Firefox?

Firefox się nie wykazuje
Firefox się nie wykazuje

Firefox nic, Explorer oczywiście także.

Boję się przeglądarki Chrome. Google czyta moje maile i wie, czego szukam w Internecie. To, co wpisuję w pasku adresowym jest dla mnie ostatnią granicą… Ale w tej chwili chciałabym, żeby wszyscy użytkownicy korzystali właśnie z niej 🙂

 

Na co komu Maven?

Mój zalążek projektu kompiluję i buduję przy użyciu Mavena. Maven (ang. “spec”) to narzędzie do budowania projektów napisanych w Javie. Sam Maven także został napisany w tym języku. Maven pozwala w uporządkowany sposób zarządzać zagadnieniami takimi jak: kompilacja, testowanie, budowanie, wynajdowanie i pobieranie zależności, generowanie dokumentacji.

Po co mi Maven, skoro mogę zbudować projekt w moim IDE? Po pierwsze, IDE nie zawsze jest pod ręką i może nagle okazać się, że na komputerze kolegi nie da się zbudować pilnie poprawionej wersji kodu, gdyż brakuje pięciu bibliotek (a po ich pobraniu – pięciu kolejnych, wymaganych przez te pierwsze). Po drugie, jeśli kod ma być testowany, a nawet wdrażany automatycznie, to przecież potrzebna jest możliwość uruchomienia go z zewnątrz. Po trzecie wreszcie – Maven to cała masa udogodnień i gotowych rozwiązań.

Konfigurację projektu mavenowego umieszcza się w pliku pom.xml. Plik ten można napisać samemu, ale najczęściej jest on generowany przez jakiś inicjalizator. W moim wypadku był to wspomniany już wcześniej Spring Initializr, ale najczęściej szablon generuje sam Maven w oparciu o żądany “archetyp”. Poniższe wywołanie stworzy szkielet aplikacji webowej z odpowiednio zainicjalizowanym plikiem pom.xml:

Powstaje w ten sposób następująca struktura:

Wygląda znajomo?

Plik pom.xml mojego projektu wygląda tak:

Co oznaczają poszczególne elementy?

  • project: obowiązkowy znacznik najwyższego poziomu.
  • modelVersion: informacja o tym, z jakiego modelu DOM (Document Object Model) korzysta dany pom.xml. DOM w Mavenie zmienia się bardzo rzadko.
  • groupId: unikatowy identyfikator organizacji bądź grupy, która stworzyła projekt; najlepiej oparty o URL.
  • artifactId: nazwa głównego artefaktu generowanego przez projekt.
  • packaging: rodzaj wynikowego archiwum (e.g. JAR, WAR, EAR, etc.).
  • version: wersja powstałego artefaktu. SNAPSHOT oznacza wersję roboczą, do której się nie przywiązujemy.
  • name: wyświetlana (np. w dokumentacji) nazwa projektu.
  • description: krótki opis projektu
  • parent: (nieobowiązkowy) nadrzędny pom.xml, w którym zawarte są różne domyślne ustawienia projektu (np. kodowanie, konfiguracja pluginów).
  • properties: właściwości projektu. Ja podaję kodowanie źródeł oraz wersję Javy.
  • dependencies: zależności, czyli biblioteki potrzebne do zbudowania projektu. Jeśli nie ma ich na dysku, zostaną pobrane z repozytorium Mavena. Oprócz id grupy i artefaktu najczęściej trzeba podać także wersję, ale w tym wypadku wersjami podstawowych bibliotek zarządza wspomniany przed chwilą rodzic.
  • build: tu można zdefiniować podstawowe informacje na temat procesu budowania, np. lokalizację zasobów, profile budowania, niezbędne pluginy i ich konfiguracja. Pluginy w Mavenie mogą wszystko: potrafią przeprowadzić statyczną analizę kodu, przeformatować pliki itp. Moja aplikacja korzysta w tej chwili z pluginu Spring Boot Maven plugin, który umożliwia tworzenie uruchamialnych plików z aplikacją webową

Gdzie Maven przechowuje biblioteki?
Jeśli w systemie brakuje wymaganych bibliotek, Maven pobiera je ze zdalnego repozytorium http://mvnrepository.com lub innych wskazanych repozytoriówi umieszcza w repozytorium lokalnym.

Domyślna lokalizacja lokalnego repozytorium Mavena w systemie Windows
Domyślna lokalizacja lokalnego repozytorium Mavena w systemie Windows

Oto najważniejsze standardowe polecenia Mavena (kolejność nie jest przypadkowa):

  • validate: sprawdź, czy projekt jest skonfigurowany w sposób umożliwiający jego zbudowanie.
  • compile: skompiluj kod, jeśli zmienił się od poprzedniego razu
  • test: przetestuj kod (testy jednostkowe, niewymagające wdrożenia).
  • package: w oparciu o skompilowany kod utwórz wynikowe archiwum (np. JAR czy WAR).
  • integration-test: przeprowadź testy integracyjne (może obejmować wdrożenie).
  • verify: sprawdź jakość wynikowego archiwum.
  • install: zainstaluj archiwum w lokalnym repozytorium Mavena. Projekt stanie się wówczas dostępny jako zależność dla innych projektów.
  • deploy: wdróż!
  • clean: usuń wszystkie artefakty wygenerowane przez poprzednie buildy.
  • site: wygeneruj dokumentację (HTML w oparciu o Javadoc).

Jak to wygląda w moim projekcie? W oparciu o pom.xml powstanie plik szafbook-0.0.1-SNAPSHOT.jar. Mogę go uruchomić w konsoli – zawiera wbudowany serwer Tomcata, na którym odpali się moja aplikacja.

console
Maven w konsoli

Mavena można podpiąć pod wszystkie najważniejsze IDE. W Eclipse będzie to wyglądało tak:

Maven zintegrowany z Eclipse
Maven zintegrowany z Eclipse

W kolejnym wpisie postaram się odpowiedzieć (sobie) na pytanie, czy w przypadku mojego projektu warto porzucić Mavena na rzecz coraz popularniejszego systemu budowania Gradle.

Bonus: troubleshooting. Gdzie mój pom.xml?!  Eclipse domyślnie wyświetla pom.xml w postaci formularza. Poniższa ilustracja pokazuje, gdzie kliknąć, żeby dostać się do wersji tekstowej.

Przejście do wersji tekstowej w Eclipse
Przejście do wersji tekstowej w Eclipse