Archiwum Szsz.pl: kwietnia 2009

GAE/J - Hello World (2)

piątek, 17 kwietnia 2009

Oto mały opis moich eksperymentów z Google App Engine for Java

Część pierwsza, Część druga

Od chwili gdy zacząłem pisać ten tekst minęło kilka dni. W tym czasie w sieci pojawiło się sporo interesujących artykułów na temat GAE/J. Najciekawsze z nich dotyczą wykorzystania dynamicznych języków.

Aktualizowany na gorąco spis można znaleźć w dokumencie
Frameworks and libraries supported by Google App Engine Java .

Najciekawszy projekt jaki znalazłem, to konsola pozwalająca na eksperymenty z prostymi skryptami w kilku językach jednocześnie. Wzmiankę zamieściłem w kategorii Znalezione jakiś czas temu. Polecam.
Many languages, and in the runtime bind them.
Demonstracja, wraz z kodem źródłowym znajduje się pod adresem lotrepls.appspot.com.

Na tle wspomnianych przykładów, to co piszę wypada dość blado, językiem Java zajmowałem się nieco poważniej w 1998 roku i od tego czasu jedynie sporadycznie poświęcałem mu uwagę. Tak więc, mając nadzieję że to co piszę, przyda się przynajmniej początkującym, opisuję moje dalsze zmagania z GAE/J.

Tym razem mam zamiar opisać coś ciekawszego, przedstawiony tu prosty programik od początku do końca działa w oparciu o mechanizmy serializacji.

Makefile (build.xml)

Poprzedni opis zakończyłem na uruchomieniu przykładowej aplikacji, nie wnikając w szczegóły jej funkcjonowania.

Jeśli ktoś chciał by podany przykład rozbudować, szybko odkrył by poważne ograniczenia, jakie ma domyślny plik build.xml. Chcąc rozwiązać ten problem, stworzyłem własny szablon aplikacji, obsługujący domyślnie wymagane mechanizmy i łatwiejszy do dalszej rozbudowy.

Szablon ten jest dostępny na stronie: code.google.com/p/szsz/downloads/.

Główna zmiana dotyczy pliku build.xml, który teraz jest na tyle uniwersalny, by nie wymagać dalszych modyfikacji.

Wszystkie pliki xml w szablonie zawierają odpowiednie przykłady i odnośniki do dokumentacji. Zachęcam do przetestowania i liczę na ewentualne uwagi.

HelloWorld

App Engine wykorzystuje Servlet API. Rozwiązanie opracowane przez firmę Sun Microsystems w 1998 roku, gdy stało się jasne że wykorzystanie, popularnego wówczas, interfejsu CGI w języku Java nie wchodzi w grę.

Osoby znające lekkie frameworki MVC poczują się swojsko gdy tylko zobaczą pierwszy przykład kodu:

HelloWorld.java

public class HelloWorld extends HttpServlet {

    public void doGet(
        HttpServletRequest  req, 
        HttpServletResponse resp)
    throws IOException {
        resp.getWriter().println("Hello, world");
    }

}

To nie wymaga żadnych dodatkowych komentarzy.

Serializacja

GAE/J ma jedną cechę za którą wielu programistów Java pewnie znienawidzi to środowisko. Część rdzennego API, do którego dotychczas stosowano założenie typu zawsze działa, jest niedostępna. Dotyczy to głównie obsługi wątków, dostępu do relacyjnych baz danych i możliwości modyfikowania systemu plików.

Jedynym mechanizmem służącym do przechowywania danych jest Datastore, do którego dostęp odbywa się poprzez API do serializacji danych (JDO, JPA). W ten sposób serializacja staje się podstawą działania każdej aplikacji w tym środowisku.

Tym razem przykład będzie się składał z kilku części i będzie w pełni oparty o model MVC.

Do dzieła..

Model

Czyli, klasa obiektów służących do manipulowania danymi. Niech będzie to prosta tabela słownikowa, typu nazwa=wartość.

Oczywiście aby aplikacja miała sens, potrzebuje jeszcze paru metod, nadających obiektowi życie i adnotacji, pozwalających na zapisywanie stanu.

Something.java

@PersistanceCapable
class Something {

    @PrimaryKey private String name;
    @Persistent private String value;

    Test(String k, String v) { 
        name =  k; 
        value = v; 
    }

    String doSomething() { 
        return name + ", " + value; 
    }

}

To wszystko. Kluczem do serializacji są adnotacje @PersistanceCapable, @PrimaryKey i @Persistent.

Adnotacje, są pewnego rodzaju specjalnymi komentarzami/dyrektywami, rozszerzającymi opis klasy na użytek funkcji korzystających z Reflection API

Przed wydaniem Java 1.5, serializacja w tym języku przypominała czarną magię i wymagała odrębnego pliku xml z opisem pól i ich mapowania na bazę danych. Na szczęście te ponure czasy już minęły. Teraz definicja klasy zawiera wszystkie informacje potrzebne do automatycznego zbudowania odpowiedniego kodu.

Kontroler (inicjalizacja)

By zobaczyć w działaniu nasz prosty model, będziemy potrzebowali równie prostego kontrolera.

Na początek będzie potrzebny prosty servlet tworzący trwałe obiekty. Ponieważ nie było by wskazane aby był dostępny dla postronnych osób, do uruchomienia będą wymagane odpowiednie uprawnienia, które ustawiamy modyfikując plik web.xml.
Akcja jest wywoływana metodą POST, potrzebny będzie odpowiedni formularz: install/index.html.

Install.java

class Install extends HttpServlet {

    public void doPost(
        HttpServletRequest  req, 
        HttpServletResponse resp)
    throws IOException {
  
        PersistenceManager pm = PMF.manager();

        Something hello = new Something("Hello", "world");
        pm.makePersistent(hello); /* ZAPIS */
        pm.close();

        resp.getWriter().println("DONE");
  
    }

}

Uwaga. Zaprezentowane tu zabezpieczenie jest dość mizerne. Należało by przynajmniej weryfikować czy akcja została wywołana przez właściwy formularz - bez tego, administratora tak napisanej aplikacji może spotkać przykra niespodzianka.

Dodatkowo do działania potrzebny jest singleton PMF.java. To rozwiązanie jest zalecane w dokumentacji GAE/J ze względów wydajnościowych, a przy okazji zaoszczędza trochę pisaniny.

Kontroler (podgląd)

Przydało by się zobaczyć efekty działania instalatora. Można by oczywiście skorzystać z opcji Data Viewer w konsoli sterującej. (Po uprzednim załadowaniu aplikacji na serwer produkcyjny), ale..

Tradycyjnie w tym miejscu tworzy się szablon JSP, który nieco przypomina skrzyżowani ASP i PHP. Wydawało by się że zapewnia to wystarczającą separację pomiędzy implementacją a wizualizacją. W wielu przypadkach rzeczywiście tak jest, ale można posunąć się dalej i całkowicie usunąć warstwę prezentacyjną z aplikacji działającej na serwerze.

Na początek, niezbędne minimum kodu..

Show.java

class Show extends HttpServlet {

    public void doGet(
        HttpServletRequest  req,
        HttpServletResponse resp)
    throws IOException {
  
        PersistenceManager pm = PMF.manager();

        /* ODCZYT */
        Something hello = pm.getObjectById(
                Something.class, 
                "Hello"
        );

        resp.getWriter().println( hello.doSomething() );
    }

}

.. oraz odpowiednie modyfikacje web.xml

W ten sposób udało się stworzyć program, który przy całej swojej złożoności, angażując najnowocześniejsze techniki, produkuje wynik identyczny z pojedynczym poleceniem print.

Kontroler (json)

Do operowania na danych została wykorzystana serializacja, a co by było gdyby tą samą technikę wykorzystać do przesłania danych na przeglądarkę?

Gdy zacząłem moje eksperymenty, sprawdziłem kilka rozwiązań. Między innymi bilioteki z json.org, które okazały się być zbyt nisko poziomowe i popularną bibliotekę xstream, która wydawała się idealnym rozwiązaniem, ale niestety zaczęła sprawiać problemy po instalacji na serwerach GAE/J - to się wkrótce może zmienić, więc jeśli ktoś woli używać xml, to polecam tą bibliotekę.
Wreszcie znalazłem rozwiązanie, które pasuje idealnie: flexjson.

Flexjson, używa wyłącznie formatu JSON. Domyślnie biblioteka serializuje publiczne pola. Jednak podobnie jak w JDO można za pomocą adnotacji określić, które właściwości mają być obsługiwane przez bibliotekę.
Największą zaletą biblioteki jest to że potrafi używać getterów i setterów, co czyni ją niezwykle elastycznym narzędziem. Dzięki temu nie trzeba traktować trwałych obiektów jak sztywnych struktur danych.

Bibliotekę instalujemy kopiując plik flexjson.jar do katalogu lib. W szablonie, który tu zaprezentowałem ta biblioteka już jest zainstalowana.

Zacznijmy od określenia w modelu, które pola mają być wysyłane do odbiorcy.

Something.java

    public @JSON String getName() { return name; }
    public @JSON String getValue() { return value; }

Następnie wystarczy nieznaczna modyfikacja kontrolera..

Show.java

    Something hello = pm.getObjectById(Something.class, "Hello");

    JSONSerializer ser = new JSONSerializer().exclude("class");
    resp.getWriter().println(
        ser.prettyPrint(hello)
    );

To wszystko.

Widok

Pozostało już tylko wyświetlić przesłane dane na przeglądarce. Można to na przykład zrobić w taki mało elegancki sposób: index.html.

$(function() {
    $.getJSON("/show", function(data) {
        $("body").html(
            data.name + ", " + data.value
        );
    });
});

Bardziej eleganckie rozwiązanie, wymagało by zastosowania odpowiednich szablonów. W końcu po stronie przeglądarki także warto oddzielić kod od warstwy prezentacyjnej :) ..ale to już kiedy indziej.

Podsumowanie

Pisanie przykładów takich jak ten, przypomina chwilami budowę kanału panamskiego po to aby później puścić nim papierową łódkę.
Chwilami w gąszczu skomplikowanych konstrukcji, można zagubić sens tego wszystkiego, myslę jednak że API do serializacji jest na tyle proste że nie sprawia problemów ze zrozumieniem.. Natomiast nowe podejście jest znacznie wygodniejsze od mozolnego łączenia się z bazami danych, czytania licznych plików i składania informacji kawałek po kawałku..

Gdyby kotoś chciał eksperymentować z przedstawionym tu kodem, to jest on dostępny do pobrania za pomocą svn
svn co -r11 http://szsz.googlecode.com/svn/trunk/gae-java/hello hello-szsz

Miłej zabawy

Etykiety: , , ,

Komentarze (0)

Red 12:29

GAE/J - Hello World (1)

sobota, 11 kwietnia 2009

Oto mały opis moich eksperymentów z Google App Engine for Java

Część pierwsza, Część druga

Instalacja

Aby zacząć pisać program, korzystając z GAE/J potrzebnych jest kilka rzeczy:

Java SDK
To najbardziej oczywisty składnik,
jeśli po napisaniu polecenia javac -version w odpowiedzi otrzymamy np: javac 1.6.0_11, to znaczy że możemy przejść do następnego punktu.
Jeśli nie, no cóż.. java.sun.com
Apache Ant
Mrówka i pliki build.xml są dla języka Java tym czym dla języka C jest make i Makefile - narzędziem pozwalającym programiście operować logiką Zrób to co mam na myśli. Można oczywiście obyć się bez tego pakietu, ale jako że bardzo ułatwia życie, polecam jego instalację. Dodam jeszcze że wszystkie przykłady są wydane wraz z plikami build.xml.
Instalację weryfikujemy pisząc ant -version, w odpowiedzi powinniśmy dostać coś takiego: Apache Ant version 1.7.1 compiled on June 27 2008
Jeśli nie jesteśmy szczęśliwym posiadaczem tego pakietu to zapraszam na stronę ant.apache.org
Eclipse
Opcja dla leniwych. ;)
Osobiście pominąłem ten punkt i nie będę go opisywał.
Użytkownicy tego IDE, będą podążali własnymi ścieżkami i nie spodziewam się by mieli pożytek z tego co tu piszę. Będą też potrzebowali armii odpowiednich pluginów..
Google App Engine SDK
Wszystko co potrzebne jest dostępne na code.google.com
Wystarczy pobrać odpowiedni zip, rozpakować i można zacząć zabawę.
W katalogu demos można znaleść przykładowe projekty.
Konto Google z aktywowanym GAE/J
Obsługa języka Java, jest w fazie testów i wymaga otrzymania zaproszenia. W celu aktywacji usługi konieczna jest wizyta na stronie appengine.google.com, tam też zakładamy nasz projekt.
Dane konta i id projektu będą potrzebne do publikacji kodu.
Środowisko

GAE/J różni się od swojego krewniaka obsługującego język Python, w większości przypadków będziemy mieli do czynienia z Java feel and look. Żegnamy się więc z czytelnymi plikami yaml i wracamy do xml. Również struktura SDK jest nieco bardziej złożona i lepiej przystosowana do większych projektów.

Eksperymenty polecam robić na szablonie projektu, skopiowanym z katalogu demos/new_project_template.

Wszystkie przykłady w katalogu demos są skonfigurowane tak aby można było je uruchomić bezpośrednio w tym katalogu. Umieszczając projekt w innym miejscu, należy zmodyfikować build.xml i podać lokalizację SDK. W tym celu szukamy na początku pliku definicji <property name="appengine.sdk" location="../.." /> i modyfikujemy atrybut location tak by wskazywał na SDK

To wszystko co trzeba zmienić by otrzymać działający przykład. Pomimo że konfiguracja jest zapisana w xml, plik jest dużo bardziej czytelny niż typowe generowane automatycznie Makefile. Zachęcam do późniejszego przejrzenia go w całości.

Środowisko testowe można uruchomić w klasyczny, znany z poprzednich edycji GAE sposób, ale wygodniej jest wpisać ant dev_appserver. Przy okazji mamy gwarancję że nowo uruchamiana aplikacja zostanie w razie potrzeby skompilowana. (Serwer należy restartować po każdej modyfikacji kodu).

Teraz, przyszła pora na ustawienie środowiska aby możliwa była instalacja na serwerach Google.
W katalogu src/WEB-INF znajdują się dwa pliki:

Instalacja rozpoczyna się po wpisaniu ant update. Jeśli wszystko się powiedzie aplikacja powinna być dostępna na id.appspot.com (na przykład szsz.appspot.com)

Podsumowanie
html
zawiera statyczne pliki projektu, takie jak index.html
src
Kody źródłowe java, oraz pliki konfiguracyjne
www
Tu znajduje się skompilowany i gotowy do opublikowania kod aplikacji
Wszędzie poza szablonem katalog ten nazywa się war (dokumentacja, przykłady). można to łatwo poprawić edytując plik build.xml, nie wem skąd wziął się ten brak konsekfencji.

Najważniejsze pliki

build.xml
Odpowiednik Makefile. Zawiera opis wszystkich reguł potrzebnych do zarządzania projektem. Najważniejsze z nich można wywołać następującymi poleceniami:
ant
Kompiluje program, tworząc katalog www (war)
ant dev_appserver
Uruchamia testowy serwer
ant update
Aktualizuje aplikację na serwerach Google
ant request_logs
Pobiera logi w formacie Apache (domyślnie z dwóch dni)
ant clean
Kasuje katalog www (war)
Dokumentacja pliku build.xml.
src/WEB-INF/web.xml
Konfiguracja servletów i przypisanie ich do scieżek.
Struktura pliku jest na tyle czytelna że nie wymaga dodatkowego opisu.
src/WEB-INF/appengine-web.xml
Konfiguracja Appengine. Dokładniejszy opis poniżej
Dokumentacja pliku appengine-web.xml
Co dalej

Mając działające środowisko, można zacząć eksperymenty z kodem, ale to już opiszę w następnej części. Zapewne już po świętach.

Etykiety: , ,

Komentarze (0)

Red 12:22

AppEngine - Java

środa, 8 kwietnia 2009

Dziś minął rok od wydania Google Appengine. Nowej platformy serwerowej dla aplikacji internetowych.

Appengine jest środowiskiem zmieniającym reguły gry na rynku. Dotychczas, tani dostawca usług serwerowych oferował platformę składająca się z języka PHP i bazy MySQL. Pomijając ograniczenia, głównym problemem był fakt że ów dostawca nie zawsze zachowywał się jak solidny partner w interesach. Wręcz przeciwnie, w krytycznym momencie podejmował wrogie działania, mające na celu pozbycie się klienta zbyt intensywnie wykorzystującego oferowane zasoby.. Gdy serwis odnosił sukces, oznaczało to zwiększony ruch, lub wyższe obciążenie procesora. Często kończyło się to zablokowaniem usługi i koniecznością poszukiwania innego partnera.

Jak łatwo się domyślić, głównym atutem nowego środowiska jest wysoka skalowalność. W wersji podstawowej Appengine jest darmowe, opłaty ponosi się dopiero po przekroczeniu pewnego pułapu. Nawet wtedy płaci się tylko za wykorzystane zasoby, a nie tak jak dotychczas, za sam fakt ich dostępności.

Nowo wydane środowisko miało jednak dość poważne wady. Przez pierwszy rok swojego funkcjonowania Appengine był ograniczony do jednego języka, jeżeli ktoś go nie znał / nie lubił, to miał pecha. Również API było ściśle związane ze środowiskiem, co zmuszało do pisania aplikacji specjalnie z myślą o nim.

Jak można było się tego spodziewać, w rocznicę wydania środowisko Appengine zostało poważnie rozbudowane. Najważniejsze zmiany dotyczą właśnie dwóch powyższych zarzutów.

Plotki o tym że kolejnym obsługiwanym językiem będzie Java, krążyły od jakiegoś czasu. Wybór platformy Java Virtual Machine jest oczywisty. Oznacza że można samodzielnie rozpocząć eksperymenty z używaniem wielu innych języków dostępnych na JVM. Javascript, Ruby, Scala i wiele innych wszystko to jest teraz na wyciągnięcie ręki.

Przy okazji wydania Appengine for Java zauważalny jest olbrzymi nacisk położony na zgodność ze standardami, serializacja, memcache - wszystkie te rozwiązania dotychczas działające w oparciu o API specyficzne dla Appengine, zostały teraz oparte o standardowe biblioteki z języka Java. Efekt: możliwość dwustronnej migracji programów z/do istniejących platform i systemów korporacyjnych.

Nie sposób także pominąć innych istotnych zmian, które wprowadzają do Appengine zupełnie nową jakość:

Zadania wykonywane w tle (Cron), możliwość importu/eksportu baz danych, a także co może być najważniejsze możliwość łatwego i bezpiecznego łączenia z korporacyjnymi bazami danych - dotychczas było to piętą achillesową wszelich usług hostingowych.

Wszystko to przekształca Appengine w poważne środowisko programistyczne do którego należy przyszłość internetu.

Polecam lekturę Nowe możliwości w Google App Engine

Przypuszczam że jeszcze nie raz będę o nim wspominał.

Etykiety: , ,

Komentarze (0)

Red 22:06

Archiwum

Subskrybuj

RSS / Atom