06 kwietnia 2008

Nowości NetBeans IDE 6.1 - Java Beans Support

Kiedy pierwszy raz przeczytałem o wsparciu dla Java Beans przez NetBeans IDE 6.1 kompletnie nie widziałem, co otrzymuję, a co za tym idzie czego mógłbym od tej funkcjonalności oczekiwać. Wspaniale się złożyło, że wraz z ukazaniem się NetBeans 6.1 BETA od razu rozpoczęto konkurs NetBeans IDE 6.1 Beta Blogging Contest, w którym blogerzy nie tylko angielskojęzyczni, ale również polskojęzyczni, mogą rozpisywać się o jego funkcjonalnościach. Nie mogłem nie skorzystać z nadarzającej się okazji popróbowania się z nowiuteńkim NetBeans 6.1 i zgłosić kilka wpisów o nim w tym konkursie. Jeśli do tej pory zastanawiałeś/-aś się, jakby włączyć się do społeczności pismaków internetowych (aka blogerzy) to właśnie jest okazja upiec dwie pieczenie na jednym ogniu - poznać NetBeans 6.1 praktycznie i być może zgarnąć nagrodę.

Po ostatnich wpisach dotyczących NetBeans 6.1 BETA i jego funkcjonalności Nowości NetBeans IDE 6.1 - JSF CRUD Generator oraz Nowości NetBeans IDE 6.1 - Spring Framework Support postanowiłem zająć się kolejną nowością - Java Beans Support.

Jak to opisywane jest w zmianach funkcjonalnych NetBeans 6.1 - NetBeans IDE 6.1 Beta Information okazuje się, że jest to funkcjonalność, którą można było znaleźć w poprzednich wersjach NetBeans, jednakże z napiętego harmonogramu prac przy 6.0 ta funkcjonalność została wyłączona. Podobno było tyle zapytań o przywrócenie jej, że w 6.1 ponownie się pojawiła.

Obowiązkowa lektura każdego programisty javowego Java Tutorial w rozdziale Trail: JavaBeans(TM), który przedstawia specyfikację JavaBeans zawiera taką oto notkę:

Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

Czy to oznacza, że przywrócenie wsparcia dla JavaBeans w NetBeans IDE 6.1 deaktualizuje ją? Pewnie tak. Należy, więc oczekiwać zmian w Java Tutorial, chociażby właśnie z tego powodu.

Co, więc możemy znaleźć w owym Java Beans Support? We wspomianym dokumentacie NetBeans IDE 6.1 Beta Information możemy przeczytać:
  • Java Beans Support
    • Bean Patterns in Navigator
    • Generate Bean Property
    • BeanInfo Editor
i niewielki wycinek ekranu z Navigatorem. Dodając do tego dokument NB61NewAndNoteWorthy miałem teoretycznie wszystko (gra słów?), co pozwoliłoby mi rozeznać się w funkcjonalności Java Beans Support. Pozostało jeszcze zajrzeć do pomocy Help > Help Contents i popróbować się z tym praktycznie. Niestety nie mogłem nic tam znaleźć, więc po krótkiej przerwie, w której zapoznałem się ze specyfikacją JavaBeans przeszedłem od razu do ćwiczeń praktycznych.

JavaBeans to specyfikacja modelu dynamicznych komponentów w Javie nazywanych ziarnami. Ich dynamiczność przejawia się w ich możliwości zmiany stanu (wartości ich atrybutów/właściwości) z bogatym mechanizmem zdarzeń o zmianach. Za pomocą mechanizmu prześwietlenia (ang. introspection) reprezentowanego przez klasę java.beans.Introspector istnieje możliwość odczytania cech ziarna - jego właściwości, metod i wspieranych zdarzeń. Wykorzystanie JavaBeans zostało najpierw dostrzeżone przez twórców środowisk programistycznych, gdzie za pomocą wymyślnych asystentów można utworzyć obiekt wybranego typu i określić wartości jego atrybutów (pamiętam, jak spierałem się kiedyś, że JavaBeans to jedynie graficzne komponenty, co okazało się szybko być nieprawdą). Zapomniane JavaBeans przybrały nowe szaty i dzisiaj znamy je jako owe popularne POJO (ang. Plain Old Java Object - stary dobry obiekt javowy). Zapewne możnaby znaleźć wielu progamistów javowych, którzy nie potrafiliby wyjaśnić terminu JavaBeans i dodatkowo myliliby go z technologią Enterprise JavaBeans (EJB), jednakże coś mi mówi, że niewielu byłoby, którzy nie potrafiliby wyjaśnić słowa POJO, bądź podjęliby przynajmniej próbę jego zdefiniowania. Ot taki paradoks technologiczny, gdzie technologia wyprzedziła swoim rozmachem czasy, w których znalazła swoje zastosowanie. Trzeba było kilku lat zanim o JavaBeans (jako POJO) usłyszał już (prawie) każdy.

Pobrałem najnowszą wersję rozwojową NetBeans IDE 6.1 z dnia 5.04.2008. Utworzyłem nowy projekt aplikacji webowej ze wsparciem JSF. Pomysł polegał na utworzeniu przykładowej aplikacji JSF postępujac zgodnie z wytycznymi Łukasza Lenarta w NetBeans 6.1 Beta - pierwsze podejście do JSF jednocześnie wykorzystując wsparcie dla JavaBeans, które jest tematem przewodnim mojego wpisu. Ziarna JavaBeans są w najbardziej podstawowym przedstawieniu zwykłymi klasami z atrybutami (właściwości - pola egzemplarza klasy - z metodami odczytującą i modyfikującą) - popularnymi POJO. "A jaki to ma związek z JavaServer Faces (JSF)?" - możnaby zapytać. Ziarna zarządzane JSF są właśnie ziarnami JavaBeans, więc jeśli JavaBeans to fundament dla funkcjonalności dostarczanej przez aplikację opartą o JSF, to połączenie lektury artykułu Łukasza o JSF (a tym samym poznaniu JSF i jego wsparciu przez NetBeans 6.1) oraz rozpoznaniu możliwości kryjących się pod terminem Java Beans Support daje ciekawą mieszankę technologiczną. Jednym słowem, skrócenie czasu potrzebnego do poznania JSF i wsparciu JavaBeans w NetBeans 6.1 do minimum. Do tego możnaby dodać JPA, które będzie obsługiwało mi mapowanie między światem relacyjnym a obiektowym, gdzie POJO stanowią integralną część - ponownie będzie okazja skorzystać z pomocy NetBeans do utworzenia encji JPA. W przeciwieństwie do artykułu Łukasza, ja skorzystam z domyślnie dystrybuowanej w NetBeans bazy danych Apache Derby (aka Java DB) oraz oddeleguję utworzenie struktur bazodanowych dostawcy JPA. A na co mi się męczyć ze strukturami bazodanowymi, na których delikatnie mówiąc znam się jak na hodowaniu kwiatów, czyli niewiele. Podlać kwiatki, tu przyciąć, czy dodać mieszanki nawozowej jak najbardziej, ale jeśli przyjdzie mi stworzyć jakąś kompozycję kwiatową czy sprowokować kwitnienie - co to, to nie.

Utworzyłem projekt aplikacji webowej korzystającej z JSF jsf-demo z encjami Customer, Item oraz Customer_Item, podobnie jak to zrobił Łukasz w swoim artykule. Kiedy utworzyłem encję Customer (Ctrl+N, Persistence > Entity Class) dostałem ziarno JavaBeans z pojedyńczym atrybutem id. Dodałem następne firstName oraz lastName jak opisywał to Łukasz tyle, że on tworzył je najpierw na poziomie bazy danych i dopiero tworzył klasy encji, a ja zacznę rozpoznawać wsparcie dla JavaBeans i właśnie w tym momencie na scenie pojawia się nowość NetBeans - funkcja Add Property... W ramach klasy Customer, wciskam Alt+INSERT i pojawia mi się menu kontekstowe z menu Add Property.


Wybieram Add Property... i pojawia mi się okienko kontekstowe z możliwością utworzenia właściwości ze wsparciem dla zdarzeń PropertyChange (pole Generate Property Change Support) oraz VetoableChange (pole Generate Vetoable Change Support). Jest to ta cecha JavaBeans, której do tej pory nie stosowałem, a którą zauważyłem, że poleca się jako mechanizm propagowania zmian w encjach za pomocą standardowego mechanizmu JavaBeans.


Uproszczenie wprowadzenia mechanizmów JavaBeans w postaci asystenta Add Property w NetBeans zaliczam do użytecznych i z pewnością nie jest to ostatni moment, w którym z niego korzystam. Na minus mógłbym ocenić konieczność dodawania cudzysłowów w wartości atrybutu o typie String oraz określenie protected jako zakresu widoczności atrybutu zamiast private.

Podobnie postępuję z kolejnym atrybutem encji Customer - lastName.

Tym razem w okienku kontekstowym pojawiło się więcej opcji automatycznego generowania elementów klasy ze względu na nowe elementy encji utworzone przez asystenta Add Property dla atrybutu firstName.


Wypełniam dane atrybutu lastName, gdzie pola Generate Property Change Support oraz Generate Vetoable Change Support są już niedostępne, bo nie są potrzebne, gdyż klasa je już posiada. Kolejny plus.


Podobnie postępuję z encją Item i atrybutami title i description oraz encją CustomerItem.

Po utworzeniu encji mogę skorzystać z kolejnej funkcjonalności z zakresu JavaBeans Support, tj. nawigatorem cech JavaBeans edytowanej klasy (Bean Patterns). Do dyspozycji jest kilka widoków.


i po wybraniu Bean Patterns można spojrzeć na klasę z perspektywy cech JavaBeans (widok Bean Patterns znajduje się w Nawigatorze, który z kolei znajduje się w lewym dolnym rogu na poniższym zrzucie ekranu).


Okazuje się, że wiele ciekawych asystentów jest dostępnych w kategorii JavaBeans Objects i na przykład utworzenie ziarna JavaBeans z udostępnieniem zdarzenia zmiany wartości (Property Change Support) to po prostu wybranie JavaBeans Component.


Kolejną funkcjonalnością opisaną w dokumencie zmian NetBeans 6.1 dostarczaną w ramach JavaBeans Support jest edytor BeanInfo. Specyfikacja JavaBeans udostępnia interfejs java.beans.BeanInfo, za pomocą którego istnieje możliwość określenia wybranych cech ziarna JavaBeans, tj. atrybutach, metod i zdarzeń. Określenie "widoku" JavaBeans naszej klasy nie wymusza określenia go dla każdego elementu, a jedynie wybranego, więc można manipulować widokiem w sposób addytywny (hmm, nie jestem pewien, czy to słowo odpowiada temu, co chcę wyrazić), nakładając jakby filtr na widok wyznaczony przez bezpośrednie prześwietlenie (ang. reflection) klasy.

Utworzenie klasy BeanInfo można zrealizować przez wykorzystanie asystenta BeanInfo dostępnego w Ctrl+N > JavaBeans Objects > BeanInfo. Jak się okazało skorzystanie z asystenta BeanInfo nie umożliwi od razu skorzystania z edytora BeanInfo. Edytor ujawni się wyłącznie po wybraniu asystenta BeanInfo w/o Icon.


Utworzyłem klasę BeanInfo dla encji Customer. Klasa BeanInfo musi nazywać się zgodnie z formatem <NazwaKlasyZiarna>BeanInfo i należeć do tego samego pakietu.


Po utworzeniu klasy BeanInfo automatycznie zostanie otworzony edytor BeanInfo z widokiem Source. Przełączam widok na Designer (przełącznik znajduje się w górnym lewym rogu edytora).


Wyłączenie opcji Get From Introspection powoduje "zapalenie" odpowiednich elementów pod BeanInfo, np. Bean, Properties, itp. Wtedy uaktywniają się inne opcje, w tym możliwość określenia położenia ikon reprezentujących ziarno.


Wybranie opcji Classpath (e.g. /org/netbeans/resources/action.gif) pozwala na wybranie ikony ze ścieżki klas w projekcie. Kolejny plus.


Po włączeniu wszystkich elementów klasy Customer dostarczanej przez klasę BeanInfo (przez odznaczenie opcji Get From Introspection w Bean, Properties Event Sources oraz Methods) zrobiło się niezwykle kolorowo ;-)


Mam wrażenie, że chociażby poprzez brak pomocy kontekstowej, wiele jest jeszcze do zrobienia w funkcjonalności JavaBeans Support przed wydaniem finalnej wersji NetBeans IDE 6.1. Na swoim przykładzie mogę śmiało stwierdzić, że pomoc kontekstowa w przypadku tego typu funkcjonalności jest niezwykle istotna, bo jakkolwiek dotykamy podstawowej funkcjonalności w Javie, to jej wykorzystanie nie jest powszechne, a udostępniane wsparcie w NetBeans ciekawe acz tajemnicze. Jak już wcześniej wspominałem dla mnie skorzystanie ze wsparcia manipulowania klasami typu JavaBeans nie jest ostatnim i z pewnością znajdzie się więcej miejsca dla niego w moich poczynaniach programistycznych z NetBeans i publikacjach. Trochę informacji o postępie prac mogłem znaleźć w dokumencie Beans_90907Experiment.

Wracając do artykułu Łukasza, skończyłem w momencie utworzenia stron JSF na bazie encji JPA za pomocą asystenta JSF Pages from Entity Classes. Mając strony JSF i dokonując kilku modyfikacjach opisanych przez Łukasza w jego artykule aplikacja jest gotowa do użycia. Pozostałe kroki są identyczne z Łukaszowymi. Na tym przykładzie można zauważyć ciekawe podejście do nauki JSF w zaleźności od wcześniejszej znajomości baz danych bądź technologi wspierających jak JPA. Łukasz podszedł do tematu bazodanowo, co określa się często mianem bottom-up, gdzie baza danych jest graczem pierwszoplanowym, podczas gdy moje podejście nazwałbym top-down, gdzie baza jest, ale utworzeniem jej struktur zajmuje się inna technologia Korporacyjnej Javy 5 (Java EE 5) - Java Persistence API, która jest częścią EJB 3.0. Teraz mamy dwa podejścia, a Ty masz wybór, które podejście jest przyjemniejsze. Efekt końcowy jest ten sam, ale stany pośrednie już nie. Podoba mi się, że Łukasz podjął wyzwanie i stanął w konkursie. Obiecuje się ciekawa potyczka ;-)

Pytanie dla wytrwałych: Do czego służy klasa java.beans.BeanInfo? Nagrodą jest wejściówka na JAVArsovia 2008 całkowicie za darmo.