Inicjalizacja danych w zależności od trybu uruchomienia aplikacji Grails

Pisząc aplikacje w Grails niejednokrotnie stajecie przed koniecznością wykonania pewnej logiki podczas startu aplikacji, logika taka to np. dodanie użytkownika do bazy danych, zapisanie podstawowych i zarazem koniecznych do działania aplikacji danych w bazie.
Logika taka powinna zostać zawarta w klasie BootStrap znajdującej się w katalogu conf Waszej aplikacji. Początkowa postać tej klasy to:

class BootStrap {

     def init = { servletContext ->
     }
     def destroy = {
     }
}

W bloku init możecie umieścić kod, który zostanie wywołany podczas uruchomienia aplikacji, blok destroy powinien zawierać operacje, które mają zostać wykonane podczas zakończenia aplikacji - zakończenie takie musi odbyć się w sposób standardowy, zakończenie wykonania aplikacji spowodowane sytuacją nadzwyczajną nie spowoduje wykonania instrukcji zawartych w bloku destroy.

Dodajmy do powyższej klasy kod, który zostanie wykonany podczas startu naszej aplikacji:

class BootStrap {

     def init = { servletContext ->
          new User(username: ‘admin’, password: ‘admin’).save()
     }
     def destroy = {
     }
}

W ten sposób zapisujemy użytkownika o loginie admin i haśle admin, oczywiście musimy mieć utworzoną klasę domenową User z odpowiednimi polami ;)

Teraz podczas startu naszej aplikacji nasz przykładowy użytkownik będzie zawsze dodawany do bazy,
pytanie co zrobić gdy chcemy wykonać logikę w zależności od środowiska w którym uruchamiamy aplikację, jak wiadomo standardowo mamy trzy środowiska: development, test, production. Uruchomienie aplikacji w konfiguracji odpowiadającej określonemu środowisku odbywa się poprzez wykonanie komendy grails run-app z odpowiednim parametrem, np.:

grails prod run-app

Powyższa komenda uruchomi aplikację w trybie produkcyjnym.
Dobra, pojawia się teraz pytanie jak w klasie BootStrap sprawdzić w jakim trybie została uruchomiona nasza aplikacja?
Odpowiedź jest bardzo prosta, użyjemy do tego celu takiego oto fragmentu kodu:

def env = GrailsUtil.environment

Jest to wywołanie statycznej metody getEnvironment, znajdującej się w klasie GrailsUtil (dla niewtajemniczonych wywołania getterów w Groovy wyglądają jak odwołania do pól klasy). Teraz zmienna env będzie zawierała wartość dzięki której będziemy w stanie zidentyfikować rodzaj trybu w jakim uruchomiona została aplikacja, będą to odpowiednio: test, development, production dla trybów: testowego, developerskiego, produkcyjnego.

Teraz nie pozostaje nam nic innego jak uzależnić od zwróconej wartości wykonanie odpowiedniego kodu, można tu standardowo zastosować instrukcję if-else, można też to zrobić sprytniej i wykorzystać dobrodziejstwa jakie daje nam Groovy:

class BootStrap {

     def init = { servletContext ->
        def env = GrailsUtil.environment
        InitializeData.“$env”()
     }
     def destroy = {
     }
}

Co oznacza powyższy blok kodu, a w szczególności tajemnicza konstrukcja InitializeData.”$env”()?
A więc dzięki niej w bardzo ciekawy sposób rozdzieliliśmy wykonanie kodu zależnego od trybu w którym została uruchomiona aplikacja, umieszczając go w klasie InitializeData w jej statycznych metodach:

class InitializeData {

       static void development() {
           //kod wykonywany dla środowiska developerskiego
       }

       static void test() {
           //kod wykonywany dla środowiska testowego
       }

       static void production() {
           //kod wykonywany dla środowiska produkcyjnego
       }
       
}

Zastosowana konstrukcja InitializeData.”$env”() służy do wywołania statycznej bezparametrowej metody o nazwie odpowiadającej wartości zmiennej env, która została zdefiniowana w klasie InitializeData

December 14, 2008 | 3 Comments 

Groovy - przydatne informacje

Dzisiaj kilka przydatnych linków dla wszystkich zainteresowanych Groovy:

  • Strona domowa projektu
  • Strona projektu Groovy, znajdziecie tam specyfikację języka, tutoriale i masę linków do różnego typu blogów i portali poświęconych językowi Groovy.

  • Grails
  • Strona domowa najpopularniejszego frameworku webowego napisanego w Groovy

  • Groovy on Grails
  • Agregator blogów o Groovy i Grails.

  • Gradle
  • Narzędzie do budowania aplikacji stworzonych przy pomocy języka Groovy (i nie tylko).

  • GroovyMag
  • Magazyn developerów Groovy, bardzo ciekawy lecz płatny :)

  • Grails Podcast
  • Podcast poświęcony Groovy i Grails.

  • Hosting aplikacji napisanych w Grails
  • Najlepszy hosting aplikacji Grails.

  • Groovy Zone
  • Wydzielona część DZone w całości poświęcona Groovy.

  • Grails Jobs
  • Szukasz pracy jako deweloper Grails? W takim razie ta strona jest warta Twojej uwagi.

  • Groovy Blogs
  • Kolejny agregator blogów o Groovy.

  • Grails Tutorials
  • BARDZO przydatna strona z linkami HOWTO w Groovy i Grails.

  • IntelliJ IDEA
  • Bezsprzecznie najlepsze środowisko do Groovy i Grails.

  • About Groovy
  • Newsy, Podcasty, Książki o Groovy i Grails - wszystko w jednym miejscu.

  • Grails Crowd
  • Szukasz projektów napisanych w Groovy lub Grails? Musisz odwiedzić powyższą stronę.

  • Grails success stories
  • Lista tzw. “success stories” na oficjalnej stronie Grails.

  • Groovy Awards
  • Kto jest najlepszym developerem Groovy? Sprawdź na Groovy Awards.

  • Groovy Live
  • Znacie Try Ruby!? Jeśli tak to czas na Groovy Live, co prawda w chwili obecnej po chińsku ale w niczym to nie przeszkadza :)

December 12, 2008 | 2 Comments 

GeeCON - pierwsza międzynarodowa konferencja o Javie oficjalnie ogłoszona!

Miło mi oznajmić, że z dniem dzisiejszym oficjalnie zostały ogłoszone prace nad pierwszą międzynarodową konferencją poświęconą Javie i RIA w Polsce. Konferencja ta nazywa się GeeCON i odbędzie się w maju przyszłego roku w Krakowie. Jest ona organizowana przesz Polską Grupę Użytkowników Języka Java, Czeską Grupę Użytkowników Języka Java oraz Poznańską Grupę Użytkowników Języka Java.

Konferencja potrwa dwa dni, podczas których uczestnicy będą mieli możliwość spotkania światowej sławy specjalistów, wśród nich Guillaume Laforge, Charles Nutter oraz Scott Davis i wielu innych. Mam nadzieję, że wydarzenie to przejdzie do pamięci wszystkich sympatyków języka Java w naszym kraju.

Aby się zbytnio nie rozpisywać zapraszam Was na oficjalną stronę konferencji.

December 8, 2008 | 6 Comments 

ROOT application context w aplikacji Grails

Pisząc ostatnio aplikacje w Grails, stanąłem przed problemem zmiany kontekstu aplikacji z domyślnego na ROOT, czyli chciałem aby moja aplikacja uruchamiała się po wpisaniu adresu serwera i portu, bez konieczności podawania specjalnej nazwy kontekstu. Zadanie wydawałoby się proste, mógłbym się bawić w konfigurowanie aplikacji w kontenerze w którym uruchamiałem aplikację, jednak chciałem to zrobić w sposób zalecany przez twórców Grails (wtedy nie wiedziałem, że tak ciężko będzie znaleźć informację na ten temat).
Po dość uciążliwym googlowaniu natrafiłem na rozwiązanie. Okazało się, że ustawienie kontekstu aplikacji sprowadza się do zdefiniowania odpowiedniego wpisu w pliku Config.groovy:

grails.app.context = “/”

W ten oto sposób możecie ustawić kontekst aplikacji na tzw. ROOT.

Dziwi mnie fakt, że dokumentacja Grails nie informuje o tym, moim zdaniem użytecznym parametrze, ja odnalazłem informację o nim w jednym z wpisów w dedykowanym Grails’om systemie obsługi zgłoszeń.
Dodam jeszcze, że w chwili pisania tego wpisu Google pokazuje tylko 123 wyniki dla zapytania “grails.app.context”, widać więc, że rozwiązanie to jest mało znane.

December 7, 2008 | Leave a Comment 

URL mapping w Grails

Dzisiaj będzie szybko aczkolwiek treściwie :) Podczas pisania aplikacji w Grails niejednokrotnie pojawia się potrzeba zmienienia mapowania URLi. Mapowanie takie definiujemy w pliku UrlMappings w katalogu conf naszej aplikacji. Plik taki ma początkowo następującą postać:

class UrlMappings {
    static mappings = {
        “/$controller/$action?/$id?”
        {
            constraints {
                // apply constraints here
            }
        }
}

Załóżmy jednak, że chcielibyśmy aby pod następującą ścieżką:

/site/id

Była dostępna strona która będzie rozpoznawana za pomocą parametru id.
Mapowanie takie możemy zdefiniować za pomocą następującego wpisu w pliku UrlMapping:

“/site/$id”
{
        controller = “main”
        action = “showPage”
        constraints {
              // apply constraints here
        }
}

Mapowanie to sprawi, że po wywołaniu adresu kończącego się na /site/home zostaniemy przekierowani do kontrolera o nazwie main (nazwa klasy to MainController) i zdefiniowanej w nim akcji showPage. Z poziomu akcji możemy pobrać identyfikator strony, uczynimy to w następujący sposób:

def showPage = {
        [pageInstance: Page.findByPageId(params.id)]
}

Jak widać w powyższym kodzie, parametr id zdefiniowany w mapowaniu URL’a będzie dostępny w params pod tą samą nazwą. W ten sposób pobierzemy stronę której parametr pageId jest równy home gdyż taka właśnie wartość odpowiada naszemu parametrowi id.
Dodatkowo w sekcji constraints możemy zdefiniować warunki dla których nasz URL będzie mapowany, np.:

“/site/$id”
{
        controller = “main”
        action = “showPage”
        constraints {
              id(matches:/[A-Z]{5}/)
        }
}

Dodanie id(matches:/[A-Z]{5}/) do bloku constraints spowoduje, iż jako parametr id podane będą mogły być wartości spełniające wyrażenie regularne, w tym wypadku identyfikator id musi się składać z pięciu liter z których dopuszczalne to A-Z.

Ostatnia ważna rzecz przy mapowaniu URLi to zdefiniowanie parametru będącego częścią URL’a jako parametru opcjonalnego:

“/site/$id?”
{
        controller = “main”
        action = “showPage”
        constraints {
             
        }
}

Zmieniliśmy tutaj ciąg znaków “/site/$id” na “/site/$id?, dodanie pytajnika oznacza, że parametr ten jest opcjonalny. Niezależnie od tego czy go podamy, czy też nie to zostaniemy przekierowani do akcji showPage w kontrolerze MainController.

December 5, 2008 | Leave a Comment