poniedziałek, 25 października 2010

Wrażenia po CodeRetreat we Wrocławiu

W sobotę 23.10.2010 odbyło się pierwsze otwarte CodeRetreat w Polsce. Wyszło bardzo dobrze (nasuwa mi się tu pewne słowo „potęgujące emocje”, którego jednak nie chcę użyć ze względu na charakter bloga). Wyłącznym sponsorem była firma Tieto,  dzięki której całe wydarzenie miało taki a nie inny przebieg. Ale zacznijmy od początku.

Czym jest CodeRetreat? Jest to spotkanie warsztatowe, dla programistów, którzy w trakcie trwania ćwiczą programowanie w parach, tworzenie kodu wysokiej jakości i inne dobre praktyki. Spotkanie składa się z kilku sesji podczas których wspólnie tworzy się kod w parach. Nie chodzi o to aby, napisać jakiś działający program, tylko ćwiczyć pewne elementy programistycznego rzemiosła. Ktoś to ładnie porównał do wytwarzania garnków. Nie robimy konkretnego garnka, tylko uczymy się w jaki sposób ugniatać glinę. Więcej o zasadach CodeRetreat można przeczytać  na stronie CodeRetreat Wrocław  i na blogu Herbi’ego.

Inicjatorem całego zamieszania był Grzegorz Dziemidowicz który rzucił pomysł, który został podłapany przez Wrocław JUG i Grupę Kunszt. CodeRetreat z założenia powinien być bezpłatny i tak też było. Organizatorzy wykonali kawał dobrej roboty. Brawo!

Wydarzenie odbywało się w Hotelu Patio we Wrocławiu. O 8.00 rano była rejestracja uczestników. Przyszło 51 z 60 zarejestrowanych osób, mimo wielu e-maili proszących o potwierdzenie przybycia. Nie przyszedł nikt z listy rezerwowej, a szkoda, bo było jeszcze trochę miejsca i nawet posłuchanie / przypatrywanie temu co się dzieje mogło by być całkiem pouczające. Po rejestracji można było się rozłożyć z komputerem na jednej z dwóch sal. Około 8.30 było przywitanie, parę słów o sponsorze i wytłumaczenie zasad. Następnie dobraliśmy się w pary i o 9.00 zaczęliśmy kodować. Pretekstem do pisania była Gra w życie.

Na początkowych sesjach trafiałem na początkujących w temacie TDD (które między innymi ćwiczyliśmy), wiec dzieliłem się swoją wiedzą. Nie znaczy to, że nic z tego nie wyniosłem, bo zawsze można się choćby nowego skrótu klawiaturowego nauczyć, lub innego toku myślenia. Później trafiałem na osoby z podobnym do mojego poziomem rozeznania tematu i można było już coś konkretniejszego poćwiczyć. Po każdej sesji kodowania był czas na retrospektywę, podczas której dzieliliśmy się swoimi spostrzeżeniami i odczuciami podczas wspólnego kodowania.

Po 3ciej sesji był obiad i dłuższa przerwa. Jedzenie było dobre i z deserem, przygotowane przez hotel. Po przerwie Szczepan Faber prezentował jedną ze szkół mokowania w testach. Dzięki temu w kolejnych sesjach postanowiłem skorzystać z mockito i w końcu miałem okazję je poznać (przynajmniej podstawy). Na przyszłość mogła by być jeszcze jedna tego typu prezentacja.

Całość skończyła się planowo przed 17.00. Pod koniec było losowanie gadżetów od sponsora, podsumowanie i dyskusja na temat co się podobało, a co nie. Był jeszcze pomysł zostania i zrobienia jeszcze jednej sesji, ale chętni się nie znaleźli. Sześć sesji kodowania okazało się wystarczające i ja pod koniec miałem już dość.

Wieczorem była jeszcze impreza integracyjna w klubie Ambra (podziemia hotelu Patio). Było dużo piwa do odebrania przy barze, więcej niż nasza moc przerobowa mogła obsłużyć. Na imprezie można było spokojnie porozmawiać o sprawach organizacyjnych, planach na przyszłość itp. To był bardzo udany dzień i wieczór.

W trakcie całego dnia poznałem różne podejścia w jaki sposób można ugryźć dany problem i nie sądziłem, że na tyle sposobów można go rozwiązać. Stwierdziłem również, że nie mógłbym razem z Szymonem w parze pracować. Tzn. On twierdzi, że się da, tylko musielibyśmy trochę spoważnieć i bardziej profesjonalnie do tego podejść. Wydaje mi się, że tak by musiało być.

Co ciekawsze jeszcze to, że podczas sesji gdzie trzeba było pisać kod na maks 4 linijki było bardzo ciężko. To ograniczenie bardzo utrudniało myślenie i pisanie. Jednak podczas kolejnego innego ćwiczenia, po fazie refaktoryzacji, udało nam się osiągnąć 4linijkowe metody, przy czym to nie było celem ćwiczenia, tylko tak wyszło samo z siebie naturalnie. Niektórzy na retrospektywie mówili, że udawało im się niemal wszystkie rzeczy na raz otrzymywać i nie sprawiało to problemu. Trzeba dążyć do takiego ideału.

Poniżej co udało mi się poćwiczyć / poznać na CodeRetreat:
  • Programowanie w parach
  • TDD
  • Mockito
  • Ping pong pair programming
  • Tworzenie kodu maks 4 linijki na metodę i 4 metody na klasę
  • Pisanie kodu bez if’ów
  • Pisane bez użycia myszki

Podczas warsztatów nie udało mi się wszystkich proponowanych technik poćwiczyć, ale będę w wolnej chwili próbował rozwinąć temat. Moja lista TODO:
  • Napisanie gry w życie bez używania liczb
  • Szersze poznanie Mockito i innych tego typu wynalazków
  • Poćwiczyć pisanie bez if’ów
  • Więcej skrótów klawiaturowych poznać
  • Pisanie z wykorzystaniem obiektów immutable

Podsumowując polecam bardzo innym uczestnictwo w tego typu warsztatach. Nawet osoby mające na co dzień możliwość programowania w parach znajdą coś dla siebie (nowe osoby do pary, nowe spojrzenie na pewne sprawy). Również osoby kompletnie zielone z TDD i z programowania w parach mogą bardzo wiele się nauczyć dzięki CodeRetreat. Na razie nie ma jeszcze konkretnych planów na kolejną taką imprezę, ale mam nadzieję, że jeszcze kiedyś będę mógł uczestniczyć w tego typu wydarzeniu.

poniedziałek, 11 października 2010

Wrażenia po Java Developers’ Day 2010 w Krakowie


Dzisiaj podzielę się z Wami moimi wrażeniami po konferencji Java Developers’ Day w Krakowie. Odbyła się ona w dniach 7-8 października 2010 na terenie Uniwersytetu Ekonomicznego w Krakowie. Była to już 5ta edycja tej konferencji i było co świętować (ale o tym później). Organizatorem była fundacja PROIDEA, która również organizuje 4Developers w Poznaniu. Przygotowana była jedna ścieżka wykładów i na drugi dzień była możliwość uczestniczenia w warsztatach (na które trzeba było się wcześniej zgłosić). Ale od początku…

Podróż do Krakowa rozpocząłem w czwartek rano, czyli w pierwszy dzień konferencji. Razem z Szymonem wyjechaliśmy samochodem z Wrocławia chwile po 6.00. Droga minęła całkiem szybko (dobrze że mamy autostrade) i przyjemnie. Chwilami mieliśmy okazję podziwiać wschód słońca, (o ile inne przeszkody terenowe nam to umożliwiały). Całkiem ładny widok, na który zawsze mi było ciężko wstać (bym chyba musiał się nie kłaść). Zdjęcie poniżej.



Do Grodu Kraka zajechaliśmy około 9. Zdążyliśmy więc na rejestrację i powitanie uczestników. Zaraz po 5cio minutowym przywitaniu zaczął sie pierwszy wykład: RESTful Java Billa Brukea z RedHat'a. Troszkę słabo było słychać, ale nie było tragicznie. Prelegent zachwalał zalety RESTowych interfejsów. Dzięki temu, że „http is everywere” w każdym języku programowania możemy dobrać się do tego interfejsu. Dzięki operacjom dostępnych w tym interfejsie: GET, POST, PUT, DELETE można łatwo napisać prostego CRUD’a. Bill również pokazywał w jaki sposób rozszerzyć ten interfejs, do bardziej skomplikowanych operacji. Ponadto dzięki temu, że są to adresy URI, administratorzy mogą łatwo zablokować / kontrolować konkretne odwołania. W Javie do pracy z RESTem Bill proponował JAX-RS znany inaczej jako JSR-311. Tam za pomocą adnotacji, mówi się która metoda ma być wywołana, gdy przyjdzie dane żądanie. Więcej można znaleźć w książce ostatnio wydanej przez prelegenta: RESTful Java with JAX-RS.

Po prezentacji była krótka przerwa, aby rozprostować nogi i coś się napić (soczku lub kawy oczywiście). Rozprostowanie nóg było konieczne, ponieważ trybuna na której siedziała widownia (ogółem wykłady odbywały się na sali gimnastycznej z rozkładaną trybuną), była niewygodna i było mało miejsca na nogi. Na kolejnych prezentacjach już starałem się siadać w pierwszych rzędach, gdzie były dostawione wygodne krzesełka i można było się spokojnie wyciągnąć. Dodatkowo uważam, że przerwy były za krótkie (5 minut). Wychodzenie z sali trwało trochę czasu i ledwo człowiek zdążył nalać sobie soczek i już musiał wracać. Rada na przyszłość: dłuższe przerwy (co najmniej 10 minut).

Dużym plusem było to, że wykłady się nie przeciągały, a jak już dochodziło do takiej sytuacji to były grzecznie, w kulturalny sposób przerywane przez organizatorów. Fajny był również monitor gdzieś na dole, który pokazywał prelegentowi czas. Wielką wagę przywiązuję do tego, aby się wpasowywać w wyznaczony czas podczas prezentacji. Wiem, że nie jest to łatwe, ale pewnymi ćwiczeniami można to osiągnąć. No i taki czasomierz jest wówczas bardzo pomocny, gdyż można coś skrócić, lub dodać do wystąpienia.

Kolejną prezentacją było wystąpienie Angeliki Langer: Programowanie Java w dobie procesorów wielordzeniowych. Wykład był po angielsku (zresztą jak poprzedni), tylko że tym razem prelegentka mówiła tak szybko jak O.S.T.R. podczas freestyle’u (kto miał okazję posłuchać na żywo Ostrego ten wie o co chodzi). Pani bardzo szybko przeskakiwała na kolejne slajdy (czasem nie było czasu aby dokładnie go przeczytać) i było one bardzo wypełnione tekstem. Był omawiany temat modelu pamięci w Javie i jak to ma się do pamięci fizycznej i przetwarzania wieloprocesorowego. Były również omawiane działanie słowa kluczowego volatile i niektórych aspektów z nim związanych. Ogółem brakowało mi jakiś konkretnych przykładów, części praktycznej prezentacji.

Podczas niektórych prezentacji można było w tle, gdzieś za ścianą w postaci kurtyny usłyszeć, odbijające się piłki do kosza, co przypominało, że jesteśmy w sali gimnastycznej. Na szczęście było to jeszcze do przeżycia i nie zagłuszało tak bardzo prelegentów.

Kolejną prezentacją było: Testowanie wydajnościowe aplikacji Java Enterprise Jarosława Błąd (nie wiem jak powinienem odmienić to nazwisko, sory). Prezentacja traktowała właściwie o wszystkim i o niczym. Prelegent opowiadał jak to należy przeprowadzać testy wydajnościowe, że najpierw trzeba zdefiniować cel (co chcemy zbadać i wynik jaki chcemy osiągnąć), później przygotować przypadki testowe i testować system pod różnym obciążeniem. Wiążą się z tym pewne problemy: rzadko kiedy mamy infrastrukturę testową, taką samą jak infrastruktura na produkcji, klient nie zezwala na czasowe wyłączenie usługi w celu testów itd. Maszyna która generuje ruch sieciowy i zapytania do usługi musi być osobną maszyną, a nie tą samą, na której to wszystko się odbywa. Problemem nie jest wygenerowanie ileś tam zapytań do serwera, problemem jest przyjęcie tych danych od usługi, dlatego maszyna testująca musi być „stosunkowo blisko” maszyny testowanej. Były również omawiane inne problemy i wąskie gardła testowania. Brakowało (znów) trochę praktyki, chociażby w wymienienia narzędzi z których można by korzystać. Dodatkowo dodam, że prelegent był przedstawicielem jednego ze sponsorów, firmy e-point.

Po prezentacji była godzinna przerwa obiadowa. Obiad był wliczony w cenę konferencji i był smaczny. Do wyboru były dwa rodzaje mięsa, ziemniaki, makaron i surówki. Było również stoisko wegetariańskie, dla chętnych. Oczywiście przez cały czas konferencji były dostępne kawa, herbata, soki i małe przekąski.

Po obiedzie była najlepsza (według mnie) prezentacja z całej konferencji. Ted Neward przedstawił Przewodnik po programowaniu funkcyjnym w Javie dla zapracowanego developera. Wielkim zaskoczeniem było używanie notatnika w celu tworzenia kodu na żywo, ręczne dopisywanie importów i kompilacja za pomocą javac. WOW! Ted pokazał w jaki sposób programując w Javie tworzyć kod który będzie posiadał cechy kodu funkcyjnego. Czyli stosowanie niemodyfikowalnych obiektów, metod (funkcji) filtrujących itd. Spodziewałem się, że Ted pokaże, że w Javie kod mu zajął 50 linijek, a za pomocą jakiegoś języka funkcyjnego można to zrobić w 5 linijek. Dla tego temat „…dla zapracowanego developera” został bardzo dobrze tutaj dobrany. Może na wykładzie nie było dużo pokazane, ale w jakim stylu! Brawo!

Po więcej na temat programowania funkcyjnego można było się zapisać na warsztat dnia drugiego. Kolega Szymon był na nim i był bardzo zadowolony. Ted bardzo skacze po różnych językach (w pierwszym dniu miał koszulkę z napisem „I love C#”) i bardzo dobrze się w nich orientuje. Warsztat był już na temat Scali, i pokazane było już więcej przykładów.

Kolejną prezentacją było: Flex z przodu, Java z tyłu: wieloekranowe Bogate Aplikacje Internetowe z wykorzystaniem technologii Adobe AIR i Flex Piotra Walczyszyna. Jest to pracownik firmy Adobe Systems Inc. A więc jednego ze sponsorów. Na jego prezentacji miałem okazje być już podczas 4Developers 2010, występował również na Javarsovii 2010 (tam mnie nie było) no i teraz. Generalnie wiedziałem już czym jest Flex i Adobe AIR. Wystąpienie było po angielsku (ktoś z widowni to zaproponował) i bardzo miło się go słuchało. Piotrek przedstawił aplikację komórkową, którą najpierw zrobił zdjęcie, wysłał je do usługi i na podstawie danych geolokalizacyjnych na komputerze, w przeglądarce można było zobaczyć miejsce zrobienia tego zdjęcia i samo zdjęcie. Ot taki bajer :) Zabrakło mi jednak przykładu jak aplikacja typu Flex ma się dogadać z Javą. Technologia ta jest już używana praktycznie, np. w Ministerstwie Finansów.

Kolejną prezentacją było wystąpienie gościa zagranicznego (kolejnego już) Lindy Rising: Odważne zmiany: jak realizować nowe pomysły. Linda bardzo często zadawała pytania do publiczności (choć ta może trochę słabo reagowała) i próbowała nawiązać z nią kontakt. Linda mówiła o racjonalnych i logicznych decyzjach w naszym życiu. Zadawała jednemu uczestnikowi pytania na temat jego małżeństwa. Na prezentacji tej można było się poczuć bardzo wyjątkowo, niemal jak w kościele na kazaniu, lub na wystąpieniu jakiegoś filozofa. Linda mówiła, że zmiany i rewolucje należy zaczynać od siebie i po prostu uczyć się nowych idei. Również dobre jedzenie (np. podczas spotkania w firmie) wpływa na lepsze myślenie. Ważne jest również mówienia słowa dziękuje, a że wystąpienie się trochę przedłużyło, to właśnie w tym momencie zostało powiedziane dziękuję od organizatorów i widowni :)

W tym momencie był to koniec wykładów, ale nie koniec pierwszego dania. Wraz z Szymonem udaliśmy się do holetu, aby się zameldować i chwile odpocząć. Mieliśmy blisko na miejsce, ale jazda w korku przez Kraków to jedna wielka udręka. A mówią, że to Wrocław jest zakorkowany…

Po chwili ogarnięcia ruszyliśmy na miasto. Nie byłem wcześniej w Krakowie i nie widziałem tutejszych zabytków. Co ciekawego zauważyłem to jak się pytało przechodniów o drogę, to każdy odpowiadał: „prosto, prosto”. Ja zawsze byłem przyzwyczajony do instrukcji w stylu: „to prosto, tam w lewo, na skrzyżowaniu w prawo, na rondzie prosto i potem znów w lewo…”. Fakt faktem można później zapomnieć co było na początku, ale przynajmniej widać, ze człowiek chce ci pomóc. A tu trzeba było co chwila powtarzać to samo pytanie w stylu: „Którędy na Wawel?”.

No właśnie Wawel. Trochę późno i ciemno już było i nie można było wejść. Ale w nocy całkiem ładnie wygląda. Potem jeszcze chwilę pokręciliśmy się po rynku / sukiennicach i drugie co zauważyłem w Krakowie to obecność dużej liczby „naganiaczy”. Nie wiem czy to odpowiedni termin, ale chodzi mi o ludzi którzy zapraszają do konkretnych klubów, oferując przy tym darmowego drinka, lub coś tam innego. We Wrocławiu nie ma aż tak dużo „naganiaczy”. Jako że było zimno, skorzystaliśmy z jednej z takich ofert i posiedzieliśmy trochę w ciepłym miejscu.

Później o 21.00 miała być impreza konferencyjna w klubie pauza. Udaliśmy się więc tam w wyznaczonym czasie. Na wejściu przywitały nas hostessy z konferencji i kielonek czerwonego kamikadze i talon na shot’a lub piwko :) Klub jest umieszczony w piwnicy, z minimalistycznym wystrojem (czytaj dużo tam czerwonej cegły), ale bardzo przyjemnie za to. Było również kilka konsoli Wii i PlayStation. Pograłem więc trochę w Need for Speed’a Shift i potańczyłem na macie (brakowało trochę dobrych bitów). Jako że były to 5te urodziny JDD był tort (ułożony z kieliszków wódki), który następnie został skonsumowany przez uczestników.

W drodze powrotnej do domu szukaliśmy jeszcze jakiegoś jedzenia. Głupio zrobiliśmy, że nie zjedliśmy kebabu na rynku, tylko szukaliśmy gdzieś dalej. Trafiło na telepizze, gdyż nic otwartego już nie było. Do hotelu doszliśmy na nogach (spacerek nocą) gdyż na autobus by trzeba było długo czekać.

Na drugi dzień konferencji zostaliśmy przywitani przez piękną panią pielęgniarkę, rozdającą Alka-Seltzer :)


Na szczęście nie był potrzebny. Oczywiście przez cały czas trwania konferencji, jak i imprezy integracyjnej towarzyszyły uczestnikom hostessy, pomagające w organizacji wydarzenia.

Pierwszym wykładem dnia drugiego było Apprenticeship - sposób na skuteczny rozwój zawodowy Łukasza Szydło. Jest on pracownikiem firmy Tieto Poland, a wiec kolejnego sponsora konferencji. Łukasz wspominał o modelu Modelu Dreyfusa i jeszcze paru innych. Wspomniał również o projekcie Agile Skills Project, który zebrał (prawie) wszystkie umiejętności, jakie powinien posiadać zwinny programista. Wspominał również o technikach jakie są stosowane u niego w firmie, w celu bycia bardziej "zwinnym". Wspomniał również o nadchodzącym CodeRetreat we Wrocławiu, którego jest współorganizatorem. Podczas konferencji rejestracja była jeszcze zamknięta, ruszyła jakoś w weekend, ale w poniedziałek już nie było miejsc.

Podczas drugiego dnia konferencji zorganizowano konkurs fotograficzny. Powieszono na ścianie zdjęcia z pierwszego dnia i imprezy. Celem konkursu było doklejanie komiksowych dymków do zdjęć i miały wygrać najśmieszniejsze. Rozwiązanie konkursu odbyło się na zakończenie konferencji.


Kolejnym wykładem było Aplikacje typu Comet z Lift w 15 min Łukasza Kuczera. Na prośbę publiczności było po angielsku, ale w tym wypadku wolałbym po Polsku. Tu było trochę przykładów kodu na slajdach, ale były one pisane małą czcionką i były duże odstępy między poszczególnymi linijkami. Kod był przez to nieczytelny i sam prelegent musiał patrzyć na swój laptop aby wiedzieć co tam jest napisane. Był opisywany model komunikacji aplikacji pisanych za pomocą Comet i porównywany z AJAX’em i typowym odpytywaniem serwera. Był również slajd wyjaśniający pochodzenie nazwy Comet (od proszku do prania, bo AJAX już było :) ). Prelegent bardzo szybko napisał aplikację typu czat. Co mi siś spodobało to bardzo fajnie, bezpośrednio w kodzie Scali, można umieszczać sekwencje XML’owe.

Kolejnym wykładem, na który bardzo czekałem było: Jeden rozmiar nie dla wszystkich, czyli NoSQL w środowisku Java Jarosława Pałki. Byłem już na prezentacji o tym samym tytule podczas Javarsovi 2010. Tam Jarek miał przygotowane wystąpienie na temat Neo4J, CouchDB i BerkleyDB. Zdążył tam jedynie omówić tylko Neo4j więc czekałem na resztę. No i nie zawiodłem się. Prelegent postanowił omówić wszystkie 3 przygotowane bazy danych, pomijając przykładowy kod. Wykład był po Polsku (mimo prośby z widowni o język Angielski), co mnie bardzo ucieszyło.

Jarek zanim przeszedł do omówienia kolejnych baz danych podał pewne dane statystyczne, mówiące, że obecnie w Internecie publicznie dostępnych jest 988 eksabajtów (10^18) danych. Dla porównania wszystkie książki w wersji papierowej to "zaledwie" 42 eksabajty. Powoduje to oczywiście problemy ze szybkim dostępem do tych danych, wyszukiwania i prezentowania ich użytkownikowi. Ponadto przeciętny użytkownik Internetu teraz więcej do niego wysyła / wytwarza dane (serwisy społecznościowe, blogi, twittery itp.) niż ich ściąga. Również dostęp do Internetu z komórek rośnie o wiele szybciej niż dawniej rósł dostęp do Internetu kablowego.

No dobra przejdźmy do konkretów. Na pierwszy ogień poszło CouchDB. Jest to baza danych, która przechowuje dokumenty. Każdy dokument musi posiadać pole id i numer rewizji. Dokument może być dowolny i nie trzeba definiować jego schematu. Domyślnie używa się JSON’a do zapisywania dokumentów, ale może być to również obiekt który da się serializować. Pierwsza wersja CouchDB powstała w Erlangu i co ciekawe baza ta nie korzysta z reguł ACID! Jest tam optimistic locking, czyli jak będziemy chcieli zaktualizować dokument, a w międzyczasie udało się to komuś innemu, to po prostu dostaniemy zwrócony błąd od CouchDB. No i tą sytuację trzeba będzie jakoś obsłużyć. CouchDB jest więc bardzo „luzacką” bazą - wystarczy spojrzeć na logo.

CouchDB posiada jeszcze interfejs RESTful i można dopisać metody, odpowiedzialne za sposób wyświetlania dokumentów i można w ten sposób stworzyć prostego bloga. Co ciekawe, w bazie tej pliki nie są nadpisywane, tylko nowa zawartość jest dopisywana do dysku. Powoduje to szybki zapis danych, ale powoduje również to, że baza bardzo szybko się rozrasta i trzeba czasem przeprowadzić małą optymalizację.

Następnie Jarek mówił o Neo4J. Jest to baza do przechowywania grafów, napisana w Javie. Po więcej informacji odsyłam do wpisu Javarsovia 2010.

Na koniec przedstawiono jeszcze BerkleyDB, bazę przechowującą pary klucz wartość. Została ona jakiś czas temu wykupiona przez Oralce’a (czego to oni jeszcze nie kupili?). Ma ona bardzo szybką implementację indeksowania, wykorzystywaną w Oracle database i DB2. Początkowo była ona napisana w C, a później przepisana na Jave. Wspomaga ona operacje na kolekcjach i jeśli ograniczymy naszą aplikację od kilku prostych zapytań, możemy śmiało w projekcie wykorzystać BerkleyDB.

Pod koniec wykładu miałem jeszcze sposobność zadać kilka pytań odnośnie obiektowych baz danych (w tym db4o). Chodziło mi o przyszłość rozwiązań obiektowych baz danych i w jaki sposób przekonywać menadżerów projektów do stosowania innych niż relacyjne bazy danych. Jarek odpowiedział, że najlepiej to się pozbyć menadżerów (sam pracuje na takim stanowisku), lub dokładnie przedstawić, o ile zmniejszą się koszta zastosowania innego rozwiązania niż droga relacyjna baza danych. To że programistom będzie łatwiej, nie jest argumentem dla ludzi, którzy podejmują takie decyzje w firmach.

Kolejnym wykładem było Zaawansowane zarządzanie sesjami HTTP w Oracle Coherence Michała Kuratczyka z firmy Oracle (kolejny sponsor). Wykład był bardzo ogólny, po angielsku i brakowało mi przykładu. Ciężko się słuchało i się wyłączyłem z prelekcji.

Następnie była przerwa obiadowa. Obiad był podobny do tego co było podawane wczoraj i było równie smaczne. W trakcie przerwy obiadowej miałem możliwość jeszcze porozmawiania z Jarosławem Pałką na tematy, związane z NoSQL i inne.

Następnie był wykład sponsorowany: Wipro Technologies w Europie i możliwości rozwoju na polskim rynku, prowadzony przez Cristian Rosia i Michała Szota. Była to prezentacja firmy, która siedzibę ma m.in. w najdroższym budynku we Wrocławiu w Grunwaldzki Center. Otwierają oni obecnie nowy oddział w Warszawie i szukają pracowników. Bardzo nie spodobało mi się umieszczanie takich wykładów promujących firmę w czasie kiedy mogło być coś ciekawego.

Na koniec pozostał jeszcze wykład Dług techniczny Thomasa Sundberga. W swojej prezentacji odwoływał się do słów Lindy i mówił o podobnych rzeczach co Łukasz Szydło. Ja z tej prezentacji nie zapamiętałem niczego konkretnego, gdyż ciężko mi było się na niej skupić.

Po ostatnim wykładzie było jeszcze losowanie nagród dla uczestników i podziękowania dla sponsorów. Za raz po tym wraz z Szymonem udaliśmy się do samochodu i pojechaliśmy zobaczyć Wawel. Ty razem zdążyliśmy go pobieżnie zwiedzić (część miejsc była już niedostępna). Następnie udaliśmy się w drogę powrotną do Wrocławia.

Podczas konferencji miałem jeszcze okazję poznać i zamienić kilka zdań z Tomkiem Nurkiewiczem. Byłem na Javarsovi na Jego prezentacji, odnośnie Projektu Voldemort, który zalicza się do lubianych przeze mnie rozwiązań NoSQL. Prowadzi on również blog, na który zaglądam.

Podsumowując konferencję myślałem że będzie lepiej. Co do organizacji to nie mam większych zastrzeżeń. Można zawsze zorganizować lepsze miejsce na konferencję, no ale wiadomo że to zależy od funduszy i ceny dla uczestników, jaką muszą zapłacić. Merytorycznie to za dużo było ogólnych wykładów traktujących o „wszystkim i o niczym”. Dobrze jak podczas całej konferencji jest jeden taki wykład, a nie że podczas kolejnego wystąpienia słyszy się o tym samym lub pochodnym zagadnieniu. No i bardzo teoretyczne były wykłady, mało praktyki, brakowało przykładów. Fakt faktem była zorganizowana ścieżka warsztatowa, ale to nieznaczny, że na prelekcjach nie można pokazywać / tworzyć kodu.

wtorek, 5 października 2010

Mechanizm RMI (Remote Method Invocation) w praktyce cz. 3

Dotychczas w poprzednich artykułach (część 1 i część 2) przedstawiłem jak zbudować prostą aplikację przy użyciu RMI, gdzie klient wywołuje metody serwera i serwer wywoluje metody klienta. Dotychczas wszystko uruchamialiśmy na jednej maszynie (localhost). Spróbujmy czy zadziała wcześniej napisana przez nas aplikacja przy próbie uruchomienia na dwóch komputerach.

Moje komputery to laptop o adresie 192.168.0.2 i PC 192.168.0.1. Na PCie odpalę serwer, a na laptopie klienta. Kopiujemy projekty na odpowiednie maszyny i pierwsze co to należy zmienić ścieżki dostępowe w skryptach uruchomieniowych. Bez tego otrzymamy zapewne jeden z błędów opisywanych w poprzednich artykułach.

No dobra ruszamy. Odpalamy serwer na PCie - wszystko działa (bo na nim przygotowywalem poprzednie artykuły). Odpalamy klienta na laptopie i:

javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: 192.168.0.2; nested exception is:
        java.net.ConnectException: Connection refused: connect]


Czyli aplikacja kliencka próbuje się połączyć z serwerem działającym na laptopie. Trzeba więc zmodyfikować adres pod który aplikacja próbuje się łączyć. Otwieramy więc MyClientMain.java w Eclipse i modyfikujemy linię definiującą adres URL:

String url = "rmi://192.168.0.1";

Uruchamiamy ponownie klienta i znów ten sam błąd. Jednak to nie tu szukaliśmy. Przyglądajac się bardziej stosowi wywołań, można zauważyć że wyjątek został rzucony przez MyClientMain.java:19. Zobaczmy co się tam dzieje:

context.bind("rmi:MyClientObject", myClientImpl);

Aaaa, czyli aplikacja kliencka nie może zarejestrować obiektu, gdyż rmiregistry zostało uruchomione na innej maszynie. Poświęciłem sporo czasu aby rozwikłać ten problem. Z tego co wyczytałem nie można zarejestrować obiektu, który ma być zdalny na maszynie innej niż localhost. (Moge się mylić w tym momencie, wiec jak ktoś wie lepiej niech pisze!) Po co więc ten argument w metodzie bind() do podania adresu? A no po to, że na jednej maszynie możemy mieć uruchomionych kilka rmiregistry działających na innych portach.

Wracając do aplikacji to jeśli chcemy klientem wywoływać metody serwera i serwer chce wywoływać metody klienta i ma to działać na osobnych maszynach, to musimy troche przerobić aplikację. Przede wszystkim klient musi posiadać uruchomienione własne rmiregistry, gdzie będzie wystawiał swoje zdalne obiekty. Dodatkowo serwer musi jakoś poznać IP z jakim ma się połaczyć, więc warto go mu przekazać (np. jako wywołanie zdalnej metody).

Ok najpierw zmiany u klienta. W skrypcie uruchomieniowym programu klienta należy dopisac linie uruchamiającą rmiregistry zanim uruchomimy właściwą aplikację:

start rmiregistry

Następnie w klasie MyClientMain należy zmodyfikować wywołanie zdalnej metody:

String clientAdres = InetAddress.getLocalHost().getHostAddress();
String str = myRemoteObject.getDescription(clientAdres);

Teraz argument przekazywany do metody będziemy traktować jak adres IP klienta, aby serwer wiedział z kim się połaczyć.

Teraz czas na serwer. Zmieniamy wywołanie metody szukającej zdalny obiekt klienta na następujący kod:

MyClientInt myClientInt = (MyClientInt) 
        context2.lookup("rmi://" + text + "/MyClientObject");

gdzie text jest argumentem przekazywanym do metody.

Uruchamiamy i wszystko działa poprawnie :) Możemy cieszyc się aplikacją RMI działającą na osobnych maszynach. Tym samym kończę cykl artykułów o RMI (chyba że jeszcze coś ciekawego przyjdzie mi do głowy, lub pojawi się zapotrzebowanie na rozwiązanie jakiegoś problemu). Wszelkie uwagi mile widziane.

Więcej informacji:
Mechanizm RMI (Remote Method Invocation) w praktyce cz. 1
Mechanizm RMI (Remote Method Invocation) w praktyce cz. 2

niedziela, 3 października 2010

Mechanizm RMI (Remote Method Invocation) w praktyce cz. 2

W poprzedniej części tego artykułu zatytułowanej Mechanizm RMI (Remote Method Invocation) w praktyce cz. 1 pokaząłem jak napisać prostą aplikację typu klient / serwer. Teraz spróbujemy rozbudować tamten projekt tak, aby serwer wywoływał metody klienta. Nie jest to typowa sytuacja wykorzystania tego mechanizmu, ale jest to dobra sytuacja dydaktyczna. Jako kod bazowy będziemy korzystać z projektu przygotowanego w poprzedniej części kursu.

W projekcie klienta dodajmy zdalny interfejs:

package com.blogspot.mstachniuk.example.rmiclient;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MyClientInt extends Remote {

    void showInfo(String info) throws RemoteException;
}

Nalezy pamiętać aby metody interfejsu deklarowały wyjątek RemoteException. W przeciwnym wypadku podczas tworzenia obiektu dostaniemy wyjatek: ExportException powodowany przez: IllegalArgumentException.

Stwórzmy dalej implementację tego interfejsu, analogicznie jak w poprzednim wpisie:

package com.blogspot.mstachniuk.example.rmiclient;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class MyClientImpl extends UnicastRemoteObject
        implements MyClientInt {

    private static final long serialVersionUID = 1L;

    public MyClientImpl() throws RemoteException {
        super();
    }

    @Override
    public void showInfo(String info) {
        System.out.println("Info: " + info);
    }
}

i dodajmy do MyClientMain linijki rejestrujące obiekt (zaraz po utworzeniu context'u):

MyClientImpl myClientImpl = new MyClientImpl();
context.bind("rmi:MyClientObject", myClientImpl);

Teraz należało by po stronie serwera napisać kod, który by wyołał metodę klienta. Dodajmy poniższy kod w metodzie getDescription(String text) klasy MyServerImpl tuż przed instrukcją return:

String url = "rmi://localhost/";
try {
    Context context2 = new InitialContext();
    MyClientInt myClientInt = (MyClientInt) 
            context2.lookup(url + "MyClientObject");
    myClientInt.showInfo("Info od serwera");
} catch(Exception e) {
    e.printStackTrace();
}

Wówczas gdy klient wywoła zdalną metodę getDescription() serwer wywoła metodę klienta i dopiero zwróci wynik do klienta. Nie jest to może najszczęśliwszy przykład, al chodzi tu o zaprezentowanie działania mechanizmu. Jako że serwer jest uruchamiany wcześniej niż kod klienta, to serwer musi poczekać na moment w którym zdalny obiekt klienta będzie już dostępny. Dlatego próbę wywołania zdalnej metody klienta umieściłem w metodzie getDescription().

No dobra, importujemy to czego potrzebuje nasz wklejony kod (swoją drogą Eclipse kilkakrotnie w tym momencie mi się zawiesiło) i kopiujemy odpowiednie interfejsy (tj. MyClientInt). Następnie uruchamiamy i otrzymujemy masę wyjątków po stronie klienta. Trzeba dodać do skryptu uruchamiającego informację o codebase:

-Djava.rmi.server.codebase=file:/D:/Java_programy/RMIClient/bin/

Teraz otrzymujemy dwa wyjątki - po stronie klienta AccessControlException, a po stronie serwera UnmarshalException, spowodowany przez EOFException.

Zmodyfikujmy więc spowrotem plik polityki client.policy w projekcie klienta, aby zezwolić na wszystko:

grant {
 permission java.security.AllPermission;
};

Uruchamiamy i działa:) Czyli zabezpieczenia nie pozwalały na odpowiednią komunikację. Chcąc ustawić tylko tyle ile musimy, powyższy plik musimy zmodyfikować w następujący sposób:

grant {
 permission java.net.SocketPermission
 "*:1024-65535", "connect, accept";
};

Napiszę jeszcze trochę o wyjątkach. W przypadku jabyśmy podali zły adres zdalnego obiektu otrzymalibyśmy  wyjątek javax.naming.NoInitialContextException. W przypadku gdy nazwa na zdalny obiekt jest zajęta (np. gdy odpalimy dwie instancje klienta), otrzymamy javax.naming.NameAlreadyBoundException. Istnieje jeszcze pewnie wiele sposobów aby coś zepsuć.

Jak widać technologia RMI daje możliwość łatwego wywoływania zdalnych metod w kodzie, tylko że trzeba się trochę namęczyć z całą otoczką uruchamiania tych aplikacji. Przedstawione tutaj rozwiązanie nie jest idealne, o czym napiszę w kolejnej części kursu.

Więcej informacji:
Mechanizm RMI (Remote Method Invocation) w praktyce cz. 1

sobota, 2 października 2010

Mechanizm RMI (Remote Method Invocation) w praktyce cz. 1

Dzisiaj chciałbym Wam przedstawić mechanizm wywoływania zdalnych metod (ang. Remote Method Invocation, RMI). Spotkałem się z nim podczas studiów na jednym z przedmiotów. Pamiętam, że znajomi męczyli się bardzo, aby napisać prostą aplikację wykorzystującą RMI. Narzekali przy tym, że to niewykorzystywane jest, że są nowsze, lepsze metody realizacji podobnej funkcjonalności, że .NET itd. Jako że zaczął się niedawno rok akademicki mam nadzieję, że moje wywody pomogą niektórym w ogarnięciu tematu.

No dobra, ale przejdźmy do rzeczy. Mechanizm RMI dodano do Javy w wersji 1.1. W późniejszych wersjach pojawiały się jakieś modyfikacje tego mechanizmu, ułatwiające trochę pisanie. My napiszemy prostą aplikację typu klient / serwer. Klient będzie miał za zadanie wywołać metodę serwera. Projekt wykonam w środowisku Eclipse (choć nie jest to moje ulubione środowisko).

Tworzymy nowy (Ctrl+N) Java Project w Eclipse, jako Project name podajemy np. RMIServer. Dodatkowo zaznaczę, że projekt trzymam w katalogu (czy też mam tak ustawione Workspace): D:\Java_programy\ - przyda nam się to na później. Zaczniemy od zdefiniowania interfejsu który nasz serwer będzie udostępniać na zewnątrz. Klikamy na src w projekcie prawym przyciskiem myszy i New -> Interface. Wpisujemy nazwę pakietu (w moim przypadku: com.blogspot.mstachniuk.example.rmiserver) i nazwę interfejsu - ja dałem: MyServerInt. Przyrostek Int pochodzi od Interface.

W utworzonym interfejsie definiujemy metody, które będziemy udostępniać na naszym serwerze. Ja utworzyłem jedną metodę, która jako argument przyjmuje String i również go zwraca. W przypadku obiektów sprawa się trochę komplikuje, więc nie będę jej opisywał. Nasz interfejs musi rozszerzać inny interfejs: java.rmi.Remote. Dodatkowo każda metoda musi mieć zadeklarowane, że rzuca wyjątek java.rmi.RemoteException. Jest on rzucany, przy niepowodzeniu operacji wywołania zdalnej metody, przy zerwaniu połączenia itp. Poniżej kod mojego opisanego interfejsu:



No dobra, to teraz napiszmy kod, który będzie implementował przedstawioną powyżej funkcjonalność. Utwórzmy klasę MyServerImpl (przyrostek Impl od Implementation). Będzie on rozszerzał klasę java.rmi.server.UnicastRemoteObject - dla wygody. Można też bez tego - tylko wtedy sami musimy utworzyć obiekt serwera. Nasza klasa dodatkowo będzie implementować nasz wcześniej zdefiniowany interfejs. Przykładowy kod poniżej:



Linia definująca pole serialVersionUID jest do tego aby środowisko Eclipse dało nam spokój (tzn. aby nie wyswietlał sie żółty wykrzyknik przy nazwie klasy). Bez tego też zadziała. Wujek Bob w książce "Czysty kod. Podręcznik dobrego programisty" zaleca jednak aby samemu nie deklarować pola serialVersionUID, a pozwolić kompilatorowi na jego automatyczne wygenerowanie. Ma to znaczenie przy ewentualnej deserializacji różnych wersji klas.

Konstruktor jest wymagany i musi deklarować wyjatek RemoteException, gdyż konstruktory UnicastRemoteObject również deklarują ten wyjątek i może się zdarzyć, że będzie problem z utworzeniem zdalnego obiektu.

Chcąc wywołać zdalną metodę, musimy zarejestrować naszą klasę w rejestrze RMI. Posłuży nam do tego klasa MyServerMain. Utwórzmy więc taką klasę w naszym projekcie. To co musimy w niej zrobić to zarejestrować nasz obiekt pod jakąś nazwą. W tym przypadku będzie to nawa MyRemoteObject i obiekt klasy MyServerImpl. Kod poniżej:



Teraz już możemy spróbować uruchomić nasz serwer. Wciśnięcie Run (Ctrl+F11) w Eclipse powoduje wyjątki. Trzeba skorzystać z linii poleceń. Będę posługiwał się bezpośrednio komendami (Windows) aby lepiej można było zrozumieć co się w aplikacji dzieje.

Na początek utówrzmy sobie plik runServer.bat w katalogu projektu (u mnie: D:\Java_programy\RMIServer). Umieśćmy w nim taką zawartość:



Na początek należy odpalić rmiregistry, czyli rejestr początkowy RMI. Poprzedzmay go komendą start, aby otworzył nam się w osobnym oknie i kolejna komenda mogła się wykonać. Następnie uruchamiamy już naszą aplikację. Podajemy flagę -cp aby wskazać gdzie nasze skompilowane klasy leżą i następnie nazwę klasy (wraz z pakietem).

I tu zaczyuna sie pierwszy problem. Dostajemy spory stos wyjątków. Pośród nich można dostrzeć:



Rozwiązanie jakie kiedyś znalazłem, to można ustawić właściwość (ang. Property) java.rmi.server.codebase. Chodzi o to, że rmiregistry nie wie gdzie jest bytecode, z którego ma korzystać i trzeba mu to jakoś powiedzieć.

Wspomniane property możemy ustawić na 2 sposoby. Pierwszy z nich to wywołanie System.setProperty(key, value), a drugi to odpowiednie wywołanie z lini poleceń:
-Dkey=value

Zmodyfikujmy więc nasz skryp uruchomienowy:



Dobra, działa (na razie). Teraz sie zajmijmy klientem. Musi on korzystać z Menadzera bezpieczeństwa RMI, jeśli chcemy ładować kod ze zdalnego serwera. Dla projektu klienta tworzymy osobny projekt o nazwie RMIClient. Tworzymy w nim pakiet (w moim przypadku com.blogspot.mstachniuk.example.rmiclient) i umieszczamy w nim nową klasę MyClientMain. Po zainicjowaniu menażera bezpieczeństwa, musimy się dostać do zdalnego obiektu. Przykładowy kod klasy klienta poniżej:




Aby Eclipse nam nie krzyczało, że nie wie co to MyServerInt, skopiujmy więc ten plik z projektu serwera do projektu klienta, pamiętając aby umieścić go w tym samym pakiecie (nazwa pakietu jest nierozłączną nazwą klasy). Gdybyśmy plik umiescili w innym pakiecie lub zmienili nazwę klasy otrzymalibyśmy wyjątek ClassCastException.

Sprawdzamy czy coś działa. Uruchamiamy najpierw serwer (za pomocą naszego skryptu), a następnie klienta (z poziomu Eclipse). Dostajemy wyjątek java.security.AccessControlException, rzucany przez metdę: lookup(). Metoda ta próbuje odnaleść zdalny obiekt. Okzuje się bowiem, że RMISecurityManager zabrania nawiązywania połączenia w sieci. Musimy więc utworzyć plik polityki bezpieczeństwa. W tym celu tworzymy plik o nazwie client.policy w katalogu bin projektu naszego klienta. W pliku tym umieszczamy następującą zawartość, dającą nam nieograniczony dostęp do wszystkiego:



Podczas wdrożenia aplikacji trzeba bedzie plik ten zmodyfikować, w myśl zasady nie dawać więcej niż trzeba. Czas napisać skrypt uruchomieniowy dla klienta (katalog projektu klienta: D:\Java_programy\RMIClient):



Niestety dalej ten sam błąd. Rozwiązaniem tego problemu moze być dodanie pełnej (bezwzglednej) ścieżki do pliku cient.policy. Modyfikujemy nasz skrypt:



Warto jednak plik policy przenieść do głównego katalogu projektu. Po co? A no podczas czyszczenia projektu w Eclipse zawartość bin jest usuwana i możemy stracić nasz plik. Modyfikujemy więc odpowiednio skrypt uruchomieniowy:



Warto też czasem sprawdzić w kodzie, czy udało nam się uzyskać odpowiednie pozwolenia:



Gdyby druga metoda rzuciła java.security.AccessControlException oznaczało by to, że nie udało się ustawić odpowiedniej polityki bezpieczeństwa, czyli pewnie ścieżka jest błędna.


Oczywiście u Was ścieżki mogą byc trochę inne i musicie je dopasować do tego gdzie trzymacie projekt. Odpalamy skrypt i... udało się. Nie ma żadnego wyjątku:) Tyle że nasz kod klienta za wiele nie robi. Dodajmy więc poniższe 2 liniki do kodu klienta (za wywołaniem lookup()):



W tym momencie ładnie widać, że operowanie na zdalnych obiektach jest tak samo proste jak operowanie na lokalnych. Wywołanie metody niczym się nie różni.
Odpalmy klienta. Na konsoli powiązanej z programem klienta powinniśmy zobaczyć wynik działania:

Wynik: getDescription: Ala ma kota

a na konsoli serwerowej:

MyServerImpl.getDescription Ala ma kota

Oznacza to, że zadziałało. Zmieńmy tylko zawartość pliku client.policy, na następującą:



Powyższy plik oznacza zezwolenie na uzyskanie połaczenia z dowlną maszyną na portach 1024 - 65535. Domyślnie RMI siedzi na porcie 1099, a obiekty serwera mogą korzystać z wyższych portów. Chcąc być bardziej restrykcyjnym zamiast gwiazdki * możemy podać localhost.

Podsumowując, stworzyliśmy prosty serwer i klienta RMI. Przedstawiłem klika wyjątków, na które można się natknąć i podałem sposób radzenia sobie z nimi. Po więcej informacji odsyłam do ksiazki Core Java 2 Techniki Zaawansowane, a także do dokumentacji i tutoriali na stronie Sun'a. Z tego co mi wiadomo istnieje jeszcze wtyczka do Eclipse'a ułatwiająca pisanie aplikacji typu RMI. Ja osobiście nie korzystałem, więc nie wiem jak ona działa.

Więcej informacji:
[1] Tutorial na stronie Oracle: http://download.oracle.com/javase/tutorial/rmi/index.html
[2] Wprowadzenie do RMI w Javie 2 by Seweryn Hejnowicz:
http://www.ii.uni.wroc.pl/~prz/200405/2005lato/java/rmi/referat_rmi.htm
[3] Tworzenia aplikacji rozproszonej RMI by dr inż. Tomasz Kubik:
http://tomasz.kubik.staff.iiar.pwr.wroc.pl/dydaktyka/Java/JavaWyk06-RMI-TK.pdf
[4] Java. Techniki zaawansowane. Wydanie VIII
http://helion.pl/ksiazki/java_techniki_zaawansowane_wydanie_viii_cay_s_horstmann_gary_cornell,javtz8.htm (ja czytałem starsze wydanie i bardzo ładnie było wszystko opisane)
[5] Czysty kod. Podręcznik dobrego programisty:
http://helion.pl/ksiazki/czysty_kod_podrecznik_dobrego_programisty_robert_c_martin,czykod.htm (odnośnie serialVersionUID)