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
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:
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.
@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.
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..
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.
public @JSON String getName() { return name; } public @JSON String getValue() { return value; }
Następnie wystarczy nieznaczna modyfikacja kontrolera..
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: gae, json, programowanie, R
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
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 poleceniajavac -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ącant -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 katalogudemos
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:
- web.xml, jest odpowiedzialny za mapowanie servletów na URL.
- appengine-web.xml, zawierający informacje specyficzne dla środowiska Google.
Wystarczy wpisać id naszego projektu zarejestrowanego na appengine.google.com.
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: gae, programowanie, R
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: gae, programowanie, R
Red 22:06