21 maj 2008

JAVArsovia 2008 - II edycja Konferencji Java grupy Warszawa JUG

31 maja 2008 w godzinach 9:00 - 19:00 w budynku Wydziału Biologii Uniwersytetu Warszawskiego przy ul. Miecznikowa 1 Warszawska Grupa Użytkowników Technologii Java (Warszawa JUG) oraz osoby zaprzyjaźnione (PJUG, Szczecin JUG, Trójmiasto JUG, Poznań JUG, Wrocław JUG) zapraszają na najciekawszą konferencję javową w Polsce - JAVArsovia 2008.

Motto konferencji: Miłośnicy Java dla miłośników Java aka Ciekawie o Javie.

Podczas 1-dniowej sobotniej konferencji zaprezentowanych zostanie wiele różnych technologii javowych i szkieletów aplikacyjnych. Z 4 panelami, każdy z 3-4 prezentacjami pragniemy, aby konferencja była ciekawa technologicznie oraz odzwierciedlała nasze własne, lokalne doświadczenia z Javą. JAVArsovia 2008 to idealne miejsce, aby spotkać się z innymi praktykami technologii, nawiązać kontakty, porozmawiać o bieżących problemach (technologicznych) i poznać nowe narzędzia, które usprawnią Twoje projekty. Sądzimy, że udział w konferencji JAVArsovia 2008 pozwoli każdemu popróbować się z nowościami technologicznymi lub zgłębić już poznane.

Wstęp wolny! Dobra zabawa gwarantowana!

Rejestracja na konferencję jest bezpłatna acz obowiązkowa i trwa do 29 maja! Na zakończenie konferencji zaplanowane jest spotkanie podsumowujące JAVArsovię na Polach Mokotowskich. Liczba miejsc ograniczona, więc czym wcześniej się zarejestrujesz, tym większa szansa na udział w niej.

Poprzednia edycja JAVArsovia 2007 była prawdziwym hitem czerwca 2007 w Polsce i teraz na pewno również nim będzie. Mamy nadzieję zorganizować największą i najbardziej huczną konferencję Java w Polsce w 2008. Bądź jej częścią! Miłośnicy Java już czekają na Ciebie...

Zapraszam w imieniu Kapituły JAVArsovii 2008 i grupy Warszawa JUG!

20 maj 2008

Dalsze atrakcje aplikacji JDA z JPA - @Enumerated

Kolejny dzień potyczek z aplikacją zbudowaną przy pomocy JDA (Java Desktop Application). Właśnie niedawno natrafiłem na ten skrót i zaskoczyła mnie zbieżność z JPA (Java Persistence API), którą również wykorzystuję w aplikacji Przychodnia. Jednym z zadań, jakie zaplanowałem w kontekście udoskonalania aplikacji była migracja pola plec typu boolean na typ wyliczeniowy (enum). Pamiętałem jeszcze z lektury specyfikacji i rozmów na grupach, że typy wyliczeniowe nie są czymś nadzwyczajnym dla JPA, więc nie spodziewałem się wielkich trudności, a mimo to i tak owa prostota rozwiązania zaskoczyła mnie.

Najpierw lektura specyfikacji JPA - rozdział 9.1.21 Enumerated Annotation (strona 181):

Domyślnie pole typu wyliczeniowego utrwalane (zapisywane) jest w bazie danych po jego liczbie porządkowej (wywołanie metody java.lang.Enum.ordinal()). Za pomocą adnotacji @Enumerated określany jest sposób mapowania pola typu wyliczeniowego, jako uzupełnienie dane z adnotacji @Basic (oczywiście adnotacja nie jest konieczna w wielu sytuacjach, więc najczęściej bazuje się na wartościach domyślnych adnotacji @Basic). Klasa java.lang.Enum, która reprezentuje wszystkie typy wyliczeniowe w Javie dostarcza dwie metody - ordinal() oraz name(), które uczestniczą w mapowaniu pola wyliczeniowego na struktury bazodanowe. Pierwsza z nich ordinal() wywoływana jest przy konfiguracji ORDINAL dla adnotacji @Enumerated, a druga przy wartości STRING. Domyślnie zakłada się ORDINAL, więc wszystkie typy wyliczeniowe będą zapisywane w bazie jako liczby porządkowe. Za pomocą STRING do bazy trafiają nazwy wartości typu wyliczeniowego.

Adnotacje posiadają swoje odpowiedniki w postaci elementów w pliku konfiguracji mapowania JPA, którym domyślnie jest META-INF/orm.xml (inne można wskazać za pomocą elementu mapping-file w META-INF/persistence.xml - "sercu" konfiguracji JPA lub nie wprost poprzez element jar-file). Odpowiednikiem xmlowym (zawartym w pliku orm.xml) adnotacji @Enumerated jest element enumerated (podelement basic), który akceptuje dwie wartości ORDINAL (domyślna) i STRING.

W mojej aplikacji Przychodnia zadeklarowałem typ wyliczeniowy pl.jaceklaskowski.przychodnia.model.Plec (początkowo był on w ramach klasy Pacjent, ale okazało się, że JDA narzekał na zagnieżdzenie klas wykorzystywanych do mapowania JPA).

 package pl.jaceklaskowski.przychodnia.model;

public enum Plec {

KOBIETA('K', "Kobieta"), MEZCZYZNA('M', "Mężczyzna");

private final char kod;
private final String nazwa;

Plec(char kod, String nazwa) {
this.kod = kod;
this.nazwa = nazwa;
}

public char kod() {
return kod;
}

@Override
public String toString() {
return this.nazwa;
}

public static Plec valueOf(int cyfra) {
return cyfra % 2 == 0 ? KOBIETA : MEZCZYZNA;
}

}
W pliku mapowania JPA - META-INF/orm.xml - wystarczyło dodać
 <basic name="plec" optional="false">
<enumerated>STRING</enumerated>
</basic>
aby do bazy trafiały napisy w postaci MEZCZYZNA lub KOBIETA. Nie rozwiązałem jeszcze kwestii zapisywania samych kodów typów, np. M dla mężczyzny, a K dla kobiety (ma ktoś pomysł jak to zrealizować, aby kod typu był wartością w bazie danych?).

Przy okazji zastosowania typu wyliczeniowego skorzystałem ze statycznego importu (import static) i kod stał się bardziej przejrzysty i czytelny. Wychodzę z założenia, że najpierw działający kod w wersji 1.0, a później jego uaktrakcyjnianie w kolejnych wersjach. W ten sposób podszedłem właśnie do zadania aplikacji Przychodnia.

Dodatkowo pola plec oraz wiek są ustawiane na podstawie obowiązkowego peselu, co sprowadziło się do następującej konstrukcji:
 protected void ustawWiekPlecNaPodstawiePeselu() {

// za Wikipedią o wieku w PESELu:
// http://pl.wikipedia.org/wiki/PESEL#P.C5.82e.C4.87
// Numeryczny zapis daty urodzenia przedstawiony jest w następującym porządku:
// dwie ostatnie cyfry roku, miesiąc i dzień.
// Dla odróżnienia poszczególnych stuleci przyjęto następującą metodę kodowania:
// * dla osób urodzonych w latach 1900 do 1999 - miesiąc zapisywany jest w sposób naturalny
// * dla osób urodzonych w innych latach niż 1900 - 1999 dodawane są do numeru miesiąca następujące wielkości:
// o dla lat 1800-1899 - 80
// o dla lat 2000-2099 - 20
// o dla lat 2100-2199 - 40
// o dla lat 2200-2299 - 60
int rokDzisiaj = Calendar.getInstance().get(Calendar.YEAR);
int rok = Integer.valueOf(this.pesel.substring(0, 2));
int miesiac = Integer.valueOf(this.pesel.substring(2, 4));
if (miesiac > 80) {
miesiac -= 80;
rok += 1800;
} else if (miesiac > 60) {
miesiac -= 60;
rok += 2200;
} else if (miesiac > 40) {
miesiac -= 40;
rok += 2100;
} else if (miesiac > 20) {
miesiac -= 20;
rok += 2000;
} else {
rok += 1900;
}
this.wiek = rokDzisiaj - rok;
if (this.wiek <= 0) {
throw new IllegalArgumentException("Niedozwolony wiek " + this.wiek + " [PESEL:" + this.pesel + "]");
}

// za Wikipedią o płci w PESELu:
// http://pl.wikipedia.org/wiki/PESEL#P.C5.82e.C4.87
// Informacja o płci osoby, której zestaw informacji jest identyfikowany,
// zawarta jest na 10 (przedostatniej) pozycji numeru PESEL.
// * cyfry parzyste (0, 2, 4, 6, 8) – oznaczają płeć żeńską
// * cyfry nieparzyste (1, 3, 5, 7, 9) – oznaczają płeć męską
this.plec = Plec.valueOf(Integer.valueOf(this.pesel.substring(9, 10)) % 2);
}
Coś mi mówi, że można byłoby to zrealizować prościej, ale nic na szybko nie przyszło mi do głowy, poza owym if-(else if)*-else. Sugestie mile widziane.

Niestety, sądziłem, że ta zmiana pociągnie za sobą zmiany w tworzonej dynamicznie tabeli przez JDA, tak że użytkownik będzie mógł wybrać płeć pacjenta z listy tworzonej na podstawie możliwych wartości typu wyliczeniowego, ale nic takiego się nie wydarzyło. W zamian pole stało się niemodyfikowalne, co w zasadzie jest równie dobre, gdyż jego wartość i tak wyliczana jest na podstawie obowiązkowego peselu.

Jutro zaplanowałem zabawę z formatowaniem danych w JTable podczas wyświetlania (renderery komórek) i edycji (edytory komórek).

18 maj 2008

Tworzenie aplikacji desktopowej z Java Desktop Application w NetBeans IDE 6.1 - część 2

W poprzednim artykule Tworzenie aplikacji desktopowej z Java Desktop Application w NetBeans IDE 6.1 przedstawiłem procedurę tworzenia aplikacji desktopowej "podpierając się" asystentem Java Desktop Application dostępnym w NetBeans IDE 6.1 oraz Java Persistence API (JPA) jako mechanizmem tworzenia odpowiednich struktur bazodanowych automatycznie. Głównym mankamentem aplikacji był brak korzystania z modelu z projektu przychodnia-model, gdzie pewne wartości były generowane automatycznie, a samo mapowanie encji odbywało się poprzez wydzielony plik mapowania META-INF/orm.xml.

W artykule Tworzenie aplikacji desktopowej z Java Desktop Application w NetBeans IDE 6.1 - część 2 przedstawiłem kolejne etapy udoskonalania aplikacji o wykorzystanie własnego modelu z projektu przychodnia-model z konfiguracją JPA z projektu przychodnia-generatortabel. Dużo dobrej zabawy w wykonaniu NetBeans IDE 6.1 i projektem Java Desktop Application.

W ramach artykułów powstaje wiele zadań do rozwiązania, które mogą być doskonałym sposobem na pogłębienie wiedzy w zakresie NetBeans IDE i tworzenia aplikacji desktopowych korzystających z Java Persistence API (JPA). Zadania należą do kategorii łatwiejszych, a to gwarantuje, że zadanie nie ma szansy się niepowieść, a tym samym i satysfakcje z wykonanego zadania. Same zalety, a jak wiedza wzrasta. Rozwiązania opublikuję w kolejnych wpisach.

p.s. Nadchodząca konferencja JAVArsovia 2008 31-ego maja 2008 może jeszcze bardziej uatrakcyjnić Twoje programistyczne "wypady" i tego typu doświadczeń technologicznych będzie znacznie więcej. Jeśli jesteś zainteresowany/-a pogłębieniem wiedzy praktycznie, to właśnie udział w konferencji JAVArsovia 2008 jest doskonałym miejscem, aby się popróbować z nowościami technologicznymi lub zgłębić już poznane. Jako przedstawiciel Kapituły JAVArsovii 2008 gorąco zapraszam do rejestracji na stronie konferencji i aktywnego uczestniczenia w niej. Do 31 maja już niedaleko, a skoro JAVArsovia pretenduje do miana największej konferencji javowej w Polsce, to na pewno nie może Cię na niej zabraknąć. Wstęp wolny! Dobra zabawa gwarantowana!

16 maj 2008

Tworzenie aplikacji desktopowej z Java Desktop Application w NetBeans IDE 6.1

W środę żona zrobiła mi niesamowitą niespodziankę! Bodajże na miesiąc przed spytała jedynie, czy mam czas w środę o 19:00 i tyle. Jakbym mógł odmówić mojej Agatce?! Oczywiście wszystkie możliwe inicjatywy przeniosłem zaraz na bezpieczniejszy czwartek i cierpliwie czekałem. W końcu okazało się, że owa niespodzianka to wyjście do Teatru Bajka na przedstawienie Goło i wesoło. Jeju, ale to było przedstawienie! Prawie umarłem ze śmiechu. Płacz murowany! Do tej pory kiedykolwiek przypomnę ją sobie, nie mogę powstrzymać się ze śmiechu. To jest obowiązkowy spektakl, dla każdego lubującego się w dobrze dobranym humorze z doborową obsadą aktorską. Po prostu cudeńko. Nie będę rozpisywał się na temat sztuki, bo szkoda byłoby uchylić chociażby rąbek tajemnicy na temat sztuki. Wystarczy, że napiszę, że jestem gotów iść na nią kolejny raz. Normalnie Góra, Żmuda, Bugi, Gustaw (szczególnie w drugiej części), Norbert i Kierownik to mistrzostwo świata w dobrym humorze. Ubaw po pachy! Dzięki Agata za wspaniały wybór!

A wracając do Javy to ostatnio natrafiłem na ciekawe zadanie, które dotyczyło stworzenia aplikacji desktopowej korzystającej z bazy danych. Czasu na jej utworzenie nie było wiele i wskazano na NetBeans IDE 6.1 jako narzędzie, które w ciekawy sposób upraszcza jej tworzenie za pomocą projektu Java Desktop Application. Podczas rozpoznawania funkcjonalności NetBeans natrafiłem na ciekawy wycinek specyfikacji Java Persistence API (JPA), gdzie mapowanie relacji jeden-do-wielu (adnotacja @OneToMany lub element <one-to-many>) można sprowadzić do konfiguracji opartej o 2 tabele z pojedyńczym kluczem obcym (z domyślnie wykorzystywanych 3 tabel z dwoma kluczami obcymi w tabeli łączącej). Użyteczna funkcjonalność NetBeans IDE 6.1 i ciekawostka JPA to równie ciekawie spędzony czas, co zaowocowało nowym artykułem Tworzenie aplikacji desktopowej z Java Desktop Application w NetBeans IDE 6.1. Zapraszam do lektury, a znudzonych siedzeniem przed kompem na spektakl Goło i wesoło. Koniecznie napisz, jak podobał się spektakl. Dla mnie był najwyższych lotów.

p.s. Kilka godzin temu przejeżdżałem koło podwrocławskiej wioski Jugowiec (a może to było miasto?). Jakby na przypomnienie, że niedługo JAVArsovia 2008 (dokładnie za 2 tygodnie - 31 maja 2008), gdzie jugowiczów będzie co nie miara. Ciekawe, czy będzie ktoś z podwrocławskiego Jugowca? Zapraszam! Wstęp wolny.

13 maj 2008

NetBeans Blogging Contest: Winner!

Dzisiaj zostałem nagrodzony dwukrotnie. Najpierw wystąpiłem na spotkaniu Warszawa JUG z prezentacją o Apache Wicket, gdzie padło tyle pytań i pojawiło się tyle wyjątków, że w ostatnim miesiącu nie zdobyłem tyle wiedzy, co właśnie podczas 31. spotkania! Przygotowuję się z tematem o Apache Wicket i OSGi na nadchodzącą konferencję JAVArsovia 2008, która jest organizowana przez grupę Warszawa JUG w dniu 31 maja 2008 w Warszawie i nie ukrywałem, że możliwość wystąpienia z Wicketem na 2 tygodnie przed konferencją jest dla mnie próbą generalną mojego przygotowania oraz zebrania dodatkowych wskazówek o potencjalnych obszarach, które należy uzupełnić, omówić, itp. Wierzę, że znalazły się osoby na spotkaniu, którym Wicket przypadł do gustu, a niewielka liczba przykładów gwarantuje, że jeszcze ciekawiej przed nimi. Z przyjemnością zebrałbym garść uwag odnośnie mojego wystąpienia i co powinienem dopracować, aby moje wystąpienie na JAVArsovia 2008 otrzymało miano najciekawiej prowadzonej (świadomie nie napisałem najciekawszej, gdyż temat jednego może zainteresować, a drugiego skłonić do odespania ostatniej niedospanej nocy - pozdrowienia dla dzisiejszych śpiochów! ;-))

Na chwilę przed wystąpieniem miałem możliwość zajrzeć do następującej wiadomości zatytułowanej NetBeans Blogging Contest: Winner!:

Jacek:

Congratulations! Your blog entry on NetBeans 6.1 was selected by our panel of judges as a winner of our NetBeans Blogging Contest.
[...]
Your blog entry will be promoted on the NetBeans Blogging Contest homepage.

Zamarłem! Nie żebym nie liczył na wygraną, bo w końcu uczestniczyłem w konkursie i udało mi się znaleźć czas na ewaluację kilku funkcjonalności właśnie, aby ostatecznie zostać wyróżnionym, ale kiedy już zostałem nagrodzony, to o tym wszystkim się zapomina, a nawet jest się zaskoczonym. Na stronie NetBeans IDE 6.1 Blogging Contest można znaleźć szczegóły konkursu i jego nagrodzonych, wśród których jestem i ja z tematem o wsparciu Spring Framework przez NetBeans IDE 6.1. Tym samym chciałbym podziękować jury, a w szczególności stałej czytelniczce i członkini jury - Magdalenie Gołdyn. Dziękuję Magda za cierpliwość i wskazanie!

11 maj 2008

31. spotkanie Warszawskiej Grupy Użytkowników Technologii Java (Warszawa JUG)

Warszawska Grupa Użytkowników Technologii Java (Warszawa JUG) zaprasza na 31. spotkanie, które odbędzie się 13.05.2008 o godzinie 18:00 w sali 5440 Wydziału MIMUW przy ul. Banacha 2 w Warszawie.

Temat prezentacji: Apache Wicket w przykładach
Prowadzący: Jacek Laskowski

Apache Wicket jest szkieletem webowym, którego podwalinami jest zarzucenie JSP jako technologii prezentacji, stworzenie warstwy modelu opartego o POJO i zniesienie konieczności stosowania wszechobecnego XMLa. Na spotkaniu Jacek zaprezentuje wiele przykładów, za pomocą których zamierza zademonstrować siłę Wicketa i przekonać do jego spróbowania w projektach. Odświeżające odseparowanie HTMLa od JSP, całkowite zaniechanie XMLa do konfiguracji aplikacji oraz wiele ciekawych rozwiązań wspierających tworzenia aplikacji webowych jak silne typowanie obiektów o zasięgu sesji czy aplikacji, wstrzymywanie żądania i przekierowywanie na stronę uwierzytelnienia są ciekawą alternatywą dla innych, znanych szkieletów webowych. Wiele z rozwiązań Wicket z pewnością sprowokuje do poszukiwania ich odpowiedników w obecnie korzystanych szkieletach. Mnóstwo przykładów gwarantuje praktyczne zrozumienie Wicketa.

Prezentację poprowadzi Jacek Laskowski, który jest pasjonatem tworzenia aplikacji javowych korzystających z Java EE i projektów otwartych. Jacek jest członkiem zespołów Apache Geronimo, Apache OpenEJB, Apache ServiceMix, Apache XBean oraz Apache ActiveMQ. Jestem założycielem i liderem Warszawskiej Grupy Użytkowników Technologii Java (Warszawa JUG). Bierze aktywny udział w wielu forach dyskusyjnych i otwartych projektach. Własne doświadczenia z językiem Java, Java EE i otwartymi projektami opisuje w Notatniku Projektanta Java EE. Służbowo pracuje na stanowisku konsultanta oprogramowania w IBM Polska.

Planowany czas prezentacji to 1,5 godziny, po której planuje się 15-30-minutową dyskusję.

Wstęp wolny!

Zapraszam w swoim imieniu i grupy Warszawa JUG!

09 maj 2008

Umiędzynarodowienie w Apache Wicket

Tempo rozwoju Apache Wicket może zdumiewać, gdyż jeszcze nie tak dawno podnosiłem wersję Wicket mojej testowej aplikacji do 1.3.3, a już mamy 1.4-m1. Z pomocą Apache Maven 2 temat sprowadził się do uaktualnienia pom.xml, w którym podniosłem wersję Wicketa oraz Spring Framework (do wersji 2.5.4). Jedną z głównych zmian w Wicketa 1.4 jest skorzystanie z mechanizmu wzorców w Javie (Java Generics), tak że musiałem zmienić sygnaturę metody WicketDemoApplication.getHomePage(), która zawęziła typ zwracanych obiektów do Class<? extends org.apache.wicket.Page>.

 c:\projs\sandbox\wicket-demo\src\main\java\pl\jaceklaskowski\wicket\WicketDemoApplication.java:[66,20] getHomePage() 
in pl.jaceklaskowski.wicket.WicketDemoApplication cannot override getHomePage() in org.apache.wicket.Application;
attempting to use incompatible return type
found : java.lang.Class<?>
required: java.lang.Class<? extends org.apache.wicket.Page>
Do mojej prezentacji Wicketa na kolejnym,wtorkowym spotkaniu Warszawa JUG pozostało już niewiele dni, więc kończąc lekturę książki Pro Wicket (Apress) trafiłem na rozdział przedstawiający mechanizm i18n - umiędzynarodowienia, który polega na przeniesieniu napisów do plików properties z przypisaniem im identyfikatorów wraz z ich wykorzystaniem w dedykowanych znacznikach <wicket:message>. Identyfikatory są niezmienne i zapisane są w ciele stron aplikacji, podczas gdy ich wartości zależne od języka są zapisane w plikach properties. Wskazanie miejsca umiędzynarodowienia polega na skorzystaniu ze znacznika <wicket:message key="..." />, który odszuka właściwego napisu dla podanego klucza (identyfikatora) wskazanego przez atrybut key. Pozostaje przedstawić, gdzie pliki properties powinny się znajdować. Jest kilka wariantów umieszczenia pliku properties, co daje nam różne poziomy granulacji komunikatów dla pojedyńczego formularza, pojedyńczej strony, dla całej grupy stron czy dla całej aplikacji. Nie wnikając w niepotrzebne szczegóły, umieszczę napisy w pliku odpowiadającym nazwie strony. Cała radość w "czystość" plików HTML została nieznacznie zaburzona wprowadzeniem specyficznych dla Wicketa znaczników <wicket:message>.

Oto strona DaneOsobowe.html ze znacznikami <wicket:message/>:
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Wicket Demo App</title>
</head>
<body>
<strong>Wicket Demo App</strong>
<span wicket:id="komunikaty"></span>
<form wicket:id="daneOsobowe" action="">
<table>
<tr>
<td><wicket:message key="imie" />:</td>
<td colspan="2"><input type="text" wicket:id="imie" /></td>
</tr>
<tr>
<td><wicket:message key="nazwisko" />:</td>
<td colspan="2"><input type="text" wicket:id="nazwisko" /></td>
</tr>
<tr>
<td><wicket:message key="login" />:</td>
<td colspan="2"><input type="text" wicket:id="login" /></td>
</tr>
<tr>
<td><wicket:message key="miejscowosc" />:</td>
<td><select wicket:id="miejscowosc">
<option>Cokolwiek</option>
</select></td>
<td><input type="submit" value="Zatwierdź" /></td>
</tr>
</table>
</form>
</body>
</html>
i odpowiadający jej plik DaneOsobowe.properties z wartościami kluczy:
 imie=Imi\u0119
nazwisko=Nazwisko
login=Login
miejscowosc=Miejscowo\u015b\u0107
W zasadzie to plik DaneOsobowe.properties powinienem był nazwać DaneOsobowe_pl.properties, aby wskazać jaki język plik zawiera, ale dla prostoty przykłady postanowiłem zaniechać tego.

I to tyle. Teraz wystarczy przenieść wszystkie napisy do odpowiednich plików properties i stworzyć wiele ich wersji językowych dla każdego wspieranego przez aplikację języka. I to bez modyfikacji kodu źródłowego! Wprowadzenie obsługi wersji językowej dla kolejnego języka sprowadza się teraz do dodania kolejnego pliku properties.

Pytanie konkursowe: Jaka jest geneza akronimu i18n, który tłumaczy się jako umiędzynarodowienie? Nagród nie przewiduje się.