27 maja 2007

JavaTechConf 2007 w Krakowie za nami

4 komentarzy
Gdyby mnie zapytać o krótkie streszczenie konferencji JavaTechConf 2007 natychmiast odpowiedziałbym, że była ona najlepszą konferencją w jakiej kiedykolwiek uczestniczyłem. Organizacja konferencji była na najwyższym poziomie i poza brakiem klimatyzacji na sali wszystko było niezwykle starannie poukładane. Mnóstwo ludzi - naliczyłem około 150 osób - tworzyło niesamowitą atmosferę, która mimo wysokich temperatur na zewnątrz i braku klimatyzacji, wszystkim pozwoliła na dobrą zabawę. Najbardziej wartościowa w konferencji była możliwość spotkania osób, które znane mi były od dawna z pl.comp.lang.java, czy jdn.pl, ale nigdy nie miałem okazji ich poznać osobiście. Uczestnictwo w konferencji dało wspaniałą okazję do nadrobienia zaległości.

Wszystko zaczęło się od telefonu od Radka Holewy (jednego z organizatorów imprezy) w piątek około 18:00, abym zapomniał o pociągu i przybył samochodem, najlepiej już w piątek. Jako, że konferencja rozpoczynała się o 9:00 moim wystąpieniem o Apache Geronimo wcale mnie to nie zdziwiło. Zmartwiła mnie jednak myśl o 3,5-godzinnej trasie do Krakowa. Krótki telefon do znajomych w Krakowie i wiedziałem, że muszę wyruszać około 5 nad ranem, aby zdążyć na 9:00. Udało się! O 8:50 byłem w Krakowie na Akademii. Po krótkiej zapowiedzi Piotra Maja już prezentowałem Geronimo. Kilka dowcipów zrobiło swoje i braki merytoryczne wydaje się, że nie zostały zauważone (poza wyjątkami jakimi raczył mnie Geronimo, co zostało utrwalone na poniższym zdjęciu). Mogąc przemawiać na sali ze 150 uczestnikami było niesamowitym przeżyciem, a udział członków Warszawa JUG pomógł mi przetrwać stres. Dzięki Panowie!


Po moim wystąpieniu pojawił się na scenie Tomasz Korzeniowski. Bardzo podobały mi się jego slajdy i technika prezentacji. Sprawnie przechodził z jednego wzoru matematycznego do drugiego tak, że po chwili nie miałem pewności, czy spociłem się ze względu na temperaturę, czy próbując zrozumieć tok rozumowania Tomka. Prezentacja wydawała się, że będzie o Lucene i była, ale u mnie pozostał niedosyt. Chciałoby się więcej, ale niestety 1,5 godziny mija szybko, kiedy na scenie jest Tomek. Przez swoją zawartość akademicką (dotykającą matematyki wyższej) prezentacja Tomka była wyjątkowa jak na Java TechConf.

Kolejny prelegent Roman Swoszowski postanowił zaprezentować RIA w wykonaniu Flex 2.0. Uczestniczyłem w spotkaniu o Flex 2.0 podczas spotkania Warszawa JUG w wykonaniu Bartka Soina, więc nie ukrywam, że już na początku skreśliłem prezentację z listy interesujących. I mimo, że Roman bardzo się starał, to nie wygrał z moim nastawieniem do Flex'a i...narastającym głodem. Dodając do tego temperaturę, byłem na wykończeniu.

Z wielką ulgą przywitałem przerwę. W gronie około 20-osobowym poszliśmy do pobliskiej pizzerni. I to nie z powodu jedzenia (zamówiony makaron był generalnie do kitu), ale ze względu na dyskusje, jakie się wywiązały przy stole, przerwa była nadwyraz treściwa. Okazało się, że zainteresowanie podobną konferencją w Warszawie jest wystarczające i 3 osoby od razu przystały na pomysł, aby wystąpić na niej jako prelegenci. Jacek, Andrzej i bodajże Tomek - wielkie dzięki! To Wasza decyzja uwieńczyła moje zmagania z pomysłem o zorganizowaniu podobnej konferencji w Warszawie na MIMUW. Do tego komentarz Piotra Maja, że mając salę i prelegentów mamy wszystko i stało się - na forum Warszawa JUG ogłosiłem oficjalnie o przygotowaniach do I Warszawskiej Konferencji Informatycznej. Jest to tymczasowa nazwa do czasu zarejestrowania domeny, kiedy to będę mógł ogłosić jej faktyczną nazwę.

Kolejna prezentacja była poprowadzona przez gościa z Czech - Romana Strobla. Osoba, która znana jest ze swojego zapału promocji NetBeans IDE, więc wiedząc o jego warsztacie prezentacyjnym i wiedzy o NetBeans z wielkim zainteresowaniem przysłuchiwałem się co ma na ten temat do powiedzenia. Gość był niesamowity! Po raz pierwszy zobaczyłem tworzenie i uruchomienie aplikacji mobilnej i wsparciu NetBeans IDE w tym zakresie. Jako, że Roman pracował z wersją rozwojową NetBeans IDE 6.0M9 nie obyło się bez wyjatków, ale ich pojawienie nie mogło zepsuć wspaniałej atmosfery prezentacji. Co mnie zdumiło, to ilość pytań. Biorąc pod uwagę, że prezentacja prowadzona była po angielsku nie spodziewałem się żadnych pytań, albo co najwyżej kilku, a tu nie tylko, że były, to jeszcze było ich najwięcej ze wszystkich prezentacji razem wziętych. Ciekawe czy sprawiła to tematyka prezentacji czy dodatkowa trudność w zadawaniu pytań po angielsku (takie malutkie wyzwanie poobiednie).

Z wielkim entuzjazmem przywitałem kolejną prezentację o EJB 3.0 w wykonaniu członka grupy Equilibrium - Janusza Marchewy. Grupa Equilibrium bardzo uaktywniła się ostatnio na jdn.pl i chciałem zobaczyć ich na żywo. Temat EJB 3.0 bardzo mnie interesuje i poświęciłem mu trochę czasu ostatnio, więc nie tylko, że mogłem utrwalić wiedzę o EJB 3.0, ale również poznać członka grupy w akcji. Możliwość wysłuchania prezentacji Janusza upewniła mnie, że goście są doświadczeni, ale sposób w jaki dochodzą do wiedzy przedstawiony (nawet napisałbym rekomendowany) przez Janusza zdecydowanie odbiega od mojego.
Przede wszystkim, zdaniem Janusza, poznawanie techologii tak obszernych jak JPA, czy nawet EJB 3.0, powinno być realizowane przez jedną osobę, gdyż większa ilość osób to jedynie same problemy komunikacyjne, jak i bardzo prawdopodobne borykanie się kilku osób z tymi samymi problemami zrozumienia tematyki. Według mnie, rozwiązaniem dla problemów komunikacyjnych nie jest zmniejszenie osób, ale właśnie ich zwiększenie i właściwe nimi koordynowanie. 15-minutowe spotkania na początek i koniec dnia zrobiłoby swoje i znacząco skróciłoby czas przyswajania technologii.
Kolejnym stwierdzeniem, z którym nie mogłem się zgodzić, było sposób poznawania technologii - praktyczne vs teoretyczne. Praktyczne polega na poznawaniu technologii podczas projektu, podczas gdy teoretyczne polega na lekturze specyfikacji, książek, artykułów, itp. W/g mnie wszystko zależy od dostępnego czasu, w którym projekt korzystający z danej technologii ma się pojawić i jedyna reguła to chęć samych uczestników do podnoszenia własnych kwalifikacji. Uczenie się technologii w praktyce niesie ze sobą ryzyko niewłaściwego stosowania jej i możliwego "położenia" projektu, jak i samego (potencjalnie) niewłaściwego wyboru technologii na rzecz innej. Drugi sposób - uczenie się teoretycznie - daje możliwość ewaluacji i wstępnego zebrania wiedzy zanim możnaby wykorzystać ją praktycznie. Oba mają rację bytu, jednak ja skłaniam się ku drugiemu, gdzie grupa osób poświęca pewien czas na rozpoznanie technologii i przedstawienia jej szerszemu gronu. Najlepiej, jeśli poznawanie technologii jest związane z 15-minutowymi, codziennymi spotkaniami, na których prezentowanoby dotychczasowy zakres wiedzy. Zebrane pytania pomogłyby wypełnić braki merytoryczne - pomóc zaplanować kolejne tematy do rozpoznania - lub pozwolić na szerzenie wiedzy od pierwszego dnia.
Co mnie postawiło na nogi to był komentarz Janusza dotyczący działania funkcji EntityManager.merge. Kolejny raz usłyszałem stwierdzenie, że funkcja odpowiada za zapisanie zmian w bazie danych podczas, gdy jej jedyne zadanie to związanie encji odłączonej z kontekstem trwałości (ang. persistence context). Jako, że najczęściej użycie funkcji merge związane jest z właśnie kończącą się transakcją, więc mylnie można założyć, że merge zapisuje dane do bazy danych. Tak jednak nie jest. Zapis do bazy danych następuje wyłącznie podczas zakończenia transakcji (zawsze), albo jako wynik wywołania funkcji flush, persist, co niekonieczne musi powodować natychmiastowy zapis, gdyż dostawca JPA może poczekać na moment zakończenia transakcji.

Na koniec konferencji wystąpił Piotr Maj z prezentacją o OSGi. Nie spodziewałem się, że wstęp do OSGi może mnie czegoś nauczyć, ale sposób w jaki Piotr zaprezentował OSGi był wyjątkowy. Piotr skorzystał z pomysłu, aby technologie przedstawiać z IDE, a nie PowerPoint'em, czy innym narzędziem do prezentacji. Pojawiły się pakunki Piotra.Szarmanckiego i Pani.Kokietki i po kilku uderzeniach klawiszy już byliśmy świadkami zarywania w wykonaniu Piotra Sz (i tym samym Piotr M. poderwał publikę). Bardzo zwięzła i konkretna prezentacja. W pewnym momencie Piotr Sz. i Pani K. nie chciały ze zobą rozmawiać i można było zauważyć lekkie zniecierpliwienie Piotra M. poszukującego rozwiązania w panelach konfiguracyjnych pakunków, ale mimo późnych godzin i temperatury publika pokazała, że nie śpi i padło rozwiązanie z sali. Wspaniały przykład na zainteresowanie publiki tematem i tak go poprowadzenia, że w razie wyjątkowych sytuacji można na nią liczyć. Sposób prowadzenia prezentacji przez Piotra był zawsze moim ulubionym i planuję, że prezentacje podczas konferencji w Warszawie będą wszystkie prowadzone w tym stylu.

O 19:00 było po wszystkim i zaczęto przygotowania do imprezy, która miała odbyć się w pobliskim pubie. Niestety musiałem wracać do Warszawy, więc nie udało mi się uczestniczyć w niej.

Nie ma co tu pisać więcej - na tej konferencji trzeba było być. Chciałbym, aby tego typu konferencji było więcej w Polsce i wierzę, że nie będę musiał długo czekać na kolejną.

Specjalne pozdrowienia dla Łukasza (ActiveY), który obiecał mi srogi komentarz nt. moich ostatnich wypowiedzi nt. SOA i SCA. Czmychnąłem naprędce, aby mnie nie zganił publicznie.

Podczas konferencji miałem również okazję poznać Piotra Kobzdę, który w moim przekonaniu jest najlepszym gościem od typów generycznych na pl.comp.lag.java, żeby nie napisać w Polsce. Każde pytanie dotyczące tego zagadnienia nie pozostaje bez odpowiedzi Piotra, więc możliwość poznania go była dla mnie wielką przyjemnością. Przekonał mnie do zastosowania ASM vs cglib + bcel i planuję, że niedługo pojawi się coś nt. temat w moim Notatniku. cglib jest stosowany w wielu projektach otwartych do tworzenia rozszerzeń klas dynamicznie (proxy) i już miałem się
jemu przyjrzeć, kiedy Piotr skutecznie odradził mi to i przekonał do ASM, który z niewiadomych powodów dla Piotra jest traktowany niewłaściwie do możliwości. Dzięki Piotr za krótkie acz inspirujące wprowadzenie do manipulacji bajtkodu w wykonaniu ASM!

25 maja 2007

SCA z językami skryptowymi w wykonaniu Apache Tuscany, Jetty i Maven 2

5 komentarzy
Kolejne doświadczenia z SCA (Service Component Architecture) w wykonaniu Apache Tuscany i kolejne pomysły wykorzystania takiej konfiguracji w projektach. Tym razem udało mi się opisać wykorzystanie Tuscany, Jetty i Maven 2 do uruchomienia SCAlenia z usługą napisaną z użyciem języka skryptowego (Groovy) w środowisku serwera aplikacyjnego Java EE. Mam przeczucie, że niedaleko jest już do zrealizowania pomysłu, w którym usługi byłyby podmieniane podczas uruchomienia aplikacji. Zanim do tego przejdę, dotychczasowe osiągnięcia spisałem w kolejnym artykule zatytułowanym SCA z językami skryptowymi w wykonaniu Apache Tuscany, Jetty i Maven 2.

Zdumiewająca jest coraz większa ilość publikacji nt. SCA i w trakcie pisania artykułu otrzymałem namiary na jeden z nich - Build mashups with the Service Component Architecture and Apache Tuscany, którego wprawdzie jeszcze nie czytałem, ale pobierzne przejrzenie wskazuje, że może być niezwykle ciekawy.

A tak z innego podwórka napiszę, że dzięki uprzejmości Marka Goldmanna grupa Warszawa JUG dostępna jest pod nowym adresem www.warszawa.jug.pl. Marek przekonuje inne JUGi w Polsce (Poznań JUG i PWrJUG), aby również skorzystały z oferty wykorzystania domeny jug.pl. Pojawiło się jeszcze kilka innych pomysłów rozruszania społeczności Java w Polsce, ale nie chcąc zapeszać nie powiem nic więcej. Cieszę się, że wśród nas zapracowanych znajdują się jeszcze niedobitki, którym się jeszcze chce trochę poudzielać. Brawo Marek!

Przypominam o nadchodzącej konferencji Java TechConf 2007 w Krakowie, podczas której zaprezentuję Apache Geronimo 2.0-SNAPSHOT w akcji. To już jutro! Ciągle pojawiają się nowe pomysły na moją prezentację i obawiam się, że przy takiej ich ilości, nic z tego nie wyjdzie. Będzie (trochę spóźniona) ekipa z Warszawa JUG, więc z pewnością pomogą. Zapowiada się ciekawie - w końcu doświadczę integracji między załogami warszawską i krakowską. Może w rewanżu należałoby coś zestawić pod koniec czerwca w Warszawie - coś na kształt Java TechConf. Zobaczymy...

20 maja 2007

X spotkanie Warszawskiej Grupy Użytkowników Technologii Java (Warszawa-JUG)

0 komentarzy
Warszawska Grupa Użytkowników Technologii Java (Warszawa-JUG) zaprasza na X spotkanie, które odbędzie się w nadchodzący wtorek 22.05.2007 o godzinie 18:00 w sali 4420 na Wydziale MiMUW przy ul. Banacha 2 w Warszawie.

Temat prezentacji: Języki skryptowe w Javie 1.6 (JSR 223) w praktyce
Prowadzący: Jakub Kaniewski

Podczas prezentacji zaprezentowane zostaną dobrodziejstwa płynące ze specyfikacji JSR-223 Scripting for the Java Platform. Zaprezentowane będą założenia grupy projektowej i w jakim stopniu udało się je zrealizować. Główną rozważaną kwestią będzie, gdzie w projektach biznesowych opartych o platformę Java EE jest miejsce na języki skryptowe - jakie zalety i wady niesie w sobie ich użycie. Na koniec zaprezentowane będzie małe porównanie prędkości różnych implementacji JSR-223 i porównanie z odpowiadającym kodem napisanym w "czystej" Javie. Dla podtrzymania tradycji spotkań Warszawa JUG, gwoździem programu będzie działająca aplikacja korzystająca z EJB 3 ze wstawkami w języku skryptowym.

Prezentacja prowadzona będzie przez Jakuba Kaniewskiego, który jest absolwentem kierunku Informatyka i Ekonometria na Wydziale Nauk Ścisłych UKSW (rocznik 2005). Z Javą ma styczność hobbystycznie i zawodowo od 5 lat. Główne zajmuje się technologiami serwerowymi: Apache Cocoon, JSF, Hibernate, EJB 3. Ostatnio próbuje sił w Ruby i JRuby.

Planowany czas prezentacji to 1,5 godziny z 15 minutową dyskusją.

Zapraszam w imieniu Warszawa-JUG!

SCAlenie (kompozyt) z Apache Tuscany i Apache Maven

0 komentarzy
Po kilku dniach rozpoznawania specyfikacji SCA - Service Component Architecture postanowiłem spróbować swoich sił i sprawdzić jej obietnice tworząc SCAlenie (częściej zwane jako kompozyt, ale pachnie mi za bardzo hutą, czy czymś podobnym) z wykorzystaniem Apache Tuscany oraz Apache Maven. Procedurę tworzenia SCAlenia opisałem w postaci kolejnego artykułu SCAlenie (kompozyt) z Apache Tuscany i Apache Maven. Jest to przyczułek do kolejnego rozpoznania bardziej skomplikowanych możliwości SCA z użyciem EJB, BPEL oraz Spring Framework.

SCAlenie jest podstawowym elementem specyfikacji architektury komponentów usługowych (SCA) i czym więcej zapoznaję się z nią, tym bardziej chcę ją wykorzystać w projektach. Możliwości rozproszenia aplikacji i korzystania z usług, których realizacja jest nie tylko w Javie, a których składanie (nie powinienem napisać scalanie?) odbywa się przy pomocy adnotacji i pliku XML są bardzo kuszące. Co rusz pojawia się wykorzystanie Spring Framework, Java EE oraz OSGi. Wszystko co ciekawe w jednym! Nic, tylko SCAlać!

p.s. Jeśli są propozycje przejścia na użycie słowa kompozyt, albo jeszcze innego zamieniam się w słuch.

14 maja 2007

Tworzenie aplikacji Google Web Toolkit z Java Persistence API

0 komentarzy
Poznając Google Web Toolkit (GWT) coraz bardziej doskwierał mi brak środowiska, które umożliwiłoby mi tworzenie aplikacji z GWT wykorzystując przy tym JPA i inne technologie Java EE wraz z uruchomieniem całej aplikacji na serwerze aplikacyjnym Java EE. Niby wszystko było jasne, jak należy wszystko zestawić, ale nie mogłem się zebrać i w końcu to sprawdzić w praktyce. Przypadkiem natrafiłem na ciekawy artykuł o GWT i Apache Geronimo - Build an Ajax-enabled application using the Google Web Toolkit and Apache Geronimo, Part 1: Run compiled Google Web Toolkit applications on Geronimo. Nie mogłem wymarzyć sobie lepszego materiału do zgłębiania tajemnic GWT, co zmotywowało mnie do zajęcia się tematem bliżej. Zaraz zabrałem się za lekturę. Tak na marginesie muszę przyznać, że artykuł pojawił się w samą porę, bo nie tylko, że poznam GWT bliżej analizując przykład z artykułu, to jeszcze będę miał dobre przygotowanie na konferencję JavaTechConf 2007 w Krakowie pod koniec maja, gdzie właśnie prezentuję Apache Geronimo i jego wsparcie dla Java EE 5. Jeśli, więc pokażę technologie Przemysłowej 5-tki w połączeniu z GWT będzie to z pewnością prezentacja, na której po prostu warto być ;-) Mam wiele pomysłów na moją godzinną prezentację i mimo bardzo krótkiego czasu na jej poprowadzenie, do worka technologicznego na konferencję dorzucam również i GWT. Obym nie obiecał gruszek na wierzbie, bo mam już w nim Apache Geronimo, Apache Maven 2, TestNG, JPA i zapewne JSF 1.2 (w wykonaniu Apache MyFaces). Szkoda, że konferencja jest w tak odległym terminie, bo znając siebie, coś na pewno jeszcze dorzucę i zamiast godziny będę prezentował cały dzień.

Wracając do moich doświadczeń z GWT i JPA przez ostatnie kilka dni, było ich tyle, że postanowiłem je spisać i udostępnić jako kolejny artykuł - Tworzenie aplikacji Google Web Toolkit z Java Persistence API. Czytelnik znajdzie tam informacje potrzebne do zestawienia środowiska programistycznego do tworzenia aplikacji z GWT i JPA oraz Apache OpenJPA, Apache Derby, Dozer i Jetty wszystko zarządzane przez Apache Maven 2. W końcu udało mi się zapoznać z ostatnimi z tematów w GWT, m.in. serializacją, kontrolkami graficznymi GWT i obsługą zdarzeń. Zeszło mi się trochę z tym środowiskiem (bodajże 4 dni) i ciekawym bardzo komentarzy i uwag odnośnie zawartości merytorycznej artykułu. Coś wydaje mi się, że trochę dużo tego wyszło i mało kto dotrwa z lekturą do końca. Może powinienem rozważyć nagrodzenie najwytrwalszych?!

Dalsze możliwości rozwoju aplikacji to udoskonalenie wyglądu interfejsu użytkownika i podział projektu na oddzielne podmoduły (w sensie M2) - dla części GWT i JPA. Jeśli będą chętni do udostępnienia swoich zmian w tym kierunku z miłą chęcią opublikuję je w ramach artykułu.

A skąd pomysł na aplikację Rejestr Osób? W czasach otwierania teczek tego typu aplikacje przeżywają swój okres rozkwitu, więc i ja musiałem spróbować. Oczywiście jest to namiastka prawdziwej aplikacji, ale jej tworzenie w GWT sprawiło mi wiele przyjemności, może nawet tyle, że zastanawiam się, co miałoby mnie skłonić do napisania jej korzystając z JSF. Na prawdę zaczynam mieć coraz większe wątpliwości przed wyborem tej jedynej technologii przy następnych projektach - wydaje się, że GWT spełnia wszystkie wymagania stawiane współczesnym szkieletom programistycznym wliczając w to wręcz banalny sposób tworzenia zaawansowanych interfejsów użytkownika, udostępnienie funkcjonalności Ajax, możliwość wykonywania zdalnych usług i tym samym wykorzystania usług serwera Java EE, obsługę przycisku wstecz, itp. Będę musiał poświęcić kilka chwil na głośne rozważania na ten temat, bo teraz na gorąco, po pomyślnie zakończonej integracji GWT i JPA zdecydowanie byłobym za GWT. Dzięki Janek, Grzesiek i Marcin za pomysł aplikacji!

Na sam koniec wrócę jeszcze do mojego ostatniego wpisu o SCA - SCA - Service Component Architecture - zaczynam rozpoznanie czegoś całkowicie dla mnie nowego. Nie ukrywam, że liczyłem na pewnien odzew w tej kwestii, ale dyskusja jaka rozwinęła się przeszła moje najśmielsze oczekiwania. Bardzo dziękuję wszystkim za komentarze, które zamierzam wykorzystać studiując specyfikację SCA. Zanim na dobre zaangażowałem się w zestawianie środowiska z GWT i JPA, udało mi się zapoznać z kilkoma materiałami nt. SCA i jedną z cech, które niezwykle mi się podobały była możliwość podmiany modułu SCA dynamicznie podczas działania aplikacji. Wydaje mi się, że przykład prezentujący tę możliwość w połączeniu z GWT mógłby być niezwykle interesujący. Wyobraźmy sobie aplikację składającą się z kilku modułów SCA (wykorzystanych przez zdalne usługi GWT), która pracuje nieprzerwanie z możliwością dynamicznej podmiany modułu. W ogóle, tworzenie modułu SCA jest tak łudząco podobne do tworzenia usługi zdalnej w GWT, że trudno o nich czytać nie sądząc, że czyta się o jednym i tym samym. Dla dalszego zobrazowania roli SCA możnaby porównać ją z OSGi do budowania modularnych architektur. Jeśli OSGi pozwala na wyszukanie modułu i jego zarządzanie podczas działania aplikacji, to różnica między SCA polega na zasięgu takiej funkcjonalności - w OSGi wszystko dzieje się w ramach pojedyńczej wirtualnej maszyny podczas, gdy w SCA nie ma żadnych takich ograniczeń - miejsce uruchomienia nie implikuje dostępnych usług. Ciekawe tylko, czy faktycznie moje rozumienie roli SCA i OSGi jest słuszne? Dużo dobrych technologii powstaje i człowiek nic innego by nie robił, jak tylko się nimi bawił i rozpoznawał. A tu Panie Jacku coraz cieplej za oknem i komu chciałoby się przesiadywać przez komputerem?! Ech, byle do zimy! ;-)

09 maja 2007

SCA - Service Component Architecture - zaczynam rozpoznanie czegoś całkowicie dla mnie nowego

7 komentarzy
Do tej pory przyszło mi głównie pracować z technologiami, które w dużej mierze należały do Przemysłowej 5-tki (Java EE 5). Ostatnio jednak coraz bardziej bombardowany zapytaniami o SOA i okolice i odpowiadając pobieżnie, wydaje się, że wreszcie nadeszła pora zajrzeć na inne podwórko. Tym podwórkiem są technologie integracyjne pod łopoczącym sztandarem nazwanym SOA. Sam akronim - Service-Oriented Architecture - oddaje jedynie myśl czy podejście architektoniczne, a mnie potrzeba technologii. Interesują mnie technologie Java, więc postanowiłem sprawdzić czego można się douczyć na innym podwórku i dlaczego wciąż jestem o to pytany. Przyznaję, że samo pojęcie - SOA - nie jest obce, ale kiedy przychodzi do produktów, technologii i konkretnych wdrożeń nie mam wiele do powiedzenia. Na pewno nie tyle, ile mógłbym powiedzieć o Java EE. Jest kilka podobnych obszarów, którymi chciałbym się zająć dokładniej(m.in. OSGi), ale zainteresowanie SCA zeszło się z kilkoma (być może nie-)przypadkowymi wydarzeniami i przeważyło szalę.

Po pierwsze, w mojej komercyjnej działalności postanowiono, abym zajął się tym tematem i związanymi produktami jak IBM WebSphere Integration Developer (WID), IBM WebSphere Process Server (WPS), IBM WebSphere Enterprise Service Bus (WESB) i kilkoma mniej istotnymi z mojego punktu widzenia. Nie, nie zamierzam opisywać tu moich bojów z tymi produktami. Pozostawię to na inną działalność.

Drugim powodem była wiadomość na grupie dyskusyjnej programistów Apache Geronimo, gdzie Raymond Feng z Apache Tuscany napisał w Geronimo/Tuscany integration o planach integracji tych dwóch środowisk.

Trzeci powód, hmmm, nie pamiętam teraz, ale sama chęć zapoznania się z technologiami już przecież wystarczy, nieprawdaż? Pamiętam, kiedy projekt Apache Tuscany był zakładany i od początku go śledziłem, aż do momentu, kiedy ilość wiedzy potrzebnej do zrozumienia poruszanych tam tematów przekroczyła moje możliwości. Teraz wracam do Tuscany, ponieważ jest to jedyna znana mi otwarta implementacja specyfikacji SCA i podobno działa na Apache Tomcat i być może niedługo na Geronimo.

Acha, przypomniałem sobie o trzecim powodzie - nowy członek grupy Warszawa JUG jest zobowiązany do zaproponowania możliwych tematów prelekcji na spotkaniach Warszawa JUG. Ot, kilka pomysłów, co mogłoby być interesujące. I tak się dzisiaj stało, że padło kilka propozycji, m.in. SOA - moda czy realne korzyści oraz ESB w Java (openESB, JBoss ESB, ServiceMix) do czego szybko dorzuciłem podobny temat Specyfikacje SOA - SCA, SDO, BPEL i pojawił się kolejny powód dla rozpoznania SCA.

A, i jakby tego było mało, właśnie dzisiaj otrzymałem zaproszenie na webinar JBoss Enterprise Service Bus (ESB) 4.0 Webinar: Service-oriented architecture middleware is born o produkcie JBoss ESB, którego powstawanie również śledziłem i pamiętam początki (nie było to tak dawno w końcu - bodajże w zeszłym roku), a który jest blisko związany ze wspomnianymi technologiami.

Nie pozostaje, więc nic innego jak zabrać się do pracy i poczytać o SCA i Apache Tuscany. Kilka ciekawych adresów wartych odwiedzenia (materiał w języku angielskim, ale tak to bywa z nowymi technologiami), których odwiedzenie zaplanowałem na dziś:
Zaczynam od prezentacji o Apache Tuscany. Wkładam słuchawki i zabieram się do długiego spania^H^H^Hsłuchania.

08 maja 2007

GWT RPC raz jeszcze, RequestBuilder oraz Timer

0 komentarzy
Na razie idzie niezwykle gładko, zdecydowanie za dobrze. Tak kończyłem ostatni wpis o GWT i muszę przyznać, że z każdym dniem, kiedy zasiadam do GWT coraz bardziej się upewniam, że jest to właściwa technologia kliencka do dalszej ewaluacji. Chciałbym, aby z każdym szkieletem programistycznym (*) było tak przyjemnie.

(*) Nie przekonuje mnie użycie tłumaczenia szkielet programistyczny jako odpowiednik angielskiego framework. Z chęcią zmieniłbym je na coś bardziej dźwięcznego. Może pora na nowe słówko?! Tyle ich powstaje, a my ciągle szukamy tłumaczeń.

Sukcesem dnia dzisiejszego w kategorii GWT jest stworzenie namiastki aplikacji pod szumnie brzmiącym tytułem Kółko i krzyżyk. Mimo, że zgodnie z wypowiedzią Reinier Zwitserloot na forum GWT - How do I start ?:

run a continuous connection**: You can't create a 'live' connection between webapp and client. Let's say you want to write 2 player pacman in GWT, with the two players connected through your server: Can't really be done; every time a player hits a key, you have to submit a complete HTTP request, with at least 200 bytes worth of headers and the like in there.

sądziłem, że jednak się da i...się nie udało. To znaczy, udało się jedynie zasymulować grę z pewnymi ograniczeniami, które powodują, że po 3 dniach walki stwierdzam, że Reinier miał w 100% rację ;-)

Mimo nieodpowiedniego przykładu do zebrania doświadczeń w GWT poznałem wiele ciekawostek związanych z tym środowiskiem. Możliwość skorzystania z Apache Maven 2 do zarządzania tworzeniem aplikacji dodatkowo uprościło przedsięwzięcie i pozwoliło mi na skupienie się na detalach GWT, a nie wszystkiego wokół, poza GWT (jak to zazwyczaj bywa).

Zanim rozpiszę się na dobre wspomnę, że archiwum forum GWT jest nieocenionym źródłem informacji. W zasadzie są tam wszystkie pytania z odpowiedziami, które samemu zadawałem sobie próbując nagiąć się do myślenia w tonie GWT. Technologia jest na tyle młoda, jednakże wystarczająco stabilna do tworzenia części klienckiej aplikacji, że śmiało można powiedzieć, że niewiele jest dostępnych aplikacji, które możnaby potraktować jako wzorcowe. Pozostaje, więc skorzystanie z archiwum forum i przeszukiwanie Internetu (prawdopodobnie również z Google).

Dla przypomnienia, co wciąż jednak umykało mojej uwadze, jest fakt, że GWT to tworzenie aplikacji myśląc o niej w kanonach JFC/Swing, gdzie (zdalne) usługi wykonywane są na serwerze i traktowane jako źródło danych (i nic poza tym), a część kliencka będzie wykonywana w przeglądarce jako JavaScript. Ponownie, wspominany już, Reinier Zwitserloot trafił w dziesiątkę ze swoim opisem części serwerowej w przewrotnie nazwanym wątku JRuby on Grails?:

GWT turns your server into a dumb terminal for data.

, co odzwierciedla problemy, których doświadczałem próbując współdzielić dane między klientami. Początkowo wykorzystałem do tego servlet i dane umieszczane w zasięgu application. Przez długi czas nie mogłem się z tym pogodzić, że wymieniając dane między klientami korzystam z ServletContext. Zazwyczaj przechowuję w nim dane konfiguracyjne bądź statyczne dane, a dane dynamiczne umieszczam w zasięgu sesji (session scope) bądź najczęściej (do czego przekonało mnie JSF) zlecenia (request scope). Okazało się, że to, co należało obsłużyć za pomocą "czystego" GWT RPC ja "infekowałem" servletami, niepotrzebnie komplikując zadanie.

Dla zobrazowania tematu przedstawię sposób komunikacji aplikacji GWT (wykonywanej w przeglądarce jako JavaScript) z częścią serwerową reprezentowaną przez servlet (wykonywanej na serwerze w dowolnej technologii, m.in. Java EE):

RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, "/iloscGraczy");
try {
builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
Window.alert(exception.toString());
}

public void onResponseReceived(Request request, Response response) {
WitajSwiecieGWT.this.iloscGraczy = Integer.parseInt(response.getText());
}
});
} catch (RequestException e) {
Window.alert("Failed to send the request: " + e.getMessage());
}

i przez zdalną usługę w "czystym" GWT RPC:

AkcjaAsync remoteService = Akcja.App.getInstance();
remoteService.zarejestrujGracza(new AsyncCallback() {
public void onSuccess(Object result) {
label.setText("Zarejestrowano nowego gracza");
}

public void onFailure(Throwable caught) {
Window.alert(caught.toString());
}
});

Niby to samo, ale zmienia się podejście do zdalnej usługi, która jest źródłem danych. Niepotrzebnie wprowadzałem kolejną technologię - servlet - do zrealizowania funkcjonalności, którą ostatecznie obsłużyłem jako zdalną usługę w GWT RPC. Oczywiście w sytuacjach migracji z jednej technologii klienckiej (wliczam w to również JSF) do GWT taka sytuacja może się zdarzyć, ale przy tworzeniu aplikacji "od zera" wydaje się być niepotrzebne.

W zasadzie zrozumienie GWT RPC jest kluczem do stworzenia wyrafinowanej aplikacji w GWT. Zakładam jednocześnie, że samo poznanie kontrolek graficznych GWT - przyciski, okna, etc. - jest nieodzownym elementem poznawania GWT, ale przy znajomości JFC/Swing możemy ten krok pominąć (zakładając, że to już się po prostu zna). Podobieństwo między GWT a Swing jest tak ogromne, że możnaby postawić pomiędzy nimi znak równości.

Skoro GWT RPC jest tak istotne, to może istnieje sposób na skorzystanie z niego nie tracąc wiele czasu na zrozumienie istoty jego działania? Sądzę, że istnieje i już po samym zapoznaniu się z dokumentacją GWT - Remote Procedure Calls wszystko powinno stać się jasne. O GWT RPC pisałem również poprzednio - GWT RPC - mechanizm zdalnego wywoływania procedur w GWT w Notatniku, więc w zasadzie większość, jeśli nie cała, teoria za GWT RPC została już zaprezentowana. Najtrudniej jest przestawić się z myślenia technologiami klienckimi uruchamianymi na serwerze (wspierającymi tworzenie interfejsu użytkownika, np. JSF) na technologię kliencką uruchamianą w przeglądarce tworzoną w...Javie, czyli GWT. GWT RPC jest na tyle istotne, że warto poświęcić mu ponownie kilka chwil.

Procedura tworzenia zdalnej usługi w GWT RPC.

Krok 1. Utworzenie interfejsu usługi Gra

Hmmm, brzmi jak pierwszy krok podczas tworzenia komponentów EJB 3.0, czy w ogóle, dowolnej, modularnej aplikacji. To się może podobać każdemu (!)

package pl.jaceklaskowski.gwt.kolkoikrzyzyk.client;

import com.google.gwt.user.client.rpc.RemoteService;

public interface Gra extends RemoteService {
/**
* Zarejestruj gracza
*
* @return true jesli gracz zostal zarejestrowany, wpp false
*/
public boolean zarejestrujGracza();
}

Uwaga 1: Część kliencka musi być w pakiecie client będącymi podpakietem dowolnego pakietu.

Uwaga 2: Interfejs usługi musi rozszerzać interfejs com.google.gwt.user.client.rpc.RemoteService.

Krok 2. Utworzenie interfejsu asynchronicznego GraAsync

To niestety zaczyna pachnieć nieświeżo - jak programowanie z EJB 2.1 i wersjami poprzednimi. Chciałoby się skorzystać z adnotacji, które w aktualnej wersji GWT 1.3.3 są niemożliwe ze względu na ograniczenia wspieranej wersji języka Java - 1.4.2 i niżej. Przeżyliśmy EJB 2.1, przeżyjemy i GWT 1.3.3.

package pl.jaceklaskowski.gwt.kolkoikrzyzyk.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.AsyncCallback;

public interface GraAsync {
/**
* Zarejestruj gracza
*
* @return true jesli gracz zostal zarejestrowany, wpp false
*/
void zarejestrujGracza(AsyncCallback async);
}

Uwaga 1: Interfejs asynchroniczny usługi musi być nazwany zgodnie z regułą - nazwa interfejsu usługi + Async.

Uwaga 2: Każda metoda interfejsu asynchronicznego musi składać się z dodatkowego, dodawanego na końcu listy parametrów wejściowych parametru o typie AsyncCallback.

Krok 3. Utworzenie implementacji usługi GraImpl

package pl.jaceklaskowski.gwt.kolkoikrzyzyk.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import pl.jaceklaskowski.gwt.kolkoikrzyzyk.client.Gra;

import javax.servlet.http.HttpServletRequest;

public class GraImpl extends RemoteServiceServlet implements Gra {
public boolean zarejestrujGracza() {
HttpServletRequest request = getThreadLocalRequest();
// pracuj z obiektem request
// wszystkie inne metody HttpServlet sa rowniez dostepne - jestemy w koncu w servlecie
return true;
}
}

Uwaga 1: Implementacja usługi musi znajdować się w odpowiednim podpakiecie server.

Uwaga 2: Implementacja jest wykonywana na serwerze i dowolna technologia może zostać użyta do jej utworzenia.

Uwaga 3: Implementacja musi rozszerzać interfejs usługi a nie interfejs asynchroniczny.

Uwaga 4: Dostęp do obiektu request i response możliwy poprzez metody RemoteServiceServlet.getThreadLocalRequest oraz RemoteServiceServlet.getThreadLocalResponse, odpowiednio.

Krok 4. Rejestracja usługi - KolkoIKrzyzyk.gwt.xml

Kolejny krok, który mógłby być zrealizowany przez adnotacje. W końcu czasy plików konfiguracyjnych w XML są daleko za nami, nieprawdaż?

<module>

<inherits name='com.google.gwt.user.User'/>

<entry-point class='pl.jaceklaskowski.gwt.kolkoikrzyzyk.client.KolkoiKrzyzykGWT'/>

<servlet path="/gra" class="pl.jaceklaskowski.gwt.kolkoikrzyzyk.server.GraImpl"/>
</module>

Uwaga 1: Rejestrujemy usługę zdalną za pomocą elementu servlet, którego atrybut path określa ścieżkę mapowania servletu, a class klasę implementacji usługi.

Krok 5. Wywołanie usługi

GraAsync graUslugaZdalna = (GraAsync) GWT.create(Gra.class);
ServiceDefTarget endpoint = (ServiceDefTarget) graUslugaZdalna;
endpoint.setServiceEntryPoint(GWT.getModuleBaseURL() + "gra");

AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
// result zawiera egzemplarz zwrócony podczas wywołania zdalnej metody
// tutaj wykonujemy operacje na interfejsie użytkownika
}

public void onFailure(Throwable caught) {
// bardzo przykładowa realizacja
Window.alert(caught.toString());
}
}

graUslugaZdalna.zarejestrujGracza(callback);

Uwaga 1: W GWT nie istnieje możliwość wykonania usługi synchronicznie, więc należy "przestawić się" na myślenie asynchroniczne, tj. dane mogą nadejść po pewnym czasie.

Uwaga 2: Adres servletu w linii 3. przykładu, gdzie wykonywana jest metoda setServiceEntryPoint odpowiada dokładnie ciągowi znaków wpisanemu w pliku konfiguracyjnym modułu w atrybucie path elementu servlet.

Uwaga 3: Warto skorzystać ze "wzorca", które podpowiada IntelliJ IDEA 6, tj. dodać poniższą klasę do interfejsu usługi

public static class App {
private static GraAsync ourInstance = null;

public static synchronized GraAsync getInstance() {
if (ourInstance == null) {
ourInstance = (GraAsync) GWT.create(Gra.class);
((ServiceDefTarget) ourInstance).setServiceEntryPoint(GWT.getModuleBaseURL() + "gra");
}
return ourInstance;
}

co sprowadzi powyższy krok do następującego:

GraAsync graUslugaZdalna = Gra.App.getInstance();

AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
// result zawiera egzemplarz zwrócony podczas wywołania zdalnej metody
// tutaj wykonujemy operacje na interfejsie użytkownika
}

public void onFailure(Throwable caught) {
// bardzo przykładowa realizacja
Window.alert(caught.toString());
}
}

graUslugaZdalna.zarejestrujGracza(callback);

Krok 6. Integracja usługi z aplikacją

Samo wywołanie usługi należy podpiąć do wykonania zdarzenia w interfejsie użytkownika pamiętając, że dane napływają z opóźnieniem, tj. asynchronicznie.

Jest wiele ciekawych rozwiązań w GWT, ale poza GWT RPC do stworzenia mojej gry skorzystałem również z mechanizmu Timer. Zacznijmy od przykładu.

Timer t = new Timer() {
public void run() {
label.setText("Sprawdzam, czy zasiedli wszyscy gracze");
if (moznaRozpoczacGre()) {
label.setText("Wyłączam sprawdzanie - wszyscy gotowi, można zaczynać, zatem rozpoczynam grę");
cancel();
}
}
};
t.scheduleRepeating(5000); // uruchamiaj co 5 sekund

gdzie metoda moznaRozpoczacGre prezentuje się następująco:

private boolean moznaRozpoczacGre() {
// polacz sie z serwerem i sprawdz ilosc graczy
// wykonaj zdalną usługę i zwróć ilość graczy
label.setText("Ilość graczy: " + iloscGraczy);
return iloscGraczy == 2;
}

W przykładzie stworzyłem egzemplarz typu Timer i dostarczyłem własną realizację metody run, która będzie wykonywana cyklicznie, zgodnie z parametrem metody schedule lub scheduleRepeating. Różnica między nimi to czas trwania zegara i moment jego wywołania - w pierwszej zegar uruchomi się raz za zadany czas, podczas, gdy w drugim przypadku będzie wykonywał się do momentu wywołania metody cancel co zadany okres czasu. Jest to najbardziej zadowalające mnie rozwiązanie do symulacji ciągłej interakcji między klientem (przeglądarka) a serwerem.

Znajomość GWT RPC, Timer oraz przyzwyczajenie się do asynchronicznej natury GWT to klucz do tworzenia aplikacji z GWT. Reszta to szczegóły, w których trudno doszukiwać się diabła ;-) Pora na rekonesans po JPA!

07 maja 2007

IX spotkanie Warszawskiej Grupy Użytkowników Technologii Java (Warszawa-JUG)

0 komentarzy
Warszawska Grupa Użytkowników Technologii Java (Warszawa-JUG) zaprasza na IX spotkanie, które odbędzie się w nadchodzący wtorek 08.05.2007 o godzinie 18:00 w sali 4420 na Wydziale MiMUW przy ul. Banacha 2 w Warszawie.

Temat prezentacji: JBoss Ajax4jsf czyli zAJAXuj swoją aplikację
Prowadzący: Tomasz Szymański

JBoss Ajax4jsf jest produktem zarazem nowym jak i dojarzałym. Dojrzałość polega na tym, że był on od jakiegoś czasu rozwijany przez firmę Exadel. Nowość na tym, że po podpisaniu umowy partnerskiej Exadel - Red Hat, firmowany jest marką JBossa.
W prezentacji przedstawiony będzie przepis na stworzenie aplikacji korzystającej z tego projektu oraz jak zmodyfikować już istniejące. Zgodnie z tradycją nie obędzie się bez przykładów z EJB3. Zaprezentowane zostanie narzędzie Exadel Studio (który niedługo stanie się Red Hat Developer Studio) do pisania aplikacji z Ajax4jsf.

Prezentacja prowadzona będzie przez Tomka Szymańskiego, studenta V roku Wydziału Elektrycznego Politechniki Warszawskiej oraz członka zespołu JBoss.org, zajmującego się tworzeniem infrastruktury jboss.org - JBoss Labs a także Lead JBoss Wiki. Tomek interesuje się Javą od paru lat i stara się podtrzymywać wczesne nią zafascynowanie mimo rutynowego jej używania.

Planowany czas prezentacji to 1,5 godziny z 15 minutową dyskusją.

Zapraszam w imieniu Warszawa-JUG!

06 maja 2007

Tworzenie aplikacji z Google Web Toolkit i Apache Maven 2

0 komentarzy
Po przeszukaniu forów i list dyskusyjnych w końcu udało mi się doszukać wtyczki dla Apache Maven 2 (M2), która pozwala na zarządzanie projektem korzystającym z Google Web Toolkit (GWT) - maven-googlewebtoolkit2-plugin. Zdumiewający jest brak informacji na ten temat, również na polskich forach, co prawdopodobnie wynika z faktu, że większość skryptów zarządzających projektem oparta jest o bezpośrednie wykorzystanie Apache Ant (co zapewnia samo GWT podczas tworzenia projektu skryptem projectCreator) lub skorzystanie ze skryptów Ant niewprost poprzez wtyczkę M2 - maven-antrun-plugin.

W kolejnym artykule zatytułowanym Tworzenie aplikacji z Google Web Toolkit i Apache Maven 2 przedstawiłem wtyczkę maven-googlewebtoolkit2-plugin dedykowaną do zadań związanych z projektem korzystającym z GWT i zarządzanym przez M2.

Tym samym udało mi się zestawić środowisko do tworzenia aplikacji GWT pod kontrolą Apache Maven 2. Jest to kolejny krok w realizacji pomysłu zestawienia środowiska do tworzenia aplikacji GWT z Java EE przy pomocy Apache Maven 2. Kolejne artykuły o aplikacjach z GWT i usługami serwera aplikacji Java EE, z M2 w tle niebawem. Na razie idzie niezwykle gładko, zdecydowanie za dobrze.

04 maja 2007

Java Persistence - Rozdział 5.1 Konteksty trwałe

0 komentarzy
Trochę minęło od ostatniej relacji specyfikacji Java Persistence API i czym bliżej końca tym coraz ciężej. Czasami zastanawiam się, czy dany temat nie był już omawiany i czy warto jest do niego wracać, albo czy nie powinienem zaprezentować krótkiego przykładu wspomagającego. Cały czas marzy mi się podejście do egzaminu z SCBCD 5, a tam mimo wielu pytań z JPA są również z EJB 3.0. Nie mogę się już doczekać, kiedy uda mi się zestawić środowisko z GF (GlassFish), JBAS (JBoss AS) oraz AG (Apache Geronimo), z którym będę mógł dalej rozpracowywać specyfikację EJB 3.0 i w końcu dotknąć JPA w środowisku tranzakcyjnym zarządzanym przez serwer aplikacyjny. Pora więc zamknąć temat JPA. Powracam do specyfikacji od lektury podrozdziału 5.1 Konteksty trwałe.

Okazuje się, że i w specyfikacji ten sam byt ma wiele równouprawnych nazw - zarządca trwałości (ang. persistence manager) oraz zarządca encji (ang. entity manager). Oba dotyczą tego samego pojęcia w specyfikacji Java Persistence i określają klasę, która realizuje wymagania specyfikacji JPA w zakresie zarządzania cyklem życia encji. Ja również używam pojęcia dostawca trwałości/JPA dla określenia zarządcy, chociaż to pojawia się zazwyczaj w kontekście (uwaga na kontekst użycia słowa kontekst ;-)) omawiania produktu/projektu dostarczającego realizację specyfikacji JPA, niż samego jego użycia w środowisku uruchomieniowym. Coraz częściej zaczynam używać przymiotnika trwały zamiast formy rzeczownika trwałości do określenia pojęć JPA, np. kontekst trwały zamiast kontekst trwałości. Różnie bywa i czasami samemu łapię się na zamiennym ich używaniu.

5.1 Konteksty trwałe

Kontekst trwały jest zbiorem egzemplarzy encji, w którym dla dowolnego identyfikatora encji istnieje unikatowy egzemplarz encji. W ramach kontekstu, zarządca encji (trwałości/trwały) kontroluje egzemplarze encji oraz ich cykle rozwojowe. Innymi słowy, mając pojedyńczego zarządcę trwałości możemy wyróżnić wiele kontekstów trwałości, każdy z pewnymi identyfikatorami encji, które wskazują na poszczególne egzemplarze encji w odpowiednim stadium życiowym i stanie (dla dalszego skomplikowania^H^H^Huproszczenia sytuacji, nie można również zapomnieć o jednostce trwałości, która tak na prawdę grupuje klasy encji i dopiero ona jest "źródłem" kontekstów dla wybranego dostawcy trwałości).

W środowisku Java EE, tranzakcja JTA zazwyczaj angażuje wiele komponentów, tj. składa się z wielu wywołań zasobów pod auspicjami aktywnej tranzakcji. Komponenty często mogą potrzebować dostępu do tego samego kontekstu trwałości w ramach pojedyńczej tranzakcji. Aby umożliwić takie wykorzystanie zarządców trwałości w środowisku Java EE, kiedy zarządca trwałości jest przekazywany (wstrzeliwany) do komponentu bądź wyszukany w drzewie JNDI, jego kontekst trwałości jest automatycznie związywany z aktualną tranzakcją, a wszystkie referencje do EntityManager, które wskazują na tą samą jednostkę trwałości będą udostępniały ten sam kontekst trwałości w ramach danej tranzakcji. Przekazywanie kontekstu trwałości przez kontener (serwer aplikacyjny) Java EE zapobiega konieczności przekazywania referencji egzemplarzy EntityManager z jednej części aplikacji do drugiej. Zarządca trwałości, dla którego kontener (serwer aplikacyjny) zarządza kontekstem trwałości w ten sposób, nazywany jest zarządcą trwałości zarządzanym przez kontener (ang. container-managed entity manager). Cyklem życia zarządcy trwałości zarządzanym przez kontener zarządza kontener Java EE (mimo, że użycie kontener Java EE może pomagać w zrozumieniu pojęcia "zarządca trwałości zarządzany przez kontener", ja będę częściej używał serwer aplikacyjny w tym znaczeniu chyba, że będzie to powodowalo niejasności).

W bardzo rzadkich przypadkach w środowisku Java EE, aplikacje mogą korzystać z kontekstów trwałości, które są samodzielne (w sensie braku zarządzania nimi przez serwer aplikacyjny), tj. nie przekazywanych z aktualną tranzakcją JTA w ramach referencji EntityManager dla danej jednostki utrwalania. W takich przypadkach, każde wystąpienie referencji EntityManager powoduje utworzenie nowego samodzielnego (odłączonego) kontekstu trwałego, który nie jest dostępny dla innych referencji EntityManager tej samej jednostki trwałej w ramach tej samej tranzakcji. Takie użycie możliwe jest dzięki metodzie javax.persistence.EntityManagerFactory.createEntityManager. Zarządcę trwałości, którego konteksty trwałe są tworzone i niszczone w ten sposób nazywa sie zarządcą trwałości zarządzanym przez aplikację (ang. application-managed entity manager). Cyklem życia zarządcy trwałości zarządzanym przez aplikację zarządza aplikacja (metody EntityManagerFactory.createEntityManager oraz EntityManager.close lub całkowite zamknięcie fabryki zarządców za pomocą EntityManagerFactory.close).

Wsparcie dla obu typów zarządców - zarządzanych przez kontener lub aplikację - jest wymagane przez kontenery aplikacji internetowych i EJB w serwerze aplikacyjnym Java EE. W ramach kontenera EJB najczęściej korzysta się z zarządców trwałości zarządzanych przez kontener.

W środowisku Java SE oraz kontenerze klientów aplikacyjnych Java EE wymagane jest jedynie wsparcie dla zarządców trwałości zarządzanych przez aplikację (pojawia się notka - żeby nie napisać adnotacja - w specyfikacji o opcjonalnym wsparciu dla JTA w kontenerze klientów aplikacyjnych Java EE).

Dla zobrazowania tematu wydaje się koniecznym, aby kolejna odsłona relacji ze specyfikacji JPA musiała zacząć się od przykładu z jednostką trwałą w trybie JTA i RESOURCE_LOCAL z serwerem GlassFish (TopLink JPA), JBoss AS (Hibernate JPA) i Apache Geronimo (OpenJPA). Będzie to dobrą rozgrzewką do zestawienia środowiska do testowania specyfikacji EJB 3.0 z różnymi serwerami aplikacyjnymi Java EE 5. Kolejna relacja zapowiada się bardzo ciekawie.

02 maja 2007

GWT RPC - mechanizm zdalnego wywoływania procedur w GWT

0 komentarzy
Kontynuuję rozpoznawanie GWT i do mojej pierwszej aplikacji korzystającej z Java EE i GWT pozostaje poznać mechanizm spinający świat technologii klienckich - uruchamianych w przeglądarce - z serwerowymi. Na scenę wchodzi - GWT RPC. Z nim czuję, że jestem bliżej celu.

Jak wspomniałem wcześniej budowanie aplikacji GWT to programowanie w Javie stron będących mieszanką technologii klienckich (z punktu widzenia architektur wielowarstowych Java EE, w których klientem jest przeglądarka) - HTML, JavaScript oraz Ajax (przez co rozumiem - przynajmniej obecnie - zarządzanie obiektem XMLHttpRequest oraz modyfikacją DOM).

Największym wyzwaniem dla programistów Java pracującymi z technologiami serwerowymi wspierającymi dynamiczne konstruowanie interfejsu użytkownika - JSF, JSP, Servlety i in. - jest zrozumienie końcowego wyniku tworzenia aplikacji GWT - utworzenie strony HTML z "dodatkami" nie będącymi w żaden sposób związanymi z Javą (poza jej rolą jako język do ich utworzenia).

Dla uproszczenia zrozumienia roli GWT w tworzeniu aplikacji internetowej (klient = przeglądarka) wyróżnijmy etapy w jej życiu (tylko te, które są wartościowe w naszej dywagacji o GWT):
  1. Programowanie - etap, w którym programista pisze kod źródłowy w Javie.
  2. Kompilacja - etap, w którym kod źródłowy jest zmieniany na postać akceptowaną przez środowisko uruchomieniowe (bajtkod lub HTML).
  3. Uruchomienie - etap, w którym bajtkod produkuje treść wysyłaną do przeglądarki.
Co łączy tworzenie aplikacji w Java EE i GWT to fakt, że są one dedykowane dla środowiska uruchomieniowego, w którym główną rolę odgrywa język Java. Kod źródłowy tworzony jest w Javie i to jest jedyna część wspólna. Pozostałe etapy są już inne. I tutaj właśnie tkwi problem w moim wcześniejszym zrozumieniu GWT. W jego przypadku, postacią uruchomieniową kodu źródłowego jest HTML podczas, gdy w technologiach Java EE jest to bajtkod (bo tak kończy program napisany w Javie). Oczywiście w efekcie i GWT i Java EE "produkuje" HTML, ale różnica tkwi w momencie jego dostępności. W przypadku GWT, HTML pojawia się już w kroku 2., podczas gdy w Java EE jest materializowany dopiero w etapie 3. - uruchomieniowym.

Pamiętając o różnicach między GWT a Java EE, tworzenie aplikacji będących mieszanką ich obu nie powinno stanowić problemu. Jak HTML (będący postacią wynikową kompilacji aplikacji GWT) mógłby zostać wkomponowany w aplikację Java EE każdy wie. Możemy zmodyfikować HTML na stronę JSP, która z kolei korzysta z innych technologii, jednakże ostatecznie struktura wynikowa strony przesyłanej do przeglądarki musi spełniać wymagania GWT. Nie przekreśla to możliwości skorzystania z innych rozwiązań, np. JSF (choć na chwilę obecną nie wiem jak miałoby to wyglądać praktycznie, a jedynie teoretycznie).

Kiedy tworzymy aplikację GWT mamy do dyspozycji kilka elementów składowych podczas jej tworzenia (etap programowanie), które były już przedstawiane poprzednio, jednakże warto o nich wspomnieć ponownie:
  • entry-point - punkt dostępowy - klasa realizująca interfejs EntryPoint, która docelowo stanie się stroną HTML. Jest to część kliencka GWT. Może istnieć wiele punktów dostępowych.
  • servlet - klasa rozszerzająca klasę RemoteServiceServlet, która jest definicją servletu - części aplikacji wykonywanej po stronie serwera (w sensie GWT i Java EE) i wywoływanej przez mechanizm GWT RPC. Klasa, z której dziedziczy servlet jest jedynie klasą pochodną znanej z Java EE klasy javax.servlet.http.HttpServlet i obsługuje mechanizm serializacji.
Wspomniany mechanizm zdalnego wywoływania procedur GWT (ang. GWT Remote Procedure Call lub w skrócie GWT RPC) to sposób na zdalne wywoływanie części serwerowej aplikacji w GWT. Podobnie jak tradycyjna aplikacja desktopowa ma możliwość pozyskiwania danych z różnych zewnętrznych źródeł, tak i aplikacja GWT ma taką możliwość. Nie jest to do końca równoważne, gdyż aplikacja GWT działa w ramach przeglądarki i obowiązuje ją zasada łączenia się jedynie z serwerem, z którego pochodzi, jednakże sama koncepcja pozyskiwania danych jest analogiczna. Sposób działania aplikacji GWT jest łudząco podobny do działania tradycyjnej aplikacji desktopowej. Za pomocą GWT RPC mamy możliwość przekazywania obiektów do/z serwera poprzez HTTP - proces serializacji. W skrócie wykorzystanie mechanizmu RPC w aplikacji sprowadza się do definicji servletu w pliku konfiguracyjnym aplikacji, definicji oraz realizacji interfejsu i ostatecznie na wywołaniu usługi z aplikacji.

Pora na krótką demonstrację teorii w praktyce, co powinno znacząco uprościć zrozumienie tematu. Stworzę aplikację WitajSwiecieGWT.

Definiujemy zdalną usługę - część serwerową aplikacji - w deskryptorze modułu - WitajSwiecieGWT.gwt.xml za pomocą elementu servlet.

<module>
<inherits name='com.google.gwt.user.User'/>

<entry-point class='pl.jaceklaskowski.gwt.witajswiecie.client.WitajSwiecieGWT'/>

<servlet path="/uslugaZdalna" class="pl.jaceklaskowski.gwt.witajswiecie.server.UslugaZdalnaImpl"/>
</module>

W punkcie dostępowym aplikacji - element entry-point - wywołana zostaje usługa zdalna jako wynik wciśnięcia przycisku.

package pl.jaceklaskowski.gwt.witajswiecie.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class WitajSwiecieGWT implements EntryPoint {
public void onModuleLoad() {

final Button b = new Button("Przycisnij");
b.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
UslugaZdalnaAsync remoteService = UslugaZdalna.App.getInstance();
remoteService.wykonajZadanieNaSerwerze("Jacek", "Laskowski", new AsyncCallback() {
public void onSuccess(Object result) {
b.setText("Zakonczono poprawnie - wynik: " + result);
}

public void onFailure(Throwable caught) {
b.setText("Zakonczono niepoprawnie");
caught.printStackTrace();
}
});
}
});
RootPanel.get().add(b);
}
}

Klasa reprezentująca zdalną usługę - UsługaZdalna - to jedynie definicja interfejsu (w przykładzie mamy do dyspozycji pojedyńczą metodę wykonajZadanieNaSerwerze).

Dla usprawnienia programowania z GWT IntelliJ IDEA dostarcza metodę pomocniczą do tworzenia egzemplarzy UslugaZdalna.

package pl.jaceklaskowski.gwt.witajswiecie.client;

import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.core.client.GWT;

public interface UslugaZdalna extends RemoteService {

public String wykonajZadanieNaSerwerze(String imie, String nazwisko);

/**
* Metoda pomocnicza utworzona przez IntelliJ IDEA
* Use UslugaZdalna.App.getInstance() to access static instance of NowyRemoteServiceAsync
*/
public static class App {
private static UslugaZdalnaAsync ourInstance = null;

public static synchronized UslugaZdalnaAsync getInstance() {
if (ourInstance == null) {
ourInstance = (UslugaZdalnaAsync) GWT.create(UslugaZdalna.class);
((ServiceDefTarget) ourInstance).setServiceEntryPoint(GWT.getModuleBaseURL() + "uslugaZdalna");
}
return ourInstance;
}
}
}

Zgodnie z wymaganiem GWT, tworzony egzemplarz musi być rzutowany na typ UslugaZdalnaAsync.

package pl.jaceklaskowski.gwt.witajswiecie.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface UslugaZdalnaAsync {
void wykonajZadanieNaSerwerze(String imie, String nazwisko, AsyncCallback async);
}

Aż w końcu należałoby zapoznać się z implementacją interfejsów w postaci usługi zdalnej wykonywanej na serwerze - klasa UslugaZdalnaImpl. Tutaj jedynym ograniczeniem jest nasza wyobraźnia. Wszystko wywoływane w ramach klasy jest wykonywane na serwerze i nie podlega obsłudze GWT. To jest miejsce pozyskiwania danych, np. poprzez JPA.

package pl.jaceklaskowski.gwt.witajswiecie.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import pl.jaceklaskowski.gwt.witajswiecie.client.UslugaZdalna;

public class UslugaZdalnaImpl extends RemoteServiceServlet implements UslugaZdalna {
public String wykonajZadanieNaSerwerze(String imie, String nazwisko) {
System.out.println("UslugaZdalnaImpl.wykonajZadanieNaSerwerze");

// Tutaj możnaby oczekiwać bardziej wyrafinowanego przetwarzania
return imie + " " + nazwisko;
}
}

Ważne, aby pamiętać, że mimo ograniczenia na konstrukcje językowe Java w GWT w części klienckiej (które muszą odpowiadać tym w Java SE 1.4 i wcześniejszym), część serwerowa nie leży w gestii zainteresowania GWT (poza udostępnieniem mechanizmu RPC) i może być tworzona z dowolnymi mechanizmami i technologiami Java SE czy EE.

Tworzenie usług zdalnych w GWT przypomina tworzenie komponentów EJB w wersji 2.1 i poprzednich, gdzie należało zdefiniować coś na kształt interfejsu biznesowego, interfejs domowy i właściwą klasę komponentu wszystko spięte za pomocą deskryptora ejb-jar.xml. Brakuje usprawnień, do których zdążyłem sie już przyzwyczaić pracując z Java EE 5, m.in. tworzenie komponentów (czy usług) w tradycyjny sposób - interfejs oraz klasa realizująca z adnotacjami. Może nadchodząca wersja GWT 2.0 będzie sprytniejsza?!

Na zakończenie strona HTML uruchamiająca GWT.

<html>
<head>
<title>Aplikacja WitajSwiecieGWT</title>
<meta name='gwt:module' content='pl.jaceklaskowski.gwt.witajswiecie.WitajSwiecieGWT'>
<link rel=stylesheet href="WitajSwiecieGWT.css">
</head>
<body>
<script language="javascript" src="gwt.js"></script>
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
<h1>Aplikacja WitajSwiecieGWT</h1>
</body>
</html>

Cały moduł gotowy do uruchomienia można pobrać jako WitajSwiecieGWT.zip. Wymagane jest jedynie zainstalowanie GWT (i posiadanie MS Windows do uruchomienia skryptów ;-)).

Na zakończenie, ważna uwaga w kontekście tworzenia aplikacji GWT w środowisku IntelliJ IDEA 6.0 - Enable "before launching" steps. Podczas uruchamiania projektu należy włączyć tę opcję, gdyż w przeciwnym przypadku część serwerowa nie zostanie zbudowana i uruchomienie mechanizmów GWT RPC zakończy się komunikatem błędu, który może prezentować się w ten sposób:


co wynika wyłącznie z niedostępności skompilowanej klasy na ścieżce klas.

Przy okazji rozwiązywania problemu (co okazało się być wyłącznie związane z samym posługiwaniem się IDEA) zauważyłem, że próbowałem korzystać z tradycyjnych metod tworząc aplikację GWT, np. caught.printStackTrace(), czy pomysłami w stylu instalacja Java SE 1.4 (co szczęśliwie zakończyło się przypomnieniem, że Java SE 5 ma możliwość kompilacji i uruchomienia z obniżoną wersją języka). Zauważam, że GWT wymaga pewnego oderwania się od dotychczasowych przyzwyczajeń i to, co było dobre w innych serwerowych technologiach tu może nie być najwłaściwszym podejściem. Ważne, aby podczas programowania z GWT korzystać z narzędzi, które są oferowane z GWT - GWT Development Shell z opcją śledzenia wykonywania programów (debug) czy podświetlenia linii z błędem, która zostanie uzupełniona o informacje pomocne w rozwiązywaniu aktualnego problemu (jak widać na powyższym zrzucie ekranu). Niestety nad rozwiązaniem tego (a przy okazji i zdobywaniem kolejnych informacji o GWT) spędziłem bodajże około 2 dni (!) Czasami warto zapomnieć o tym co się wie i zacząć wszystko od nowa, bo doświadczenie to często niepotrzebny bagaż (doświadczyłem tego na własnej skórze, kiedy uczyłem się, początkowo nieosiągalnej, sztuki żonglowania).