czwartek, 23 grudnia 2010

Db4o jak zacząć?


W tym poście opowiem jak zacząć swoją przygodę z db4o. Nie będę pisał kolejnego tutoriala na ten temat, gdyż zostało to już niejednokrotnie zrobione. Skupię się raczej na przygotowaniu środowiska, pokazaniu przydatnych narzędzi i odesłaniu do ciekawych artykułów. Zaczynajmy.

Chcąc się bawić z db4o musimy na początek wybrać wersję z której będziemy korzystać. Ja na co dzień korzystam z wersji 7.4 określanej jako Stable. Mamy jeszcze wersje 7.12 (określaną jako Production) i 8.0 (Development). Podstawowe funkcjonalności powinny być takie same, ale z tego co kojarzę to poszczególne wersje różnią się pewnymi bardziej zaawansowanymi mechanizmami.

Chcąc więc skorzystać z db4o należy podpiąć odpowiedniego JAR’a pod projekt. Możemy takowego bezpośrednio ściągnąć ze strony producenta: db4o for Java, version 7.4.155.14653 ZIP W tym pliku, katalogu lib mamy min. dostępne odpowiednie wersje JAR’ów przygotowane dla różnych wersji Javy:

  • db4o-7.4.155.14653-java1.1.jar
  • db4o-7.4.155.14653-java1.2.jar
  • db4o-7.4.155.14653-java5.jar

Ja oczywiście korzystam z wersji dla Javy 5. Jeżeli korzystamy z mavena, to musimy dodać następujący wpis:


  
    db4o
    http://source.db4o.com/maven/
  



  com.db4o
  db4o-java5
  7.4-SNAPSHOT


Teraz już możemy się bawić. Na początek polecam przejście tutoriala: doc\tutorial\db4o-7.4-tutorial.pdf z archiwum ściągniętego wraz z db4o. Pokazuje on za pomocą przykładów funkcjonalności db4o. Nie ma tu jakiś wielkich teorii jak całość działa, tylko raczej ukazanie funkcjonalności za pomocą przykładu i krótkiego komentarza. Budowana jest w nim aplikacja odnosząca się do wyścigów F1 i w kolejnych rozdziałach przedstawia kolejne dostępne funkcjonalności.

W tutorialu tym brakuje pokazanego kodu klasy Util. Musimy więc sami stworzyć sobie taką klasę w naszym projekcie, lub zastąpić wszelkie wywołania Util.DB4OFILENAME nazwą pliku w którym będzie przechowywana nasza baza danych. Ewentualnie skorzystać z kodu dostępnego w tym samym katalogu co tutorial.

Znalazłem nawet niemalże tłumaczenie tego tutoriala na polski. Fakt faktem nie dotyczy on najnowszej wersji, a jedynie 6.3. Kiedyś przeczytałem to całkiem dokładnie i było nie było to najgorsze tłumaczenie. Można się na nim opierać. Czasami są wywoływane w tym „tutorialu" metody, które są obecnie @deprecated, ale poza tym jest całkiem ok. Opisywane tłumaczenie jest zawarte w pracy magisterskiej Pawła Protasia pt. Pomost pomiędzy SBQL a Db4o.

Jeżeli chcielibyśmy stworzyć prostego CRUD’a z wykorzystaniem db4o i JSP polecam artykuł z 8mego numeru Java exPress  pt.: DB4O - Obiektowa baza danych. Autorem artykułu jest Paweł Cegła, który również na swoim blogu pisze o db4o.

To tyle na początek jeśli chodzi o chęć zrozumienia działania samej bazy db4o. Chcąc tworzyć już bardziej skomplikowane, wielowątkowe aplikacje, powinniśmy zapoznać się z klasą Db4oUtil. Pierwszy raz znalazłem ją na blogu Space Program we wpisie: Db4oUtil (aka. The Easiest Way to Get Started With Db4o). Kopia tej klasy (troszkę zmodyfikowana) znajduje się również na stronie db4o: Db4oUtil (aka. The Easiest Way to Get Started With Db4o). Podaje obydwa linki, gdyż jakiś czas temu strona db4o przechodziła renowacje i wówczas wiele linków nie działało.

Db4oUtil jest thread safe i proste w użyciu. Ja akurat zazwyczaj korzystam ze zmodyfikowanej przez mnie wersji tego pliku w zależności od aktualnych potrzeb projektowych. Schemat użytkowania jest podany w przytoczonych artykułach.

Mamy jeszcze do dyspozycji oczywiście dokumentację javadoc. Miejscami nie jest ona „wylewna”, ale na pewno warto ją podpiąć pod ulubione IDE. Jest jeszcze Reference Documentation (doc\reference\db4o-reference-java.pdf), ale to już jest ponad 1000 stron w pdf’ie i początkowo odradzam. Dopiero jak czegoś nie znajdziemy w tutorialu, ani w javadoc to można tego szukać w dokumentacji referencyjnej.

Na koniec chciałbym polecić narzędzie ObjectManagerEnterprise (OME). Jest to aplikacja służąca do podglądu bazy db4o (nawet jak nie wiemy jakie klasy tam siedzą). Narzędzie jest dystrybuowane razem z biblioteką db4o. Działa ono jako wtyczka do Visual Studio (w przypadku gdy korzystamy z wersji db4o dla C#) lub Eclipse (w przypadku gdy korzystamy z wersji Javowej). Jest jeszcze rozszerzenie dla Netbeans’a: db4o-netbeans, ale jest ono już nie rozwijane od 3ch lat i z nowym NB nie współpracuje (a szkoda).

OME wywodzi się bezpośrednio z projektu db4o Object Manager działającego jako aplikacja standalone. Jednak i ten projekt nie jest już rozwijany i nie wspiera nowszych wersji db4o.

Jeszcze mogę polecić własną prezentację pt.: Inicjatywa NoSQL na przykładzie db4o, którą miałem ostatnio okazję prezentować w ramach WrocJUG. Więcej o samej prezentacji w poprzednim wpisie: Wrażenia po pierwszej mojej prezentacji w ramach Wrocław Java User Group.

To chyba na tyle co mógłbym polecić na początek, jeśli ktoś chciałby się pobawić db4o. Wszelkie komentarze z interesującymi linkami na temat db4o mile widziane.

sobota, 18 grudnia 2010

Wrażenia po pierwszej mojej prezentacji w ramach Wrocław Java User Group


We wrotek (14.12.2010) miałem przyjemność prowadzić prezentację w ramach Wrocław Java User Group (WrocJUG). Było to moje pierwsze wystąpienie na tym poziomie trudności. Wielokrotnie prowadziłem prezentacje w ramach koła naukowego ISA^2 czy PWrJUG, ale na WrocJUG jest trochę inaczej. O ile studenci w miarę wierzą w to co się do nich mówi, to na WrocJUG padają już trudne pytania i byle odpowiedź jest tu niewystarczająca. Tutaj trzeba mieć większą wiedzę i mocne argumenty, aby przekonać do siebie słuchaczy.

Mój temat prezentacji to: Inicjatywa NoSQL na przykładzie db4oDb4o zajmuję się już od jakiegoś czasu, a zaczynałem od studenckiego projektu, później była magisterka i kilka małych projekcików dla własnych celów. O rozwiązaniach NoSQL miałem okazję trochę posłuchać w ramach polskich konferencji. Prezentacją chciałem trochę przybliżyć i rozpropagować te obydwie rzeczy we Wrocławiu.

Do samej prezentacji przygotowywałem się dość długi czas. Już podczas wakacji miałem pierwsze pomysły, jakie triki mogę wykorzystać w prezentacji, aby widownię trochę rozbawić i zmusić do dyskusji. Samą prelekcję musiałem trochę odwlec w czasie, gdyż chciałem się najpierw obronić, a dopiero potem przemówić na WrocJUG. Jak już zgłosiłem gotowość do prezentowania, to trzeba było jeszcze chwilę poczekać na wolną salę (spotkania nie są regularne, więc nie mamy jej na stałe zarezerwowanej).

Jak poszła prezentacja? Po prelekcji zgarnąłem kilka pozytywnych opinii, z czego się cieszę. Zależało mi na tym, aby zmusić widownię do dyskusji, co mi się udało. Padało tyle pytań, że całe wystąpienie przeciągnęło się do 2 godzin i 15 minut! Udało mi się ponadto poprowadzić prezentację na luzie i sala często się śmiała.

Czy udało mi się przekonać uczestników do korzystania z db4o? Chyba nie do końca. Jeżeli przedstawił bym produkt, który ma funkcjonalność zbliżoną do obecnych komercyjnych, relacyjnych baz danych, to wtedy może tak. Db4o jednak ma troszkę inne przeznaczenie (małe i średnie projekty, aplikacje standalone) niż duże relacyjne kombajny, przechowujące ogromne ilości danych.

Podczas prezentacji dało się odczuć, jak bardzo jesteśmy zakorzenieni w relacyjnym modelu danych i jak ciężko jest nam się odnaleźć w nowym środowisku. Znamy bardzo dobrze programowanie obiektowe, ale ciężko nam jest sobie wyobrazić, aby przechowywać dane w postaci obiektów. Bardzo też się przyzwyczailiśmy do innych możliwości jakie oferuje nam relacyjna baza danych i nie chcemy z nich tak łatwo rezygnować.

Uwagi jakie zebrałem na temat samej prezentacji:

  • Nie wszystko było czytelne na slajdach, np. czarny tekst na czerwonym tle na jednym z obrazków. Wynikało to trochę z wypalenia się lampy rzutnika. Z drugiej strony chciałem zachować kolorystyke stosowaną w dokumentacji db4o.
  • Nie zawsze udawało mi się ładnie złamać linię kodu na slajdach. No niestety miałem trochę „tasiemcowate” warunki w if-ach, a nie chciałem czcionki w kodzie pomniejszać, ze względu na pogorszenie widoczności.
  • Ładniej również kod uruchamiany można było dopracować, np. nie tworzyć metod statycznych. Wynikło to trochę z mojego lenistwa, gdyż chciałem aby wszystko co ciekawe w danym przykładzie, działo się w metodzie main(). Niektórzy jednak oceniają programistę po jego kodzie i niezaspecjalnie na tym polu wypadłem. Trzeba się poprawić na przyszłość! Na przykład zamiast pokazywać kolejne możliwości w metodzie main(), można przygotować testy uczące (chyba tak to się nazywa). Chodzi mi o testy, które piszemy dla siebie, gdy chcemy poznać działanie nowej biblioteki. W ten sposób sprawdzamy, czy dobrze zrozumieliśmy dokumentację.
  • Zamiast używać SVN’a można by kopiować odpowiednie pliki projektów z uprzednio przygotowanych katalogów. Nie chciałem tworzyć kodu na żywo, gdyż bardzo dobrze wiem, że to ciężkie zajęcie pisać kod i jednocześnie opowiadać o nim, a najczęściej i tak wychodzi, że o czymś zapominamy i nie działa. Zaczyna się wtedy desperackie poszukiwanie przyczyny, a publika się zaczyna nudzić. Dlatego postanowiłem skorzystać z SVN’a i przełączać się pomiędzy kolejnymi rewizjami kodu. Z widowni słyszałem szmery, że to fajny pomysł, ale rzeczywiście kopiowanie pliku mogło by być trochę szybsze.
  • Mało wiedziałem o komercyjnym zastosowaniu db4o i jakie sprawia problemy. No cóż nie mam komercyjnego doświadczenia z db4o, ani informacji jak to się sprawdza na produkcji.
  • Odpalanie prostych przykładów kodu nie zawsze jest potrzebne.
  • Warto zainstalować program typu ZoomIt, aby jakby coś nie było czytelne, można było powiększyć ekran.
  • Brakowało mi trochę takiej aplikacji, która wyświetlała by slajdy w trybie prezentacji. Tzn. abym na ekranie laptopa widział aktualny slajd i następny, a na rzutniku był tylko aktualny slajd wyświetlany. Z tego co mi wiadomo to pakiet MS Office i OpenOffice mają taką funkcjonalność, ale niestety one nie obsługują pdf'ów. Jakby ktoś znał taką aplikację proszę o info.

Więcej uwag nie pamiętam, jak mi się cos przypomni to dopiszę :)

czwartek, 11 listopada 2010

Zostałem magistrem inżynierem


W środę (10.11.2010) stałem się magistrem inżynierem. Po co o tym tutaj piszę? Aby trochę podsumować ostatni okres mojego życia i aby kiedyś do tego postu powrócić i zobaczyć co się zmieniło. Ale od początku.

Moje studiowanie troszkę się przedłużyło. Generalnie starałem się zawsze pracować regularnie i intensywnie (zwłaszcza nad magisterką), jednak na początku czerwca stwierdziłem, że mogę się nie wyrobić z zakończeniem aplikacji i redakcją pracy. Do tego jeszcze się rozchorowałem i nie byłem w stanie nad tym siedzieć. No dobra, to przekładam obronę na wrzesień – nic się przecież przez to nie stanie.

Czy było to dobre posunięcie? Teraz na pewno bym tak nie zrobił. Trochę za ambitnie podszedłem do magisterki i jak bym miał taką pisać drugi raz, zrobił bym byle działało i oddałbym ją w terminie. Może nie była by ona najwyższej jakości, ale na magisterkę nie robi się niewiadomo jakich odkrywczych rzeczy.  Od tego są doktoraty. No i magisterka nie jest niewiadomo jak dokładnie sprawdzana i weryfikowana.

Druga sprawa to załatwianie formalności związanych z obroną. Indeks w dziekanacie leżał ponad 3 tygodnie i był weryfikowany, czy czasem nie oszukiwałem podczas studiów. Nie dość, że oceny z każdego przedmiotu lądują w kilku miejscach (indeks, karta zaliczeń, protokół, różne systemy informatyczne) to teraz na koniec  trzeba to wszystko sprawdzić , czy się oceny zgadzają.  No i to niestety trwa, nawet jak się nie miało „ciekawego” przebiegu studiów. Przez te formalności (czy jak kto woli proces biznesowy) nie zdążyłem we wrześniu z obroną (mimo dotrzymania wszelkich terminów).

Dalej było załatwianie kolejnych formalności: druk pracy w kilku egzemplarzach w tym archiwalna „przywiązana naturalnym sznurkiem do teczki” i ponumerowana ołówkiem (SIC!), przepisanie całego indeksu do arkusza kalkulacyjnego (mimo obecności tych ocen w innych systemach informatycznych) i wiele innych. Na co komu to, to nie wiem. Większość tej makulatury i tak po jakimś czasie pójdzie do spalenia (wskazuje na to chociażby ten naturalny sznurek).

No dobra w końcu zebrało się kilkunastu chętnych do obrony i w listopadzie w końcu zrobili termin. Jak wyglądała sama obrona? Już miałem wchodzić na salę, laptop odpalony na prezentacji, a tu komisja stwierdza, że robi sobie przerwę… No i kolejna godzinka czekania.

Sama obrona poszła szybko (około 20 min). Byłem bombardowany pytaniami w trakcie prezentacji i podczas odpowiadania na wylosowane pytania. Trafiłem na takie które średnio umiałem, ale wybrnąłem i obroniłem się na 5,0. Praca magisterska również oceniona była na 5,0 ale średnia ze studiów zaważyła na tym, że na koniec wyszło 4,5. Szkoda, że tutaj zaangażowanie w kołach naukowych się nie liczy bo by na pewno wyszło lepiej. No cóż, i tak z tych ocen można być dumnym.

Jak wyglądał czas przed obroną (a raczej w oczekiwaniu na termin obrony)? Mi to przypominało trochę siedzenie na gwoździach. Załatwianie formalności, czekanie na termin, opracowywanie pytań… Jak dla mnie był to straszny okres wyczekiwania, w którym ciężko było sobie sensownie czas zorganizować, bo mogli nagle zadzwonić i powiedzieć, że za kilka dni obrona. Teraz mam nadzieję, że skoro już jestem po, to coś więcej się na blogu technicznego pojawi.

Czy dostrzegam jakieś pozytywy przeniesienia obrony na późniejszy termin? Tak, drugi raz bym tak nie zrobił i mniej ambitnie bym podszedł do magisterki. Z drugiej strony, gdybym chciał się bronić w pierwszym terminie, nie mógłby uczestniczyć w najlepszej konferencji Javowej w jakiej było mi dane dotychczas uczestniczyć. Oczywiście myślę tutaj o Javarsovi. Zamiast uczestniczyć w prelekcjach, zarywałbym nocki kończąc w pocie czoła magisterkę. A znając prawa Murphy'ego pewnie i tak coś przed końcem by się sypło. No i nie wiem czy bym blog zaczął pisać…

Czas pokaże co było dobre.

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)

czwartek, 9 września 2010

Czysta strona w prezentacji i problem ostatniego slajdu

Trochę znajomych osób trochę narzeka na mnie ostatnio, że nic nowego na blogu nie piszę. Cóż trzeba się trochę poprawić, mimo niezbyt dużej ilości wolnego czasu ostatnio. Przygotowałem więc krótki wpis na temat tego, z czym się ostatnio męczyłem.

Tworząc prezentację z wykorzystaniem systemu składu tekstu LaTeX, a dokładniej pakietu beamer, wykorzystujemy zazwyczaj jeden ze zdefiniowanych szablonów wyglądu prezentacji. Powoduje to, że nagłówek, stopka i inne jeszcze elementy w całej prezentacji będą wyglądać tak samo. Chcąc zmienić wygląd naszej prezentacji wystarczy modyfikacja jednej linijki (ewentualnie dwóch) w preambule dokumentu i już całkowicie zmienia się nam wygląd prezentacji. Tabelę jakie są dostępne szablony prezentacji można zobaczyć tutaj: http://www.hartwork.org/beamer-theme-matrix/. Nic oczywiście nie stoi na przeszkodzie aby zdefiniować sobie własny szablon, ale to nie temat na dziś.

Ostatnio potrzebowałem, aby jeden slajd prezentacji wyglądał zupełnie inaczej niż reszta. Nie jest to może eleganckie rozwiązanie, gdyż prezentacje - techniczne zwłaszcza - powinny trzymać się jednego szablonu / wyglądu. Ale czasem chcemy cos bardzo podkreślić i potrzebujemy wtedy jednego innego slajdu.

Jak to osiągnąć? Najpierw pozbądźmy się nagłówka, loga i stopki z prezentacji. Można to wykonać w następujący sposób:



lub jak kto woli:



Dzięki temu zabiegowi (użyciu [plain]) otrzymujemy jeden pusty slajd. No dobra niby ładnie, pięknie, ale jak korzystamy z szablonu, który wstawia navigation bar, to wówczas na slajdzie jest on dalej widoczny. Czym jest ten navigation bar? A no jest to zbiór pewnych przycisków, umieszczanych na slajdach, najczęściej w prawym dolnym rogu. Umożliwiają one nawigację po slajdach, ale są raczej rzadko używane i mają dlatego mało kontrastowy kolor. Przykład takiego paska zamieszczam poniżej (celowo na czarnym tle):


Jak się tego pozbyć? Przykład poniżej:



Rozwiązanie to zaproponował mi Marcin M. (nazwisko znane redakcji), za co serdecznie dziękuję. Co prawda nie spotkałem się z szablonem który miałby tego navigationbar’a ustawionego pionowo (można sobie samemu takiego zrobić za pomocą opcji [vertical]), ale jednak tą ostatnią linijkę lepiej jest zamienić na przywrócenie domyślnych ustawień:



Działa? Działa! Dzięki tym zabiegom otrzymaliśmy pusty slajd. No dobra, ale co nam po pustym slajdzie? Zmieńmy kolor tła:



Komendy te możemy wstawiać pomiędzy slajdami, manipulując przez to tym jak mają wyglądać.

To tyle jeśli chodzi o modyfikację pojedynczego slajdu (lub grupy slajdów) w prezentacji. Jeśli chodzi o inne kolorowanie tekstu na takim slajdzie to zamiast edytować kolory szablonu, lepiej zadeklarować kolor danego tekstu, za pomocą \textcolor.

Chciałem jeszcze opisać problem ostatniego slajdu w prezentacji. Otóż zalecane jest, aby pierwszy i ostatni slajd był taki sam (gdyby się komuś przysnęło na prezentacji, to aby wiedział za co brawa biją ;) ). Czasem jednak pierwszy i ostatni slajd mogą powodować figle już na samej prezentacji. Jako przykład, z życia wzięty, przytoczę historię jaka się przytrafiła Jackowi Laskowskiemu na konferencji 4Developers, opisaną we wpisie: Ochy i echy z piątkowego 4Developers w Poznaniu. Otóż byłem na tej prezentacji i Jacek chce zaczynać, a tu nie może się przełączyć na drugi slajd. Chwila napięcia i „atmosfera gęstnieje”. Na szczęście ktoś z sali zauważył że jest to ostatni slajd a nie pierwszy.

Mi dzisiaj do głowy przyszło, że ok - pierwszy i ostatni slajd powinny wyglądać tak samo - ale pod koniec wystąpienia zazwyczaj się dziękuje za uwagę. Czy jest na to potrzebny osobny slajd? Pomyślałem, że na ostatnim tytułowym slajdzie, można by było od razu podziękować za uwagę. Czy jest to możliwe do zrealizowania w beamer’ze? Po chwili kombinowania okazało się ze tak.

Stronę tytułową wstawiamy w prezentacji za pomocą polecenia \titlepage. Jest ono generowane automatycznie według danego schematu wyglądu prezentacji. Chcą mieć wpływ na to co znajdzie się na prezentacji, w preambule wywołujemy następujące polecenia (nie musimy wszystkich):



Polecenia te zazwyczaj umieszczamy w preambule dokumentu, ale nic nie stoi na przeszkodzie aby później je przedefiniować. Aby wyświetlić ostatnią stronę prezentacji taką jak pierwszą z małą modyfikacją możemy to zrobić następująco:



Przykładowy efekt poniżej:



Jakby komuś przeszkadzało, ze na końcowym slajdzie tytuł jest trochę wyżej, to w preambule może dodać polecenie:



Dzięki temu tekst na pierwszym slajdzie nie będzie widoczny (bo będzie w kolorze tła), ale pozycje pozostałych elementów zostaną wyliczone tak, jakby był ten tekst wyświetlany.

To już koniec na dzisiaj. Mam nadzieję, że moje wywody się komuś przydadzą...

piątek, 27 sierpnia 2010

Kolorowanie składni Javy w systemie LaTeX

Dzisiaj opiszę trochę o środowisku lstlisting w systemie składu tekstu LaTeX. Czemu chcę o tym napisać? Ponieważ ten temat do mnie co chwile wraca. Nie wystarcza mi raz skonfigurowane i użyte środowisko, tylko co jakiś czas musze coś w nim zmodyfikować i wykorzystać gdzieś indziej. Innymi słowy chciałbym sobie zrobić małą ściągawkę na blogu, dotyczącą tego pakietu, bo ciągłe przeszukiwanie dokumentacji - co znaczą poszczególne opcje - zaczęło mnie już irytować.

Chcąc ładnie wyświetlić kod w naszym dokumencie, składanym przy użyciu systemu LaTeX, musimy dołączyć w preambule pakiet listings. Najczęściej zaraz pod nim następuje konfiguracja pakietu:



Następnie będzie można już korzystać z prostego otoczenia do wstawiania kodu:



W nawiasach kwadratowych można przedefiniować niektóre ustawienia dostępne w lstset, dodać etykietę i treść podpisu. Zmiany te będą aktywne dla danego listingu kodu.

Odmiennym sposobem wstawienia kodu może być dołączenie go bezpośrednio z pliku zewnętrznego:



I tutaj w nawiasach kwadratowych można przedefiniować odpowiednie parametry.

Poniżej najważniejsze i najciekawsze parametry lstset:

language - Wybór języka programowania z którego korzystamy. W przypadku Javy mamy dostępny dialekt AspectJ, który możemy użyć następująco: language=[AspectJ]Java.
basicstyle - Ogólny styl kodu, np. \footnotesize \small \scriptsize itp. Gdzieś wyczytałem / usłyszałem, że kod powinien być trochę mniejszą czcionką pisany od reszty tekstu.
aboveskip - Odstęp nad kodem.
belowskip - Odstęp pod kodem.
showspaces - Wyświetlanie znaku spacji (jako pokreślenie). Domyślnie wyłączone.
showstringspaces - Wyświetlanie znaku spacji (jako pokreślenie) ale w tekstach (Stringach). Domyślnie włączone, więc warto ustawić na false.
showtabs - Wyświetlanie znaku pokreślenia w miejscach występowania tabulatora.
tab - Możemy zdefiniować, co będzie wyświetlane jako znak tabulacji. Wymaga showtabs=true.
prebreak - Wyświetlanie znaku na końcu linii tekstu, która musi być złamana.
postbreak - Wyświetlanie znaku na początku linii, która została złamana.
breakindent - Wielkość wcięcia złamanej linii.
frame - Ramka dookoła listingu. Możliwe wartości: none, leftline, topline, bottomline, lines(linia na dole i górze) , single (pojedyncza ramka), shadowbox (ramka z cieniem).
identifierstyle - Styl identyfikatorów (zmiennych).
commentstyle - Styl komentarzy.
stringstyle - Styl napisów.
keywordstyle - Styl słów kluczowych.
numbers - Położenie numerów linii. Możliwe wartości: none, left, right.
stepnumber - O ile linijek ma się wyświetlać numer linii. Domyślnie 1.
numberstyle - Styl numerków.
numberblanklines - Jeśli false to puste linie nie mają numerków, domyślnie true.
numbersep - Odległość między numerem a listingiem.
captionpos - Pozycja podpisu listingu. Możliwe wartości t (top) i/lub (bottom).
gobble - Liczba początkowych znaków w kodzie, która ma być ignorowana. Tzn. jak wklejamy kod, który zawsze się zaczyna od dwóch spacji, to możemy je, za pomocą tego parametru, zignorować
escapeinside - Definiuje znaki pomiędzy którymi, można wstawić dodatkowy komentarz wewnątrz kodu. Użyte w ten sposób: escapeinside="" powodowało mi kiedyś, że nie chciał odpowiednio cudzysłowów wyświetlać.

Czasami użycie niektórych parametrów może wymagać dołączenia dodatkowych pakietów przed definicją.

Poniżej zamieszczam przykładowy kod który będę próbował ładnie wyświetlić:



Dobra teraz pokażę kilka konkretnych przykładów zastosowania tego co dotychczas opisałem. Na początek ustawienia zaproponowane przez mojego przyjaciela Tomka:



A oto efekt:

No kod został bardzo ładnie pomalowany. Wszystkie słowa kluczowe zostały ładnie wyłapane i pomalowane na niebiesko. Komentarze również zostały ładnie wyróżnione niezależnie od tego w jaki sposób zostały zadeklarowane. Podpis rysunku uzyskano przy pomocy dodatkowego parametru dla danego listingu:



Jakby się przyjrzeć bardziej temu listingowi to można jednak zobaczyć mały mankament. Otóż długa linijka tekstu została automatycznie złamana przez system składu. Spowodowało to jednak to, że obramowanie pomiędzy liniami 11 a 12 zmieniło kolor na kolor tekstu. Nie wiem czym to jest dokładniej spowodowane, ale podejrzewam komendę \raisebox użytą przy prebreak. Jak ktoś wie skąd to się bierze, to chętnie poznam rozwiązanie. Niby można wyłączyć łamanie linii za pomocą breaklines=false ale to spowoduje, że tekst wyjdzie po za obszar ramki.

Jak dla mnie ustawienia te nie są idealne. W swojej pracy magisterskiej zrezygnuję z ramki i kolorów. Dlaczego? Gdyż będę musiał wtedy część stron wydrukować na kolorowej drukarce a takiej nie posiadam. Może to spowodować, że marginesy stron pochodzących z różnych źródeł, nie będą dokładnie do siebie pasowały (z powodu innych obszarów drukowania w różnych drukarkach). Dlatego wolę uniknąć kolorowych stron w swojej pracy.

Poniżej zamieszczam mój zestaw ustawień:



Dają one następujący efekt:


Już nie wygląda tak ładnie, ale nie jest też tragicznie. Można się dziwić czemu nie wyrzuciłem z kodu definicji keywordstyle, commentstyle i stringstyle tylko ustawiłem w nich kolor na czarny? A no po to, aby krój czcionki mi się nie zmienił :)

Dobra teraz chciałbym pokazać takie ustawienia, aby składnia kodu wyglądała tak jak w NetBeans’ie:



Efekt poniżej:

Nie jest to do końca tak jak bym sobie tego życzył. NetBeans dodatkowo nazwę klasy i metody testSetId wyświetla czcionką pogrubioną. A metoda assertEquals jest czcionką pochyloną pisana, ze względu że jest to metoda statyczna. Szukałem sposobu w jaki to zrobić, ale lstlisting po za słowami kluczowymi, komentarzami i string’ami nic więcej nie rozróżnia…

Ale można, jakby dodefiniować nowe słowa kluczowe i zastosować dla nich oddzielny styl. Z tym że jeśli chodzi o nazwy klas i metod, to warto te ustawienia jednorazowo dla konkretnego listingu stosować. Przykład poniżej:



Efekt poniżej:


Uff udało się. Nazwa klasy i metody są już pisane pogrubioną czcionką. Również metoda assertEquals zaczęła być wyświetlana kursywą. A co ja takiego zrobiłem? Najpierw zdefiniowałem nowy classoffset o numerze 1. Następnie zdecydowałem jakie słowa kluczowe należą do tego zestawu (morekeywords) i jak mają wyglądać (keywordstyle). Następnie czynność powtórzyłem dla assertEquals nadając jej inny styl. Może da się to jakoś bardziej uniwersalnie zrobić, ale tego już nie wiem.

Na koniec podam jeszcze kilka ciekawych sztuczek. Gdybyśmy chcieli zmienić numerowanie linii musimy przedefiniować polecenie \thelstnumber. Np. chcąc wyświetlać dwukropek po numerze linii musimy po definicji \lstset dodać poniższą linijkę:



Chcąc zrobić np. na końcu dokumentu spis wszystkich listingów użytych w dokumencie wystarczy wydać komendę:



Aby zmienić nagłówek dodawany przez to polecenie piszemy w preambule:



Chcąc zmienić nazwę Listing dokładaną do każdego listingu możemy zastosować nastepującą instrukcję w preambule:



I jeszcze numerowanie listingów. Chcąc je numerować według numeru rozdziału i numeru który to rysunek w danym rozdziale piszemy (najlepiej w jednej linijce):



Definicję tę umieszczamy za \begin{document}! Dodatkowo trzeba przedefiniować section (w premabule):



Co ciekawsze jak kilka razy w ramach \lstset zdefiniujemy pewne wartości to zostaną wybrane te położone dalej. Dlatego czasem jak nam nie chcą działać pewne zmiany to sprawdźmy czy nie mamy duplikatów. Ja trochę czasu w ten sposób straciłem.

Ponadto trzeba kolejne ustawienia wartości rozdzielać przecinkiem (nie stawiamy go po ostatnim parametrze). Inaczej nie wszystkie parametry zostaną dobrze skwalifikowane. Podobnie możemy mieć ustawione parametry które nie istnieją, a kod i tak się będzie kompilował :)

I jeszcze uwaga jeśli chodzi o umieszczanie listingów kodu na prezentacjach z użyciem pakietu beamer. Musimy zezwolić na „złamanie” slajdu, gdyby kod się nie zmieścił na jednym. Inaczej dostaniemy błąd: Paragraph ended before \lst@next was complete. Pozbywamy się tego za pomocą:



Powinniśmy jednak unikać kilkustronicowych listingów kodu na slajdach prezentacji, gdyż nie należy to do sztuki tworzenia dobrych prezentacji. Zmniejszenie czcionki kodu może zwiększyć liczbę kodu jaki możemy przedstawić, ale stanie się on mniej czytelny. Zresztą komu chce się analizować kilkustronicowy kod na prezentacjach?

Użycie allowframebreaks powoduje jednak, że w górnej części slajdu w tytule będzie na końcu wyświetlana cyfra rzymska mówiąca który to slajd z kodem. Nawet jak będziemy tworzyć jednoslajdowe listingi to i tak otrzymamy brzydką jedynkę rzymską w tytule. Aby się tego pozbyć należy w preambule dokumentu dodać linijkę:



Od teraz już nasze listingi kodu, czy to w dokumentach, czy w prezentacjach będą wyglądać profesjonalnie:)