11 lutego 2009

Pierwsze kroki z Grails - rozdział 2. w "The Definitive Guide to Grails"

Pierwsze dwa rozdziały mam za sobą i gdybym mógł wszystko rzucić pewnie obróciłbym całe 500+ stron książki "The Definitive Guide to Grails", wydanie 2. w jeden dzień. Wciąż zdumiewa mnie mój zachwyt Grails. Wszystko wydaje się być takie proste. Oby zachwyt nim nie minął z rozpoczęciem pierwszej aplikacji webowej. Podczas mojego wystąpienia na 4Developers 7. marca w Krakowie przedstawię Grails praktycznie oraz jego okolice - Groovy i Project Zero. Wartoby do tego czasu rozpracować wszelkie niuanse, aby nie zostać zaskoczonym bardzo podstawowym pytaniem, a już nieciekawie byłoby nie móc skonfrontować mojego entuzjazmu z faktycznymi wdrożeniami w Grails. Stąd wszelkie uwagi i pytania proszę zadawać teraz. Podglądam opis wykładu Python i Django: Szybkie i latwe tworzenie aplikacji webowych Marcina Mierzejewskiego, tak aby uczestnicy mogli porównać ich cechy (Django wymienia się jako protoplastę Grails), ale niestety jego i moje wystąpienie są w tym samym czasie! No cóż, my wiemy co dobre i pojawimy się na Grails, czyż nie?!

Wracając do rozdziału 2. "Getting Started with Grails" to wiele już z tego było podczas mojej lektury "Beginning Groovy and Grails". Niektóre z porównań czy uwag są nowością dla mnie, ale ogólnie nic nowego.

W poprzednim rozdziale autorzy stworzyli zrąb aplikacji gTunes z pojedynczym kontrolerem. Teraz przedstawiają mechanizm rusztowania (ang. scaffolding), za pomocą którego można niezwykle szybko (< 1 minuta) stworzyć prototyp aplikacji CRUD dla danego modelu (klas dziedzinowych). To musi się podobać! I się podoba. Wyróżniamy dwa typy rusztowania: dynamiczny i statyczny. Dynamiczne rusztowanie budowane jest "na bieżąco" podczas uruchomienia aplikacji. Tworzone są widoki (strony GSP) oraz kontroler. Korzysta z mechanizmu prześwietlania (ang. reflection) oraz cechy Groovy. Wystarczy zdefiniować klasę dziedzinową (poleceniem grails create-domain-class) i w odpowiadającym jej kontrolerze (stworzonym poleceniem grails create-controller) definiujemy atrybut scaffold, np.
 package pl.jaceklaskowski.nauczyciel

class SlowoController {
def scaffold = Slowo
}
Dla Groovy Slowo == Slowo.class, więc nie ma konieczności podania rozszerzenia .class jawnie.

Podczas dynamicznego rusztowania Grails rozpoznaje typy poszczególnych atrybutów klas dziedzinowych i dostraja widok, np. dla atrybutów typu String tworzy pole tekstowe w GSP, a dla atrybutów typu Date wyświetli pole rozwijalne do wyboru daty.

Utworzenie relacji jeden-do-wielu między klasami dziedzinowymi możliwe jest dzięki statycznemu polu hasMany, którego wartością jest mapa, w której klucz to nazwa atrybutu, a wartość to typ elementu, z którym klasa jest związana, np.
 static hasMany = [slowa:Slowo]
Deklarując atrybut statyczny hasMany w klasie A ustawiamy jedynie relację jednokierunkową. Klasa docelowa nie ma świadomości uczestniczenia w niej. Dodanie pola o typie klasy źródłowej relacji zmienia relację na dwukierunkową.

Domyślna implementacja metody toString() w Grails to nazwa klasy i identyfikator obiektu. Ma to znaczenie przy wyświetlaniu listy obiektów w relacji jeden-do-wielu, dla widoku klasy wiodącej w relacji.

Rusztowanie statyczne opiera się na szablonach, które można dowolnie modyfikować. W Grails możemy stworzyć konieczne kontrolery i widoki GSP dla klas dziedzinowych - wystarczy grails generate-views, grails generate-controller czy grails generate-all. Dzięki stworzonym artefaktom możemy poznać jak właściwie działa Grails.

Warto wtrącić uwagę autorów (str. 17), że Grails is not just a CRUD framework. Ostatnio chyba za bardzo naciskam na ten CRUD w Grails i może nawet (pochopnie) postawiłem znak równości między nimi. Zdaje się, że pospieszyłem się (chociaż nie widzę innych zastosowań na razie).

Domyślną metodą (domknięciem) wykonywanym przez Grails w kontrolerze jest index. Nie podano akcji w URI, wykonana zostanie index.

Konwencją w Grails jest wiązanie strony GSP dla danego kontrolera i jego domknięcia tak, że dla kontrolera XControler i akcji (domknięcia) y zostanie wyświetlona strona grails-app/views/x/y.gsp.

W GSP możemy skorzystać z metod redirect i render, odpowiednio do przekierowania na podanego w action domknięcia (akcji) oraz wyświetlenia podanej strony (parametr view).

Możemy korzystać z atrybutu scaffold ustawionego na daną klasę dziedzionową, dla której istnieje "nasz" kontroler bez konieczności tworzenia stron GSP - zostaną stworzone dynamicznie (uzupełnią braki).

Dalej autorzy przedstawiają konfigurację reagującą na środowisko, w którym Grails pracuje. Pojawia się konfiguracja bazy danych (za pomocą konfiguracji Hibernate w grails-app/conf/DataSource.groovy) na przykładzie MySQL. Warto zauważyć, że można konfigurować dostęp do bazy danych przez podanie wszystkich parametrów połączenia (per środowisko), albo wskazanie wpisu w drzewie JNDI parametrem jndiName (w dataSource dla danego środowiska).

Stworzenie paczki wdrożeniowej to wykonanie grails war. Domyślna konfiguracja Jetty znajduje się w GRAILS_HOME/conf/webdefault.xml, a uruchomienie WARa to grails run-war. Polecenie grails run-app jest zalecane do uruchamiania "rozwojowego".

Pełne polecenie grails war to grails [środowisko (opcjonalne)] war [katalog-zapisu-war (opcjonalnie)].

p.s. Zainteresowani wsparciem moralnym pisarza Notatnika proszeni są o wzięcie udziału w konkursie Bloger Roku 2008. Wystarczy wejść na stronę do głosowania na Notatnik, gdzie podajemy nasz adres email i zatwierdzamy. Wiadomość z adresem potwierdzającym pojawia się w naszej skrzynce, klikamy w niego potwierdzając nasz wybór. I tyle. Dziękuję!