Kilkakrotnie pytano mnie o tematy prac inżynierskich i magisterskich, a wtedy zaczyna się główkowanie, który byłby tym jedynym, interesującym. Kiedy wyszła Java EE 5 byłem zachwycony zmianami, podobnie z JEE6. Było też zainteresowanie OSGi i okolicami, teraz programowanie funkcyjne z Clojure, a w odwodzie kilka innych, mniej lub bardziej ciekawych zagadnień. Nawet dzisiaj zostałem poproszony o wyznaczenie tematów do przedstawienia studentom w ramach praktyk studenckich w IBM i w mgnieniu oka miałem 10 sztywno określonych i jeden otwarty, który rozpoczynał się od "Rozpoznanie wybranej funkcji* produktu z rodziny IBM WebSphere BPM". Współpraca ze studentami to niezwykle ciekawy i produktywny sposób na poznawanie nowego (człowieka i jego sposobu myślenia oraz samego tematu). Wszyscy zadowoleni.
Postanowiłem rzucić temat wyszukania czegoś ciekawego na bloga licząc, że ktoś ma pomysł w zakresie JavaServer Faces (JSF) 2.0, a boryka się z problemem braku czasu na jego dogłębne rozpoznanie w postaci pracy licencjackiej (to jakby nie patrzeć rok ślęczenia nad tematem!).
Autor ostatniej prośby napisał:
Czy istnieje możliwość nawiązania współpracy w zakresie mojej pracy inżynierskiej, naturalnie związanej z korporacyjną Javą. Chciałbym zrealizować temat nie tylko wartościowy merytorycznie ale i również interesujący z punktu widzenia programisty, wolałbym uniknąć pracy odtwórczej i skupić się na tym co mógłbym poprzez swoją pracę dyplomową wnieść od siebie. Jestem już po wstępnej rozmowie z moim promotorem, z którym rozważaliśmy możliwość podjęcia tematu związanego mniej lub bardziej z JSF 2.0. Wiem, że jesteś otwarty na różnorodne propozycje, dlatego po cichu liczę na email od Ciebie przesiąknięty entuzjazmem, który mnie nie opuszcza nawet na krok podczas rozważań nad tematem mojej pracy.
Na moją odpowiedź, raczej w tonie ostrożnej aprobaty, otrzymałem taką:
Dzięki za zainteresowanie moją propozycją, tak jak już wcześniej wspomniałem chciałbym poprzez swoją pracę dyplomową wnieść coś od siebie. Wykorzystanie JSF2 do zbudowania przykładowej aplikacji webowej jest ostatecznym rozwiązaniem, którego nawet nie chcę brać pod uwagę. Idealnym rozwiązaniem byłby temat oryginalny oraz interesujący.
W kwestii tematu właśnie liczyłbym na Twoją pomoc, z pewnością są zagadnienia związane z JSF2, którymi zainteresowany jesteś najbardziej. Wiedzę w tej dziedzinie masz nieporównywalnie większą niż moja, stąd zapewne mógłbyś zaproponować kilka interesujących pomysłów. Może istnieje jakieś komercyjne narzędzie (lub jego część), które czeka na swoją ogólnodostępną implementację? A może masz zupełnie inny pomysł na temat pracy?
I tutaj pojawiła się moja odpowiedź, już z wstępnym szkicem zakresu technologicznego pracy:
JSF2 jest ciekawe, ale coś mi mówi, że wiele tu już zrobiono i ciekawym mogłoby być użycie innej technologii tworzenia UI niż facelets czy JSP. Przyjrzałbym się jednak bardziej użyciu CDI w JSF i co do tej pory zrobiono. CDI jako rozwiązanie javowe weszło dopiero w JEE6, więc jest bardzo młode i pewnie wiele tutaj do zrobienia. Gdybym miał szukać ciekawego tematu właśnie koło CDI kręciłbym się, może w połączeniu z OSGi?! Właśnie CDI + OSGi wydaje się być nietrywialnym tematem dotykającym dwa rozwiązania. To byłoby cudo techniczne!
Uważacie, że JSF2, CDI i OSGi mogłoby być "produktywnym" stosem technologicznym? Co mógł(a)byś Ty zaproponować delikwentowi? Mnie zawsze intrygowało, czy dałoby się tak użyć JSF, aby zbudować aplikację desktopową? W końcu JSF dotyka warstwy widoku i aplikacje webowe są jedynie/aż implementacją referencyjną demonstrującą oferowane możliwości (albo ich brak) budowania niebagatelnego interfejsu użytkownika. Gdyby relacjonować JSF2, czy byłoby cokolwiek, co stanowiłoby dla Ciebie szczególnie ciekawe zagadnienie? Wszelkie propozycje będą uważnie rozpatrzone, a upublicznione mają niemałe szanse na realizację. Dla mnie będzie to stanowiło magnes do powrotu do Java EE 6, które zeszło na plan drugi po pojawieniu się Clojure, dla Ciebie zrealizowanie pomysłu cudzymi rękoma, a pytającemu zapewnią ciekawe spędzenie czasu przy pracy inżynierskiej. Wszyscy są do przodu!
[*] Dowiedziałem się dzisiaj, że nie ma liczby mnogiej od "funkcjonalność", a można mówić jedynie o funkcjach produktu (!)
Pokazywanie postów oznaczonych etykietą jsf. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą jsf. Pokaż wszystkie posty
18 listopada 2010
03 września 2008
JSF 1.2 - rozdział 7.4 NavigationHandler
Rozdział 7 specyfikacji JavaServer Faces przedstawia API z pakietu javax.faces.application, które stanowi podwaliny dla mechanizmu rozszerzania (w tym i zmiany) zachowania działania szkieletu JSF. Wielokrotnie spotykam się z opinią o bardzo nieprzyjaznym dla programisty rozwiązaniu jakim jest JSF i tyleż samo napotykam w nim interesujących konstrukcji programistycznych. Przykładem możliwości jakie można uzyskać w JSF jako szkielecie aplikacyjnym może być JBoss Seam, którego głównym celem jest (a może jedynie początkowo była) integracja technologi interfejsu użytkownika w Java EE - JavaServer Faces 1.2 - oraz technologii komponentów biznesowych opartych o Enterprise JavaBeans (EJB) 3.0. Dodając do tego projekty facelets oraz RestFaces, którymi parałem się przez ostatnie tygodnie i coraz bardziej intrygowało mnie, co spowodowało, że stało się to możliwe. Wystarczy dostarczyć pewne rozszerzenie (ala wtyczkę) do JSF deklarując w faces-config.xml i już JSF może działać inaczej niż byśmy mogli sobie początkowo wyobrazić. Na pierwszy ogień poszedł javax.faces.application.NavigationHandler, który opisany jest w rozdziale 7.4 NavigationHandler specyfikacji JavaServer Faces 1.2.
NavigationHandler jest to część szkieletu aplikacyjnego JSF uruchamiania do obsługi łańcucha znakowego będącego logicznym identyfikatorem zwróconym przez wykonaną akcję w aplikacji i wybraniem nowego widoku do wyświetlenia. Jeśli wynik akcji jest null ten sam widok, który spowodował wykonanie akcji zostanie ponownie wyświetlony. W zasadzie najlepiej możnaby to uzmysłowić prezentując sygnaturę jedynej metody abstrakcyjnej klasy NavigationHandler:
Implementacja JSF musi dostarczyć domyślną realizację NavigationHandler, który pozwala na zdefiniowanie przepływów (przejść między stronami w aplikacji) w plikach konfiguracyjnych (domyślnie faces-config.xml). Do konfiguracji przepływu służy znacznik <navigation-rule>. Znacznik może zawierać opcjonalny <from-view-id>, który akceptuje wartości wyrażenia regularnego dla aktualnego identyfikatora widoku postaci dosłownej (pełne dopasowanie)
Możliwe jest określenie wielu <navigation-rule> dotyczących tego samego <from-view-id>, ale niepoprawnym jest określenie tej samej kombinacji <from-*> dla danego <from-view-id>.
Zwrócenie null z akcji informuje NavigationHandler, aby nie przeszukiwał reguł i ponownie wyświetlił aktualny widok.
Elementy <from-outcome> oraz <from-action> odpowiadają parametrom wejściowym metody handleNavigation.
Możliwe jest skorzystanie z elementu <redirect/> do określenia przekierowania aktualnego żądania do zadanej strony, po którym następuje zatrzymanie przetwarzania żądania JSF (wywołując javax.faces.context.FacesContext.responseComplete()). Wyjątkiem jest środowisko portletowe, gdzie przekierowania nie są dozwolone.
Znalezienie pasującego widoku powoduje zbudowanie nowego, tracąc stan poprzedniej (uwaga: może być czasochłonne).
Podmiana domyślnego NavigationHandler następuje programowo poprzez wykonanie metody javax.faces.application.Application.setNavigationHandler(NavigationHandler handler) lub deklaratywnie w faces-config.xml w sekcji <application>.
Pozostaje życzyć sobie, żeby konstruowanie nowych kontrolek JSF było równie proste. Jest to bodajże najbardziej pracochłonne zadanie w JSF. Na razie jest nie na moje siły i wydaje się, że jedynie facelets mógłby być panaceum (acz wprowadza własny ViewHandler i znaczniki JSP należy migrować do znaczników facelets, co ponownie może być nie lada wyzwaniem).
NavigationHandler jest to część szkieletu aplikacyjnego JSF uruchamiania do obsługi łańcucha znakowego będącego logicznym identyfikatorem zwróconym przez wykonaną akcję w aplikacji i wybraniem nowego widoku do wyświetlenia. Jeśli wynik akcji jest null ten sam widok, który spowodował wykonanie akcji zostanie ponownie wyświetlony. W zasadzie najlepiej możnaby to uzmysłowić prezentując sygnaturę jedynej metody abstrakcyjnej klasy NavigationHandler:
public void handleNavigation(FacesContext context, String fromAction, String outcome)Na podstawie przekazanego kontekstu FacesContext oraz wyniku outcome działania akcji fromAction handleNavigation podejmuje decyzję o kolejnej stronie do wyświetlenia.
Implementacja JSF musi dostarczyć domyślną realizację NavigationHandler, który pozwala na zdefiniowanie przepływów (przejść między stronami w aplikacji) w plikach konfiguracyjnych (domyślnie faces-config.xml). Do konfiguracji przepływu służy znacznik <navigation-rule>. Znacznik może zawierać opcjonalny <from-view-id>, który akceptuje wartości wyrażenia regularnego dla aktualnego identyfikatora widoku postaci dosłownej (pełne dopasowanie)
<navigation-rule>, początek widoku (!) zakończonego gwiazdką
<from-view-id>/stworzKategorie.jsp</from-view-id>
<navigation-case>
<from-action>#{kategoriaAgent.stworz}</from-action>
<to-view-id>/wyswietl.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>, gwiazdkę, która określa wszystkie możliwe widoki (strony)
<from-view-id>/stworz*</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/wyswietl.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>lub po prostu bez określenia <from-view-id>, co przekłada się również na dowolny widok:
<from-view-id>*</from-view-id>
<navigation-case>
<from-action>#{kategoriaAgent.stworz}</from-action>
<to-view-id>/wyswietl.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>W ramach <navigation-rule> znajduje się dowolna liczba <navigation-case>, które precyzują dopasowanie.
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/wyswietl.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Możliwe jest określenie wielu <navigation-rule> dotyczących tego samego <from-view-id>, ale niepoprawnym jest określenie tej samej kombinacji <from-*> dla danego <from-view-id>.
Zwrócenie null z akcji informuje NavigationHandler, aby nie przeszukiwał reguł i ponownie wyświetlił aktualny widok.
Elementy <from-outcome> oraz <from-action> odpowiadają parametrom wejściowym metody handleNavigation.
Możliwe jest skorzystanie z elementu <redirect/> do określenia przekierowania aktualnego żądania do zadanej strony, po którym następuje zatrzymanie przetwarzania żądania JSF (wywołując javax.faces.context.FacesContext.responseComplete()). Wyjątkiem jest środowisko portletowe, gdzie przekierowania nie są dozwolone.
<navigation-rule>Brak <navigation-rule>, która pasuje do parametrów metody handleNavigation nie zmienia aktualnego widoku (podobnie jak wartość null).
<from-view-id>/stworz*</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/wyswietl.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/failure.jsp</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
Znalezienie pasującego widoku powoduje zbudowanie nowego, tracąc stan poprzedniej (uwaga: może być czasochłonne).
Podmiana domyślnego NavigationHandler następuje programowo poprzez wykonanie metody javax.faces.application.Application.setNavigationHandler(NavigationHandler handler) lub deklaratywnie w faces-config.xml w sekcji <application>.
<application>Można wyobrazić sobie implementację, której konfigurację przepływów definiujemy w faces-config.xml oraz bazie danych. Dobrym źródłem wiedzy nt. temat będzie z pewnością wątek How the way for create a new NavigationHandler w stosunkowo młodym forum GlassFish WebTier. Możnaby również oprzeć NavigationHandler na regułach pisanych w Groovy czy umożliwić kreowanie przepływów z poziomu interfejsu użytkownika. Chętnie zapoznałbym się z wdrożonymi pomysłami.
<navigation-handler>klasa.realizujaca.NavigationHandler</navigation-handler>
</application>
Pozostaje życzyć sobie, żeby konstruowanie nowych kontrolek JSF było równie proste. Jest to bodajże najbardziej pracochłonne zadanie w JSF. Na razie jest nie na moje siły i wydaje się, że jedynie facelets mógłby być panaceum (acz wprowadza własny ViewHandler i znaczniki JSP należy migrować do znaczników facelets, co ponownie może być nie lada wyzwaniem).
20 sierpnia 2008
Operatory . i [] w JSF 1.2 i egzamin JSF 1.1 - Basic na javaBLACKbelt
Podczas lektury książki o facelets (cf. Book review: Facelets) pojawiło się kilka przykładów konstrukcji Unified EL typu #{bean['value']}. Dla przypomnienia, Unified EL jest językiem wyrażeń wspólnym dla JSF 1.2 i JSP 2.1 (co za zbieg okoliczności z tymi numerami!). W zasadzie, to zgodnie z zapisami w specyfikacji JSF 1.2, rozdział 1.3.7 package javax.faces.el:
As of version 1.2 of this specification, all classes and interfaces in this package have been deprecated in favor of the Unified Expression Language (EL) from JSP 2.1.
Please see Chapter 5 "Expression Language and Managed Bean Facility".
Co oznacza ni mniej, ni więcej, że język wyrażeń JSF zmigrował (upodobnił się) do języka wyrażeń w JSP 2.1. Jako uzupełnienie dodam, że w rozdziale 5 Expression Language and Managed Bean Facility specyfikacji JSF 1.2 napisano:
JavaServer Faces relies on the Unified Expression Language (Unified EL, or just EL) provided by version 2.1 of the JavaServer Pages specification. The EL is described in a separate specification document delivered as part of the JSP 2.1 spec. Please consult that document for complete details about the EL.
Zaglądając do specyfikacji Expression Language Specification Version 2.1 (A component of the JavaServer Pages Specification Version 2.1), do rozdziału 1.6 Operators [] and . znalazłem to, czego nie mogłem zrozumieć podczas lektury książki Facelets:
The EL follows ECMAScript in unifying the treatment of the . and [] operators.
expr-a.identifier-b is equivalent to expr-a["identifier-b"];
I właśnie to było powodem mojego braku zrozumienia zapisów ${bean[items]} (tym razem wyrażenie JSP ze względu na użycie dolara '$' jako wyróżnika, kto - JSP vs JSF - i kiedy będzie interpretował wyrażenie) z książki. Sądziłem do tej pory, że wspomniana konstrukcja #{bean['value']} jest zarezerwowana wyłącznie dla atrybutów ziaren zarządzanych, których typem jest mapa (java.util.Map), czyli konstrukcja #{bean.localeMap.pl} jest równoznaczna z #{bean.localeMap['pl']}, gdzie bean dostarcza metody public Map getLocaleMap(). Teraz już wiem, że bean['value'] odpowiada bean.value, czyli (najczęściej) wykonaniu metody bean.getValue(). Należałoby wspomnieć, że realizacja rozwiązania wyrażenia pozostawia się w JSF obiektowi typu javax.el.ELResolver (więcej o nim w rozdziale 5.5.2 ELResolver specyfikacji JSF 1.2).
I zapewne nie pisałbym o tym, gdyby nie fakt, że znalazłem się dzisiaj na javaBLACKbelt i zachciało mi się egzaminu. Przeglądając listę egzaminów trafiłem na egzamin JSF 1.1 - Basic, który początkowo oblałem (już nie pamiętam kiedy i dlaczego, ale wprost nie mogłem uwierzyć, że wciąż jest na liście do poprawki). Dzisiaj był ten dzień, kiedy postanowiłem popróbować się z nim ponownie. I warto było! Bodajże 3. pytanie właśnie dotknęło wspomnianego tematu operatorów . i [] autorstwa Piotra Kowalskiego (!):
Poza tym jednym pytaniem od Piotra, dostałem jeszcze kolejne jego 4 pytania (dwa dotyczyły javax.faces.CONFIG_FILES) i muszę przyznać, że były na na prawdę wysokim poziomie. Gratulacje! Widać gość zna się na rzeczy. Na swoje jedno również trafiłem i może dlatego ostatecznie zakończyłem egzamin z wynikiem 22/ 24 = 91%. Pozostało 7 punktów do niebieskiego pasa (!), a przede mną darmowe Java SE Base API - Intermed, Java 5 New Language Features oraz XML Core - Basic.
Na koniec mojej przygody ze specyfikacją "Expression Language Specification Version 2.1" całkiem przypadkowo trafiłem na rozdział 1.17 Enums dotyczący typów wyliczeniowych (enum). Dowiedziałem się w nim o nieznanej mi wcześniej metodzie
Pytanie konkursowe: W jaki sposób rozróżnia się wyrażenia JSF i JSP?
As of version 1.2 of this specification, all classes and interfaces in this package have been deprecated in favor of the Unified Expression Language (EL) from JSP 2.1.
Please see Chapter 5 "Expression Language and Managed Bean Facility".
Co oznacza ni mniej, ni więcej, że język wyrażeń JSF zmigrował (upodobnił się) do języka wyrażeń w JSP 2.1. Jako uzupełnienie dodam, że w rozdziale 5 Expression Language and Managed Bean Facility specyfikacji JSF 1.2 napisano:
JavaServer Faces relies on the Unified Expression Language (Unified EL, or just EL) provided by version 2.1 of the JavaServer Pages specification. The EL is described in a separate specification document delivered as part of the JSP 2.1 spec. Please consult that document for complete details about the EL.
Zaglądając do specyfikacji Expression Language Specification Version 2.1 (A component of the JavaServer Pages Specification Version 2.1), do rozdziału 1.6 Operators [] and . znalazłem to, czego nie mogłem zrozumieć podczas lektury książki Facelets:
The EL follows ECMAScript in unifying the treatment of the . and [] operators.
expr-a.identifier-b is equivalent to expr-a["identifier-b"];
I właśnie to było powodem mojego braku zrozumienia zapisów ${bean[items]} (tym razem wyrażenie JSP ze względu na użycie dolara '$' jako wyróżnika, kto - JSP vs JSF - i kiedy będzie interpretował wyrażenie) z książki. Sądziłem do tej pory, że wspomniana konstrukcja #{bean['value']} jest zarezerwowana wyłącznie dla atrybutów ziaren zarządzanych, których typem jest mapa (java.util.Map), czyli konstrukcja #{bean.localeMap.pl} jest równoznaczna z #{bean.localeMap['pl']}, gdzie bean dostarcza metody public Map getLocaleMap(). Teraz już wiem, że bean['value'] odpowiada bean.value, czyli (najczęściej) wykonaniu metody bean.getValue(). Należałoby wspomnieć, że realizacja rozwiązania wyrażenia pozostawia się w JSF obiektowi typu javax.el.ELResolver (więcej o nim w rozdziale 5.5.2 ELResolver specyfikacji JSF 1.2).
I zapewne nie pisałbym o tym, gdyby nie fakt, że znalazłem się dzisiaj na javaBLACKbelt i zachciało mi się egzaminu. Przeglądając listę egzaminów trafiłem na egzamin JSF 1.1 - Basic, który początkowo oblałem (już nie pamiętam kiedy i dlaczego, ale wprost nie mogłem uwierzyć, że wciąż jest na liście do poprawki). Dzisiaj był ten dzień, kiedy postanowiłem popróbować się z nim ponownie. I warto było! Bodajże 3. pytanie właśnie dotknęło wspomnianego tematu operatorów . i [] autorstwa Piotra Kowalskiego (!):
#{bean.value}
is the same as
#{bean['value']}I kiedy zobaczyłem je, od razu mnie olśniło! Odpowiedź jest...nie, nie odpowiem wprost i tak już wszystko wiadome, więc po co odkrywać Amerykę skoro dawno odkryta ;-) Teraz i Ty będziesz znał(a) odpowiedź! Może pora na podejście do JSF 1.1 - Basic? Pochwal się wynikiem i czy trafiłeś/-aś na wspomniane pytanie.Poza tym jednym pytaniem od Piotra, dostałem jeszcze kolejne jego 4 pytania (dwa dotyczyły javax.faces.CONFIG_FILES) i muszę przyznać, że były na na prawdę wysokim poziomie. Gratulacje! Widać gość zna się na rzeczy. Na swoje jedno również trafiłem i może dlatego ostatecznie zakończyłem egzamin z wynikiem 22/ 24 = 91%. Pozostało 7 punktów do niebieskiego pasa (!), a przede mną darmowe Java SE Base API - Intermed, Java 5 New Language Features oraz XML Core - Basic.
Na koniec mojej przygody ze specyfikacją "Expression Language Specification Version 2.1" całkiem przypadkowo trafiłem na rozdział 1.17 Enums dotyczący typów wyliczeniowych (enum). Dowiedziałem się w nim o nieznanej mi wcześniej metodzie
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)Przykład użycia to (przykład ze specyfikacji) ${mySuit == 'Spade'}, który uruchomiłby Enum.valueOf(Suit.class, 'Spade'), który z kolei zwróciłby wartość Suit.Spade typu wyliczeniowego Suit. Nie wiem do tej pory, dlaczego zrobiła na mnie takie wrażenie, ale coś mi mówi, że kiedyś takiej metody poszukiwałem. Dodatkowo warto zapoznawać się z tego typu metodami, gdyż przyzwyczajają (= uczą obcować) z typami generycznymi (szablonowymi?), których mistrzami niewielu mogłoby się nazwać (dobrym materiałem szkoleniowym są z pewnością dwie pozycje - Java Generics FAQs - Frequently Asked Questions oraz Generics in the Java Programming Language, których całkowicie nie udało mi się jeszcze "skonsumować").
Pytanie konkursowe: W jaki sposób rozróżnia się wyrażenia JSF i JSP?
24 lipca 2008
faces-config.xml podzielony z javax.faces.CONFIG_FILES
Zgodnie ze specyfikacją JavaServer Faces 1.2 (rozdział 10.4.2 Application Startup Behavior, strona 312) podczas uruchamiania aplikacji webowej korzystającej z JSF implementacja JSF wykonuje następujące kroki konfiguracyjne:
Najbardziej zaintrygował mnie krok 3, o którym już ktoś mi wcześniej wspominał, jako sposobie na podział rozrastającego się faces-config.xml na mniejsze pliki składowe. Z pewnością zarządzanie mniejszymi plikami jest prostsze, więc możliwość podziału faces-config.xml na mniejsze pliki konfiguracyjne jest wartościową informacją.
Możemy, więc posiadać wiele plików konfiguracyjnych w formacie faces-config.xml, które definiujemy w deskryptorze wdrożenia aplikacji webowej - /WEB-INF/web.xml następująco:
Pozostaje sprawdzenie, czy taki podział konfiguracji JSF jest wspierany przez środowiska programistyczne. Sprawdziłem NetBeans 6.5 i muszę przyznać, że mam dobrą i złą wiadomość. Zacznę od tej złej - jedynie faces-config.xml jest specjalnie traktowany jako plik konfiguracyjny JSF przez edytor PageFlow (pisałem o nim w NetBeans 6 i jego edytor PageFlow do faces-config.xml). Dobra wiadomość jest taka, że tworząc ziarno zarządzane przez asystenta JSF Managed Bean w polu Configuration File widnieją nasze pliki konfiguracyjne JSF.
Nie obyło się bez zgłoszenia kilku błędów odnośnie wsparcia javax.faces.CONFIG_FILES, jak np. Issue #141444 [65cat] Configuration Files without all javax.faces.CONFIG_FILES, gdzie w Configuration Files jedynie wymieniony jest pierwszy z listy plików w javax.faces.CONFIG_FILES oraz faces-config.xml.
Zastanawiam się, jak szeroko stosowana jest owa funkcjonalność JSF podziału pliku konfiguracyjnego faces-config.xml w projektach. Zdarzyło się u Ciebie? Chętnie zapoznałbym się z powodem takiego podziału - łatwość zarządzania, czy coś więcej?
- (opcjonalnie) sprawdza istnienie definicji servletu javax.faces.webapp.FacesServlet w deskryptorze wdrożenia i w przypadku jego braku może w tym momencie zakończyć pracę
- poszukuje META-INF/faces-config.xml we wszystkich zasobach aplikacji webowej (poprzez odpytanie ServletContext o wszystkie dostępne zasoby, jak pliki jar, czy zawartość WEB-INF/classes) i wczytuje je jako plik konfiguracyjny JSF w odwrotnej kolejności do tej zwróconej przez Thread.getContextClassloader().getResources())
- sprawdza istnienie parametru kontekstowego javax.faces.CONFIG_FILES, który jest listą plików konfiguracyjnych oddzielonych przecinkiem, a następnie wczytuje je kolejno
- sprawdza istnienie pliku /WEB-INF/faces-config.xml w aplikacji webowej
<?xml version="1.0"?>gdzie każdy z elementów wpływa na konfigurację naszej aplikacji webowej korzystającej z JBoss Seam (i niewprost z JSF). Przy okazji okazało się, że plik jboss-seam.jar zawiera również plik META-INF/ejb-jar.xml, co określa go również jako moduł EJB.
<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<factory>
<application-factory>org.jboss.seam.jsf.SeamApplicationFactory</application-factory>
</factory>
<application>
<navigation-handler>org.jboss.seam.jsf.SeamNavigationHandler</navigation-handler>
<view-handler>org.jboss.seam.jsf.SeamViewHandler</view-handler>
<state-manager>org.jboss.seam.jsf.SeamStateManager</state-manager>
<el-resolver>org.jboss.seam.el.SeamELResolver</el-resolver>
<message-bundle>org.jboss.seam.core.SeamResourceBundle</message-bundle>
</application>
<lifecycle>
<phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener>
</lifecycle>
</faces-config>
Najbardziej zaintrygował mnie krok 3, o którym już ktoś mi wcześniej wspominał, jako sposobie na podział rozrastającego się faces-config.xml na mniejsze pliki składowe. Z pewnością zarządzanie mniejszymi plikami jest prostsze, więc możliwość podziału faces-config.xml na mniejsze pliki konfiguracyjne jest wartościową informacją.
Możemy, więc posiadać wiele plików konfiguracyjnych w formacie faces-config.xml, które definiujemy w deskryptorze wdrożenia aplikacji webowej - /WEB-INF/web.xml następująco:
<?xml version="1.0" encoding="UTF-8"?>Daje to ciekawą możliwość nadpisywania konfiguracji, np. produkcyjnej testową lub podobnie, gdzie poszczególne definicje ziaren zarządzanych JSF w produkcyjny-faces-config.xml są nadpisane przez faces-config.xml w katalogu WEB-INF. Po wykonaniu testów funkcjonalnych można po prostu usunąć plik WEB-INF/faces-config.xml i wdrożyć aplikację na właściwe środowisko testowe.
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/produkcyjny-faces-config.xml, /WEB-INF/inny-faces-config.xml</param-value>
</context-param>
</web-app>
Pozostaje sprawdzenie, czy taki podział konfiguracji JSF jest wspierany przez środowiska programistyczne. Sprawdziłem NetBeans 6.5 i muszę przyznać, że mam dobrą i złą wiadomość. Zacznę od tej złej - jedynie faces-config.xml jest specjalnie traktowany jako plik konfiguracyjny JSF przez edytor PageFlow (pisałem o nim w NetBeans 6 i jego edytor PageFlow do faces-config.xml). Dobra wiadomość jest taka, że tworząc ziarno zarządzane przez asystenta JSF Managed Bean w polu Configuration File widnieją nasze pliki konfiguracyjne JSF.
Nie obyło się bez zgłoszenia kilku błędów odnośnie wsparcia javax.faces.CONFIG_FILES, jak np. Issue #141444 [65cat] Configuration Files without all javax.faces.CONFIG_FILES, gdzie w Configuration Files jedynie wymieniony jest pierwszy z listy plików w javax.faces.CONFIG_FILES oraz faces-config.xml.
Zastanawiam się, jak szeroko stosowana jest owa funkcjonalność JSF podziału pliku konfiguracyjnego faces-config.xml w projektach. Zdarzyło się u Ciebie? Chętnie zapoznałbym się z powodem takiego podziału - łatwość zarządzania, czy coś więcej?
18 lipca 2008
NetBeans 6 i jego edytor PageFlow do faces-config.xml
Pamiętam, że już jakiś czas tematu zastanawiałem się nad zastosowaniem edytora PageFlow do edycji faces-config.xml - główny plik konfiguracyjny aplikacji JavaServer Faces (JSF). Dzisiaj natrafiłem na wpis, który sprowokował mnie do zbadania tego tematu dokładniej. I warto było, bo kolejny temat mam z głowy. W końcu! Czy nie masz takich natarczywych tematów, które trapią Cię od wielu dni/tygodni/miesięcy, ale mimo to nie znalazłeś/-aś czasu, aby go rozwiązać?! Ja mam ich kilka i jeden właśnie zszedł z listy.
Głównym zadaniem edytora PageFlow, który służy do edycji pliku faces-config.xml, jest umożliwienie wprowadzania zmian w regułach nawigacyjnych aplikacji JSF w sposób graficzny bez konieczności grzebania się w zawiłościach pliku XML (cf. Page Flow Editor Functional Specification). Udostępnienie tej funkcjonalności po prostu zdejmuje z użytkownika obowiązek znajomości jego składni. I w zasadzie to jest jego główna i jedyna potrzeba korzystania. Skoro mniej musimy znać, aby poprawnie skonfigurować przepływ między stronami w aplikacji JSF, to właśnie to jest jego zaletą i tego oczekiwałbym od IDE.
Garść informacji o edytorze PageFlow dla faces-config.xml znajduje się w dokumencie PageFlow Editor for NetBeans 6.0 i jakkolwiek dotyczy wersji NetBeans 6.0, to niewiele zmieniło się od tego czasu. Dodatkowych informacji, a w zasadzie zrzutu ekranu, który uzmysławia możliwości PageFlow, można znaleźć we wpisie Net Beans (6.1) Page Flows, ale ponownie zbyt pobieżnie i niewiele. Dopiero podczas lektury tego wpisu zorientowałem się, czego mógłbym faktycznie oczekiwać od PageFlow. Do tej pory moje aplikacje JSF budowane w NetBeans składały się ze zwykłych stron JSP, które zawierały kontrolki JSF. Mówiąc językiem używanych szkieletów webowych, to był to jedynie JavaServer Faces.
Przy takiej konfiguracji PageFlow udostępniał jedynie 3 akcje dla stron JSP.
Zastanawiałem się wciąż po co ten plus po prawej stronie (u góry zakryty przez menu Delete). Kilkakrotnie napotykałem dyskusję dotyczącą Visual Web JavaServer Faces (w skrócie Visual Web) w kontekście budowania aplikacji JSF w NetBeans. Visual Web to zestaw kontrolek JSF, podobnie jak IceFaces, RichFaces, Tomahawk czy Tobago (pewnie jest ich znacznie więcej, ale te mi teraz przychodzą do głowy). Coś mi mówiło, że właśnie tutaj powinienem szukać odpowiedzi. Kiedy dodałem Visual Web JavaServer Faces do kategorii Frameworks we właściwościach projektu projektu JSF strony JSP stworzone jako Visual Web JSF Page były specjalnie traktowane przez NetBeans.
Nadal były stronami JSP, ale poza zmianą wizualną w widoku Projects, która polegała na zmianie ikony związanej ze stronami, do ich edycji mogłem użyć edytora Design, JSP i Java w jednym (czego nie miałem do dyspozycji przy "zwykłych" stronach JSF).
Zmiana również wpłynęła na dostępne menu w PageFlow związane ze stronami typu Visual Web.
Pojawiły się 3 nowe akcje i możliwe stało się wiązanie (tworzenie przepływu/nawigacji) między elementami strony - przycisk (ang. button) jako Add Button, odnośnik (ang. hyperlink) jako Add Hyperlink oraz odnośnik z obrazkiem (ang. image hyperlink) jako Add Image Hyperlink a innymi stronami w aplikacji. Mam wciąż pewne opory przed stosowaniem tego zestawu Visual Web, bo brakuje mi sprawdzenia na ile jest to przenośne między serwerami aplikacyjnymi (np. czy będę mógł uruchomić aplikację zbudowaną z pomocą Visual Web na Apache Geronimo czy WASie) oraz potencjalne problemy podczas integracji z innymi, wspomnianymi wcześniej, zestawami kontrolek JSF. Temat zostawiam do zbadania na później, chyba że ktoś już zna odpowiedź i zechciałby podzielić się wrażeniami.
Ostatecznie PageFlow prezentuje się następująco.
Od razu można zgadnąć, które strony są typu Visual Web, a które "zwykłymi" JSP. I to jest właśnie zagadka na weekend - rozpoznać typy stron na załączonym wyżej zrzucie ekranu. Miłej zabawy!
Głównym zadaniem edytora PageFlow, który służy do edycji pliku faces-config.xml, jest umożliwienie wprowadzania zmian w regułach nawigacyjnych aplikacji JSF w sposób graficzny bez konieczności grzebania się w zawiłościach pliku XML (cf. Page Flow Editor Functional Specification). Udostępnienie tej funkcjonalności po prostu zdejmuje z użytkownika obowiązek znajomości jego składni. I w zasadzie to jest jego główna i jedyna potrzeba korzystania. Skoro mniej musimy znać, aby poprawnie skonfigurować przepływ między stronami w aplikacji JSF, to właśnie to jest jego zaletą i tego oczekiwałbym od IDE.
Garść informacji o edytorze PageFlow dla faces-config.xml znajduje się w dokumencie PageFlow Editor for NetBeans 6.0 i jakkolwiek dotyczy wersji NetBeans 6.0, to niewiele zmieniło się od tego czasu. Dodatkowych informacji, a w zasadzie zrzutu ekranu, który uzmysławia możliwości PageFlow, można znaleźć we wpisie Net Beans (6.1) Page Flows, ale ponownie zbyt pobieżnie i niewiele. Dopiero podczas lektury tego wpisu zorientowałem się, czego mógłbym faktycznie oczekiwać od PageFlow. Do tej pory moje aplikacje JSF budowane w NetBeans składały się ze zwykłych stron JSP, które zawierały kontrolki JSF. Mówiąc językiem używanych szkieletów webowych, to był to jedynie JavaServer Faces.
Przy takiej konfiguracji PageFlow udostępniał jedynie 3 akcje dla stron JSP.
Zastanawiałem się wciąż po co ten plus po prawej stronie (u góry zakryty przez menu Delete). Kilkakrotnie napotykałem dyskusję dotyczącą Visual Web JavaServer Faces (w skrócie Visual Web) w kontekście budowania aplikacji JSF w NetBeans. Visual Web to zestaw kontrolek JSF, podobnie jak IceFaces, RichFaces, Tomahawk czy Tobago (pewnie jest ich znacznie więcej, ale te mi teraz przychodzą do głowy). Coś mi mówiło, że właśnie tutaj powinienem szukać odpowiedzi. Kiedy dodałem Visual Web JavaServer Faces do kategorii Frameworks we właściwościach projektu projektu JSF strony JSP stworzone jako Visual Web JSF Page były specjalnie traktowane przez NetBeans.
Nadal były stronami JSP, ale poza zmianą wizualną w widoku Projects, która polegała na zmianie ikony związanej ze stronami, do ich edycji mogłem użyć edytora Design, JSP i Java w jednym (czego nie miałem do dyspozycji przy "zwykłych" stronach JSF).
Zmiana również wpłynęła na dostępne menu w PageFlow związane ze stronami typu Visual Web.
Pojawiły się 3 nowe akcje i możliwe stało się wiązanie (tworzenie przepływu/nawigacji) między elementami strony - przycisk (ang. button) jako Add Button, odnośnik (ang. hyperlink) jako Add Hyperlink oraz odnośnik z obrazkiem (ang. image hyperlink) jako Add Image Hyperlink a innymi stronami w aplikacji. Mam wciąż pewne opory przed stosowaniem tego zestawu Visual Web, bo brakuje mi sprawdzenia na ile jest to przenośne między serwerami aplikacyjnymi (np. czy będę mógł uruchomić aplikację zbudowaną z pomocą Visual Web na Apache Geronimo czy WASie) oraz potencjalne problemy podczas integracji z innymi, wspomnianymi wcześniej, zestawami kontrolek JSF. Temat zostawiam do zbadania na później, chyba że ktoś już zna odpowiedź i zechciałby podzielić się wrażeniami.Ostatecznie PageFlow prezentuje się następująco.
Od razu można zgadnąć, które strony są typu Visual Web, a które "zwykłymi" JSP. I to jest właśnie zagadka na weekend - rozpoznać typy stron na załączonym wyżej zrzucie ekranu. Miłej zabawy!
05 czerwca 2008
EJB 3.0 Redbook opublikowany i doświadczenia z trinidadowym tr:tree
Podczas mojego wystąpienia o Apache Wicket na konferencji JAVArsovia 2008 publiczność nie pozostała mi dłużna w kontekście dzielenia się wiedzą i w trakcie moich bojów z poprawianiem błędów w edytorze javowym w Eclipse padło z sali: "Skorzystaj z Ctrl+1!". Okazuje się, że człowiek zaoszczędziłby wiele czasu, gdyby zamiast zabawiać się z Ctrl+Spacja, czy podobnie skorzystał po prostu z pomocy Ctrl+1, którą Tomek N. opisał w korespondencji do mnie:
Ctrl+1 działa także gdy w kodzie nie ma błędów, jego semantyka brzmi wtedy "Zrób to, czego w tej chwili potrzebuję" ;-). Podobnie Ctrl+2.
Wiadomo, że najprostsze rzeczy najtrudniej znaleźć, ale jak pokazuje mój przypadek warto podejmować się wyzwań w postaci wystąpień publicznych, bo to, co wczoraj mogło być moją niewiedzą, jutro jest już innych, a ja cieszę się z darmowej wskazówki. Najważniejsze, aby nie ukrywać swojej niewiedzy licząc na pomoc publiczności. Kolejny raz przekonałem się, że było warto. Dzięki Tomek!
Kolejna fajna rzecz przytrafiła mi się wczoraj - opublikowano moją pracę dotyczącą EJB 3.0 w wykonaniu IBM WebSphere Application Server 6.1 - WebSphere Application Server Version 6.1 Feature Pack for EJB 3.0. Wielu pamięta moje relacje z pobytu w US i teraz mogę już upublicznić cel mojej podróży - WebSphere Application Server Version 6.1 Feature Pack for EJB 3.0 aka EJB 3.0 Redbook, czyli pierwsza książka mojego autorstwa. Nie było lekko, ale bardzo przyjemnie, więc nie odczułem wielkiego zmęczenia. Współtworzyłem ją w iście międzynarodowym gronie: Ueli Wahli (Szwajcar), Giuseppe Bottura (Włoch) i Nidhi Singh (Hinduska) w słonecznej Kalifornii. Wiele dobrej zabawy i odpoczynku, co wierzę, że udało się zawrzeć w książce, której lekturę gorąco polecam. Proszę o krytyczne spojrzenie na pracę, której celem ma być przybliżenie EJB 3.0 i jego (jej?) realizacja przez WAS 6.1. Nie byłbym sobą, gdybym w takim momencie nie wspomniał również o nadchodzącym IBM WebSphere Application Server Network Deployment 7.0 Open Beta (WAS7), który dostępny jest w wersji beta na stronie IBM WebSphere software early programs - IBM WebSphere Application Server Network Deployment V7.0 Open Beta. Wspomniałem o nim przy okazji mojego wyjazdu do Sosnowca (IBM WAS 7.0 Open Beta oraz IBM RAD 7.5 Open Beta na moim wykładzie na Uniwersytecie Śląskim w Sosnowcu), gdzie zostałem tłumnie przywitany...w przeważającej większości całkowicie nieprogramującą społeczność (!) Ostatnie przewidywania o potencjalnej dacie pojawienia się wersji produkcyjnej JBoss AS 5.0 nie są imponujące, a tu proszę inni nadrabiają technologiczne straty i zaczynają stanowić wartościową alternatywę (gra słów zamierzona ;-)).
Wczoraj, na Wydziale MIMUW na Banacha 2 miało miejsce spotkanie z panem Andrzejem Blikle - właścicielem firmy cukierniczej A.Blikle i...informatykiem (o specjalności matematyczne podstawy informatyki), profesorem doktorem habilitowanym, członekiem Rady Języka Polskiego i Fundacji Kultury, od 1977 pracownikiem Instytutu Podstaw Informatyki Polskiej Akademii Nauk (za Andrzej Blikle w polskiej Wikipedii). Co za zbieg okoliczności, że można zajmować się i słodyczami, i informatyką (!) Ciekaw jestem ilu z Was wiedziało o matematycznych powiązaniach pana Blikle?! Co mnie najbardziej zaskoczyło podczas spotkania to fakt, że p. Blikle prowadzi comiesięczne i bezpłatne spotkania dotyczące TQM. Dzisiaj, czwartek 5.06.2008, odbędzie się kolejne spotkanie, ale niestety nie wiem gdzie i o której. Warto było wysłuchać prezentacji p. Blikle, na której wspominał o kilku zasadach prowadzenia firmy, których trudno by szukać w wielu - Zasada stałego dokonalenia - Aby doskonałe było to, co klient u nas kupuje, doskonalić musimy wszystko, wszyscy i stale) czy Nie oczekuj perfekcji, oczekuj postępu (za W.E.Demingiem). Takie sympatyczne spotkanie, które prowokuje do myślenia o naszej roli w firmie i sposobie prowadzenia własnej karierze zawodowej.
Wstęp mógł być trochę nużący, więc w myśl "Zasady stałego dokonalenia" czy "Nie oczekuj perfekcji, oczekuj postępu" najwyższa pora zabrać się za popróbowanie się z czymś nowym. Dzisiaj zajmę się Apache Myfaces Trinidad - zbiorem kontrolek i innych dodatków usprawniających aplikacje korzystające z JavaServer Faces, a dokładniej jednej kontrolce Trinidada - tr:tree. Do ostatniego projektu potrzebowałem skorzystać z kontrolki, która modelowałaby strukturę drzewiastą podobną do listy katalogów i zawartych w nich plikach. Idealnym kandydatem była właśnie kontrolka tr:tree. Jedyne co udało mi się do tej pory rozpoznać to zasilenie kontrolki moimi danymi w postaci javax.faces.model.DataModel (dokładniej org.apache.myfaces.trinidad.model.ChildPropertyTreeModel). O modelach zasilających struktury typu h:dataTable czy wspominany tr:tree pisałem w Tabele w JavaServer Faces - znacznik <h:dataTable>.
Tworzę projekt przy pomocy archetypu myfaces-archetype-trinidad (więcej w artykule Deklaratywne bezpieczeństwo w JSF z JAAS i Jetty czy notce Tworzenie projektu aplikacji JSF z pomocą myfaces-archetype-trinidad).
Utworzony projekt pracuje z Javą 1.4, więc zmieniam konfigurację projektu na Javę 5 dodając konfigurację wtyczki maven-compiler-plugin do pom.xml:
Następnie tworzę klasę modelu pl.jaceklaskowski.faces.trinidad.model.Category:
Pytanie konkursowe: Jaka klasa (abstrakcyjna) z JSF jest podstawą dla źródła danych kontrolek JSF - h:dataTable czy tr:tree?
Ctrl+1 działa także gdy w kodzie nie ma błędów, jego semantyka brzmi wtedy "Zrób to, czego w tej chwili potrzebuję" ;-). Podobnie Ctrl+2.
Wiadomo, że najprostsze rzeczy najtrudniej znaleźć, ale jak pokazuje mój przypadek warto podejmować się wyzwań w postaci wystąpień publicznych, bo to, co wczoraj mogło być moją niewiedzą, jutro jest już innych, a ja cieszę się z darmowej wskazówki. Najważniejsze, aby nie ukrywać swojej niewiedzy licząc na pomoc publiczności. Kolejny raz przekonałem się, że było warto. Dzięki Tomek!
Kolejna fajna rzecz przytrafiła mi się wczoraj - opublikowano moją pracę dotyczącą EJB 3.0 w wykonaniu IBM WebSphere Application Server 6.1 - WebSphere Application Server Version 6.1 Feature Pack for EJB 3.0. Wielu pamięta moje relacje z pobytu w US i teraz mogę już upublicznić cel mojej podróży - WebSphere Application Server Version 6.1 Feature Pack for EJB 3.0 aka EJB 3.0 Redbook, czyli pierwsza książka mojego autorstwa. Nie było lekko, ale bardzo przyjemnie, więc nie odczułem wielkiego zmęczenia. Współtworzyłem ją w iście międzynarodowym gronie: Ueli Wahli (Szwajcar), Giuseppe Bottura (Włoch) i Nidhi Singh (Hinduska) w słonecznej Kalifornii. Wiele dobrej zabawy i odpoczynku, co wierzę, że udało się zawrzeć w książce, której lekturę gorąco polecam. Proszę o krytyczne spojrzenie na pracę, której celem ma być przybliżenie EJB 3.0 i jego (jej?) realizacja przez WAS 6.1. Nie byłbym sobą, gdybym w takim momencie nie wspomniał również o nadchodzącym IBM WebSphere Application Server Network Deployment 7.0 Open Beta (WAS7), który dostępny jest w wersji beta na stronie IBM WebSphere software early programs - IBM WebSphere Application Server Network Deployment V7.0 Open Beta. Wspomniałem o nim przy okazji mojego wyjazdu do Sosnowca (IBM WAS 7.0 Open Beta oraz IBM RAD 7.5 Open Beta na moim wykładzie na Uniwersytecie Śląskim w Sosnowcu), gdzie zostałem tłumnie przywitany...w przeważającej większości całkowicie nieprogramującą społeczność (!) Ostatnie przewidywania o potencjalnej dacie pojawienia się wersji produkcyjnej JBoss AS 5.0 nie są imponujące, a tu proszę inni nadrabiają technologiczne straty i zaczynają stanowić wartościową alternatywę (gra słów zamierzona ;-)).
Wczoraj, na Wydziale MIMUW na Banacha 2 miało miejsce spotkanie z panem Andrzejem Blikle - właścicielem firmy cukierniczej A.Blikle i...informatykiem (o specjalności matematyczne podstawy informatyki), profesorem doktorem habilitowanym, członekiem Rady Języka Polskiego i Fundacji Kultury, od 1977 pracownikiem Instytutu Podstaw Informatyki Polskiej Akademii Nauk (za Andrzej Blikle w polskiej Wikipedii). Co za zbieg okoliczności, że można zajmować się i słodyczami, i informatyką (!) Ciekaw jestem ilu z Was wiedziało o matematycznych powiązaniach pana Blikle?! Co mnie najbardziej zaskoczyło podczas spotkania to fakt, że p. Blikle prowadzi comiesięczne i bezpłatne spotkania dotyczące TQM. Dzisiaj, czwartek 5.06.2008, odbędzie się kolejne spotkanie, ale niestety nie wiem gdzie i o której. Warto było wysłuchać prezentacji p. Blikle, na której wspominał o kilku zasadach prowadzenia firmy, których trudno by szukać w wielu - Zasada stałego dokonalenia - Aby doskonałe było to, co klient u nas kupuje, doskonalić musimy wszystko, wszyscy i stale) czy Nie oczekuj perfekcji, oczekuj postępu (za W.E.Demingiem). Takie sympatyczne spotkanie, które prowokuje do myślenia o naszej roli w firmie i sposobie prowadzenia własnej karierze zawodowej.
Wstęp mógł być trochę nużący, więc w myśl "Zasady stałego dokonalenia" czy "Nie oczekuj perfekcji, oczekuj postępu" najwyższa pora zabrać się za popróbowanie się z czymś nowym. Dzisiaj zajmę się Apache Myfaces Trinidad - zbiorem kontrolek i innych dodatków usprawniających aplikacje korzystające z JavaServer Faces, a dokładniej jednej kontrolce Trinidada - tr:tree. Do ostatniego projektu potrzebowałem skorzystać z kontrolki, która modelowałaby strukturę drzewiastą podobną do listy katalogów i zawartych w nich plikach. Idealnym kandydatem była właśnie kontrolka tr:tree. Jedyne co udało mi się do tej pory rozpoznać to zasilenie kontrolki moimi danymi w postaci javax.faces.model.DataModel (dokładniej org.apache.myfaces.trinidad.model.ChildPropertyTreeModel). O modelach zasilających struktury typu h:dataTable czy wspominany tr:tree pisałem w Tabele w JavaServer Faces - znacznik <h:dataTable>.
Tworzę projekt przy pomocy archetypu myfaces-archetype-trinidad (więcej w artykule Deklaratywne bezpieczeństwo w JSF z JAAS i Jetty czy notce Tworzenie projektu aplikacji JSF z pomocą myfaces-archetype-trinidad).
(wybieram pozycję 5 i wciskam Enter zapytany przy Y:).
$ mvn archetype:generate -DarchetypeCatalog=http://myfaces.apache.org \
-DgroupId=pl.jaceklaskowski.faces.trinidad -DartifactId=myfaces-trinidad-tree -Dversion=1.0
Utworzony projekt pracuje z Javą 1.4, więc zmieniam konfigurację projektu na Javę 5 dodając konfigurację wtyczki maven-compiler-plugin do pom.xml:
<plugin>UWAGA: Import projektu do Eclipse z pomocą wtyczki m2clipse kończy się utworzeniem projektu na poziomie Java 1.4, więc mimo powyższej zmiany mogą pojawić się problemy z kompilacją projektu. Należy zmienić konfigurację projektu w Properties > Java Compiler i odznaczyć Enable project specific settings (zakładając, że domyślnie Eclipse pracuje z Java 5 lub wyżej).
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
Następnie tworzę klasę modelu pl.jaceklaskowski.faces.trinidad.model.Category:
package pl.jaceklaskowski.faces.trinidad.model;oraz ziarno zarządzane categoryAgent reprezentowane przez klasę pl.jaceklaskowski.faces.trinidad.CategoryAgent.
import java.util.ArrayList;
import java.util.List;
public class Category {
private long id;
private String name;
private String description;
private Category parent;
private List<Category> children = new ArrayList<Category>();
public Category() {
}
public Category(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Category getParent() {
return parent;
}
public void setParent(Category parent) {
this.parent = parent;
}
public List<Category> getChildren() {
return children;
}
public void setChildren(List<Category> children) {
this.children = children;
}
public void addCategory(Category category) {
this.children.add(category);
}
}
package pl.jaceklaskowski.faces.trinidad;Konfiguracja ziarna categoryAgent w faces-config.xml ("serce" aplikacji facesowej) wygląda następująco:
import java.util.ArrayList;
import java.util.List;
import javax.faces.model.DataModel;
import org.apache.myfaces.trinidad.model.ChildPropertyTreeModel;
import pl.jaceklaskowski.faces.trinidad.model.Category;
public class CategoryAgent {
private long categoryId;
private Category category;
private List<Category> categories = new ArrayList<Category>();
{
Category root = new Category("Korzen");
root.addCategory(new Category("Podkategoria #1"));
root.addCategory(new Category("Podkategoria #2"));
root.addCategory(new Category("Podkategoria #3"));
categories.add(root);
}
private DataModel model = new ChildPropertyTreeModel(categories, "children");
public long getCategoryId() {
return categoryId;
}
public void setCategoryId(long categoryId) {
this.categoryId = categoryId;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public String selectCategory() {
Category selectedCategory = (Category) model.getRowData();
System.out.println("++ Wybrano kategorie o name: " + selectedCategory.getName());
return null;
}
public DataModel getModel() {
return model;
}
public void setModel(DataModel model) {
this.model = model;
}
}
<managed-bean>Zmieniam stronę index.jspx na poniższą, gdzie skorzystam z tr:tree do wyświetlenia dostępnych kategorii i ich powiązań.
<managed-bean-name>categoryAgent</managed-bean-name>
<managed-bean-class>pl.jaceklaskowski.faces.trinidad.CategoryAgent</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>Uwieńczeniem prac są testy - mvn clean jetty:run i otwieram stronę http://localhost:8080/myfaces-trinidad-tree/faces/index.jspx (nie potrafię wytłumaczyć dlaczego Jetty nie respektuje wpisu welcome-file-list w desktyptorze wdrożenia aplikacji webowej, w której jawnie wskazano faces/index.jspx jako jedną z nich i stąd należy wpisać pełną ścieżkę do index.jspx!). Wciśnięcie plusa rozwija węzeł kategorii, natomiast minusa zwija. Poza tym wybór kategorii przez wciśnięcie jej nazwy powoduje wykonanie akcji w aplikacji, która sprowadza się do wyświetlenia komunikatu na konsoli. Wszystko działa jak należy!
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:tr="http://myfaces.apache.org/trinidad">
<jsp:directive.page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" />
<f:view>
<tr:document title="Apache MyFaces Trinidad Archetype Demo">
<tr:form>
<tr:tree var="node" value="#{categoryAgent.model}">
<f:facet name="nodeStamp">
<tr:commandLink text="#{node.name}" action="#{categoryAgent.selectCategory}" />
</f:facet>
</tr:tree>
</tr:form>
</tr:document>
</f:view>
</jsp:root>
Pytanie konkursowe: Jaka klasa (abstrakcyjna) z JSF jest podstawą dla źródła danych kontrolek JSF - h:dataTable czy tr:tree?
24 maja 2008
Deklaratywne bezpieczeństwo w JSF z JAAS i Jetty
Podczas kolejnej wycieczki technologicznej przyszło mi się zmierzyć z tematem, o który byłem pytany wielokrotnie, ale nie znałem odpowiedzi - deklaratywne uwierzytelnianie i autoryzacja w aplikacjach webowych z JSF. W ogóle temat bezpieczeństwa w aplikacjach korporacyjnych był traktowany przeze mnie po macoszemu i nigdy nie doczekał się odpowiedniego traktowania. Aż do dzisiaj, kiedy to postanowiłem nie odpuszczać, aż do znalezienia rozwiązania.
Zadanie: Zabezpieczenie aplikacji webowej opartej o JavaServer Faces (JSF) przed nieuprawnionym dostępem, czyli wprowadzenie mechanizmu deklaratywnego uwierzytelnienia i autoryzacji.
Rozwiązanie znajdziesz w moim nowym artykule Deklaratywne bezpieczeństwo w JSF z JAAS i Jetty. Miłej lektury!
Pytanie konkursowe: Za pomocą jakich 3 głównych elementów deskryptora wdrożenia WEB-INF/web.xml definiuje się bezpieczeństwo deklaratywnie? Nagrodą jest bezpłatny udział w konferencji JAVArsovia 2008 w nadchodzącą sobotę 31 maja 2008. Pamiętaj o rejestracji!
Zadanie: Zabezpieczenie aplikacji webowej opartej o JavaServer Faces (JSF) przed nieuprawnionym dostępem, czyli wprowadzenie mechanizmu deklaratywnego uwierzytelnienia i autoryzacji.
Rozwiązanie znajdziesz w moim nowym artykule Deklaratywne bezpieczeństwo w JSF z JAAS i Jetty. Miłej lektury!
Pytanie konkursowe: Za pomocą jakich 3 głównych elementów deskryptora wdrożenia WEB-INF/web.xml definiuje się bezpieczeństwo deklaratywnie? Nagrodą jest bezpłatny udział w konferencji JAVArsovia 2008 w nadchodzącą sobotę 31 maja 2008. Pamiętaj o rejestracji!
29 kwietnia 2008
Tworzenie projektu aplikacji JSF z pomocą myfaces-archetype-trinidad
Mam wrażenie, że ten tydzień obfituje w rozpoznawanie archetypów mavenowych. Potrzebowałem szybko stworzyć aplikację JSF i mogło być szybko, gdyby nie fakt, że teraz zanim za cokolwiek się zabiorę, to mam tyle opcji, że nie wiem, co ostatecznie wybrać (nie wiem, co gorsze - nie wiedzieć z czego wybrać, bo ma się wiele opcji, czy nie znając żadnej?!). Weźmy jako przykład owe stworzenie aplikacji JSF - mogę skorzystać z NetBeans IDE (Właśnie! Miałem pobrać finalną wersję NetBeans IDE 6.1!), albo Eclipse IDE, albo jeszcze inne IDE, które byłoby dedykowane do pracy z JSF. Mogę również skorzystać z Apache Maven 2 i skorzystać z jednego z wielu archetypów dedykowanych do stworzenia aplikacji JSF dostarczanych przez Apache MyFaces - MyFaces Archetypes for Maven. A to tylko tak na szybko, bo pewnie jest jeszcze kilka innych opcji. Niejednokrotnie jestem pytany o moje wrażenia dotyczące bibliotek kontrolek JSF udostępniane przez MyFaces, więc nie wahając się długo odhaczyłem kolejne zadanie z mojej listy do ewaluacji - sprawdzić utworzenie aplikacji JSF z pomocą archetypu udostępnianego przez MyFaces myfaces-archetype-trinidad.
Archetyp myfaces-archetype-trinidad dostępny jest w repozytorium m2 jako org.apache.myfaces.buildtools.myfaces-archetype-trinidad. Ostatnia wersja to 1.0.1. Jak napisano w MyFaces Archetypes for Maven wystarczy uruchomić mvn archetype:generate -DarchetypeCatalog=http://myfaces.apache.org i wybrać odpowiednią opcję do stworzenia aplikacji JSF z danymi rozszerzeniami - w moim przypadku będzie to 5: remote -> myfaces-archetype-trinidad (Simple Web application using Apache Myfaces and Trinidad).
Warto zauważyć, że pobierana wersja MyFaces Trinidad to 1.2.5, podczas gdy zgodnie ze stroną główną projektu mamy już wersję 1.2.7 (March 16, 2008 - MyFaces Trinidad 1.2.7 Released). Zaraz i tym się zajmę.

Po wpisaniu Jacek Laskowski i wciśnięciu press me pojawiła się kolejna strona z okienkiem dialogowym.

Pozostaje jeszcze uaktualnić wersję Trinidada i ponownie uruchomić. Dla uproszczenia aktualizacji wersji autorzy archetypu umieścili numery wersji w sekcji properties w pliku pom.xml, tak że nie jest konieczna ich aktualizacja w kilku miejscach (można również uruchomić aplikację z poziomu mvn z podaniem wersji z linii poleceń, co ma tę zaletę, że nie modyfikujemy konfiguracji w pom.xml, a możemy bawić się własnymi wersjami). Uaktualniam trinidad.version do 1.2.7
Pytanie konkursowe: Jak nazywa się archetyp do automatycznego tworzenia aplikacji JSF opartej o MyFaces i Trinidad? oraz znacznie trudniejsze: Dlaczego do uruchomienia aplikacji musiałem podać adres http://localhost:8080/myfaces-witajswiecie/faces/index.jspx zamiast http://localhost:8080/myfaces-witajswiecie? Jedno z pytań, które możnaby dodatkowo zadać w kontekście tego wpisu to W jaki sposób uruchomić stworzoną aplikację z wersją Trinidad 1.2.7 bez modyfikacji pom.xml? Nagród nie ma.
Archetyp myfaces-archetype-trinidad dostępny jest w repozytorium m2 jako org.apache.myfaces.buildtools.myfaces-archetype-trinidad. Ostatnia wersja to 1.0.1. Jak napisano w MyFaces Archetypes for Maven wystarczy uruchomić mvn archetype:generate -DarchetypeCatalog=http://myfaces.apache.org i wybrać odpowiednią opcję do stworzenia aplikacji JSF z danymi rozszerzeniami - w moim przypadku będzie to 5: remote -> myfaces-archetype-trinidad (Simple Web application using Apache Myfaces and Trinidad).
jlaskowski@work /cygdrive/c/projs/sandboxTeraz wystarczy jedynie mvn package i uruchomić aplikację z Jetty - mvn jetty:run (w zasadzie to mvn package jest wykonywany przez uruchomieniem Jetty, więc mogłoby być zaniechane).
$ mvn archetype:generate -DarchetypeCatalog=http://myfaces.apache.org
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO] task-segment: [archetype:generate] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:generate]
Choose archetype:
1: remote -> myfaces-archetype-helloworld (Simple Web application using Apache Myfaces)
2: remote -> myfaces-archetype-helloworld-facelets (Simple Web application using Apache Myfaces and Facelets)
3: remote -> myfaces-archetype-helloworld-portlets (Simple Web application using Apache Myfaces and Portlets)
4: remote -> myfaces-archetype-jsfcomponents (Simple JSF Component using Apache Myfaces)
5: remote -> myfaces-archetype-trinidad (Simple Web application using Apache Myfaces and Trinidad)
Choose a number: (1/2/3/4/5): 5
Define value for groupId: : pl.jaceklaskowski.myfaces
Define value for artifactId: : myfaces-witajswiecie
Define value for version: 1.0-SNAPSHOT: : 1.0.0
Define value for package: : pl.jaceklaskowski.myfaces
Confirm properties configuration:
groupId: pl.jaceklaskowski.myfaces
artifactId: myfaces-witajswiecie
version: 1.0.0
package: pl.jaceklaskowski.myfaces
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: myfaces-archetype-trinidad:1.0.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: pl.jaceklaskowski.myfaces
[INFO] Parameter: packageName, Value: pl.jaceklaskowski.myfaces
[INFO] Parameter: basedir, Value: c:\projs\sandbox
[INFO] Parameter: package, Value: pl.jaceklaskowski.myfaces
[INFO] Parameter: version, Value: 1.0.0
[INFO] Parameter: artifactId, Value: myfaces-witajswiecie
...
[INFO] ********************* End of debug info from resources from generated POM ***********************
[INFO] OldArchetype created in dir: c:\projs\sandbox\myfaces-witajswiecie
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
Warto zauważyć, że pobierana wersja MyFaces Trinidad to 1.2.5, podczas gdy zgodnie ze stroną główną projektu mamy już wersję 1.2.7 (March 16, 2008 - MyFaces Trinidad 1.2.7 Released). Zaraz i tym się zajmę.
jlaskowski@work /cygdrive/c/projs/sandbox/myfaces-witajswiecieUruchamiam aplikację.
$ mvn package
...
[INFO] [war:war]
[INFO] Packaging webapp
[INFO] Assembling webapp[myfaces-witajswiecie] in [c:\projs\sandbox\myfaces-witajswiecie\target\myfaces-witajswiecie]
[INFO] Processing war project
[INFO] Webapp assembled in[422 msecs]
[INFO] Building war: c:\projs\sandbox\myfaces-witajswiecie\target\myfaces-witajswiecie.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
jlaskowski@work /cygdrive/c/projs/sandbox/myfaces-witajswiecieOtwieram przeglądarkę na stronie http://localhost:8080/myfaces-witajswiecie/faces/index.jspx i mam podstawową aplikację JSF z wykorzystaniem MyFaces Trinidad.
$ mvn -PjettyConfig clean jetty:run
...
[INFO] [jetty:run]
[INFO] Configuring Jetty for project: A custom project using myfaces
[INFO] Webapp source directory = C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp
[INFO] web.xml file = C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp\WEB-INF\web.xml
[INFO] Classes = C:\projs\sandbox\myfaces-witajswiecie\target\classes
2008-04-28 22:53:59.273::INFO: Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /myfaces-witajswiecie
[INFO] Tmp directory = determined at runtime
[INFO] Web defaults = org/mortbay/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
[INFO] Webapp directory = C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp
[INFO] Starting jetty 6.1.8 ...
2008-04-28 22:53:59.351::INFO: jetty-6.1.8
2008-04-28 22:53:59.491::INFO: No Transaction manager found - if your webapp requires one, please configure one.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.PRETTY_HTML' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.ALLOW_JAVASCRIPT' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.RENDER_VIEWSTATE_ID' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.STRICT_XHTML_LINKS' found, using default value true
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getLongInitParameter
INFO: No context init parameter 'org.apache.myfaces.CONFIG_REFRESH_PERIOD' found, using default value 2
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig getBooleanInitParameter
INFO: No context init parameter 'org.apache.myfaces.VIEWSTATE_JAVASCRIPT' found, using default value false
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig createAndInitializeMyFacesConfig
INFO: Tomahawk jar not available. Autoscrolling, DetectJavascript, AddResourceClass and CheckExtensionsFilter are disabled now.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.config.MyfacesConfig createAndInitializeMyFacesConfig
INFO: Starting up Tomahawk on the MyFaces-JSF-Implementation
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator feedStandardConfig
INFO: Reading standard config META-INF/standard-faces-config.xml
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator feedClassloaderConfigurations
INFO: Reading config
jar:file:/C:/.m2/org/apache/myfaces/trinidad/trinidad-impl/1.2.5/trinidad-impl-1.2.5.jar!/META-INF/faces-config.xml
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator feedWebAppConfig
INFO: Reading config /WEB-INF/faces-config.xml
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: Starting up MyFaces-package : myfaces-api in version : 1.2.2 from path :
file:/C:/.m2/org/apache/myfaces/core/myfaces-api/1.2.2/myfaces-api-1.2.2.jar
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: Starting up MyFaces-package : myfaces-impl in version : 1.2.2 from path :
file:/C:/.m2/org/apache/myfaces/core/myfaces-impl/1.2.2/myfaces-impl-1.2.2.jar
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: MyFaces-package : tomahawk-sandbox not found.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.config.FacesConfigurator logMetaInf
INFO: MyFaces-package : tomahawk not found.
Apr 28, 2008 10:54:00 PM org.apache.myfaces.shared_impl.util.LocaleUtils toLocale
WARNING: Locale name in faces-config.xml null or empty, setting locale to default locale : en_PL
Apr 28, 2008 10:54:01 PM org.apache.myfaces.config.FacesConfigurator handleSerialFactory
INFO: Serialization provider : class org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory
Apr 28, 2008 10:54:01 PM org.apache.myfaces.webapp.AbstractFacesInitializer initFaces
INFO: ServletContext 'C:\projs\sandbox\myfaces-witajswiecie\src\main\webapp\' initialized.
2008-04-28 22:54:01.739::INFO: Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 10 seconds.

Po wpisaniu Jacek Laskowski i wciśnięciu press me pojawiła się kolejna strona z okienkiem dialogowym.

Pozostaje jeszcze uaktualnić wersję Trinidada i ponownie uruchomić. Dla uproszczenia aktualizacji wersji autorzy archetypu umieścili numery wersji w sekcji properties w pliku pom.xml, tak że nie jest konieczna ich aktualizacja w kilku miejscach (można również uruchomić aplikację z poziomu mvn z podaniem wersji z linii poleceń, co ma tę zaletę, że nie modyfikujemy konfiguracji w pom.xml, a możemy bawić się własnymi wersjami). Uaktualniam trinidad.version do 1.2.7
<trinidad.version>1.2.7</trinidad.version>i ponownie uruchamiam aplikację. Też działa! Aplikacja jest gotowa do rozbudowania. Dalej to już czyste programowanie w JSF z MyFaces Trinidad, tym razem jednak już zapewne z pomocą jakiegoś IDE. Zawsze krążyłem koło kontrolek Trinidad, aby rozpoznać co oferują, więc teraz nadarza się okazja i to zadanie wykreślić z listy oczekujących.
Pytanie konkursowe: Jak nazywa się archetyp do automatycznego tworzenia aplikacji JSF opartej o MyFaces i Trinidad? oraz znacznie trudniejsze: Dlaczego do uruchomienia aplikacji musiałem podać adres http://localhost:8080/myfaces-witajswiecie/faces/index.jspx zamiast http://localhost:8080/myfaces-witajswiecie? Jedno z pytań, które możnaby dodatkowo zadać w kontekście tego wpisu to W jaki sposób uruchomić stworzoną aplikację z wersją Trinidad 1.2.7 bez modyfikacji pom.xml? Nagród nie ma.
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ć:
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.
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
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.
04 kwietnia 2008
Własny JSF renderer oraz krótka przygoda z NetBeans Eclipse Importer
Dostałem zadanie od Andrzeja K., który poprosił mnie o napisanie artykułu "odnośnie renderkit-ów w JSF". Kiedyś tam czytałem na ten temat, ale nic poza tym i dodając do tego, że trochę minęło od mojej ostatniego spotkania z JSF postanowiłem przyjąć "zaproszenie". Rozpocząłem lekturę specyfikacji JSF 1.2, szczególnie rozdziału 8. Rendering Model. Okazało się, że lektura specyfikacji to jedno, a uruchomienie przykładu to drugie. Najbardziej istotne znaczenie ma z jaką implementacją przyjdzie nam pracować. Ja zacząłem od Apache MyFaces 1.2.2, które dystrybuowane jest z Apache Geronimo 2.1. Do pracy potrzebne było mi IDE i padło na Eclipse 3.3.2 z wtyczką Geronimo Eclipse Plugin (GEP).
Utworzyłem projekt typu Dynamic Web Project z rozszerzeniem JSF i utworzyłem stronę index.jsp.
Kilka słów wyjaśnienia, po co i dlaczego tak. Postawione zadanie polegało na stworzeniu renderera dla dostarczanej domyślnie przez JSF kontrolki h:outputText. Każda kontrolka JSF ma związany z nią renderer, który wie, w jaki sposób wyrysować ją w danym środowisku graficznym, np. przeglądarce HTML. Można sobie wyobrazić sytuację, w której chcielibyśmy stworzyć renderera dla technologii Mozilla XUL, PDF, czy SWT/JFace, czy innych. Zaletą tworzenia aplikacji opartych o JSF jest to, że nie zależy ona od sposobu wyświetlania (renderowania) i to właśnie rendererowi pozostawia się obowiązek jej wyrysowywania. Twórca aplikacji JSF odpowiada (jedynie) za rozkład elementów - kontrolek JSF - na stronie. Specyfikacja JSF zobowiązuje dostawców implementacji JSF, aby domyślny zestaw rendererów dla kompletu kontrolek JSF obsługiwał HTML. Wsparcie dla innych technologi wyrysowywania pozostawione są w gestii danej implementacji JSF.
Po kilku nieudanych próbach uruchomienia przykładu było już wiadomo, że wtopiłem. Renderer nie działał (!) Zacząłem poszukiwać odpowiedzi w źródłach MyFaces i zapoznałem się z artykułem Extending Trinidad’s default renderers. Niestety nic nie pomogło. Kompletnie zniechęcony napisałem na grupę użytkowników Apache MyFaces przedstawiając mój problem - Custom renderer for h:outputText - possible?. Niestety, mając nadzieję, że otrzymam odpowiedź w krótkim czasie, po dniu zniechęcony postanowiłem napisać na forum Web Tier APIs - JavaServer Faces na Sun Forums - Custom renderer for h:outputText - possible?. Tam odpowiedź nadeszła w przeciągu 2 godzin (!) Okazało się, że problemem mogła być implementacja JSF, którą do tej pory był Apache MyFaces, a sugerowano użycie JSF RI dystrybuowanego przez GlassFisha.
Yes it is possible. Have you tried running your code on GlassFish to rule out an implementation bug in MyFaces or Geronimo? You can download glassfish and deploy your web application directly on it to test: https://glassfish.dev.java.net/public/downloadsindex.html
Good luck!
Ken Paulsen
https://jsftemplating.dev.java.net
Zaraz wziąłem się za próbowanie z NetBeans IDE 6.1 (wersja rozwojowa) i GlassFish. Ku mojemu zdziwieniu...nie jeszcze tego nie napiszę, to byłoby jak poznać zakończenie kryminału zanim się jeszcze zacznie go czytać ;-)
Utworzyłem projekt w NetBeans i już miałem przełożyć klasy z projektu w Eclipse, kiedy przypomniałem sobie, aby właśnie w tym momencie popróbować się z wtyczką Eclipse Project Importer do importowania projektów z Eclipse do NetBeans. Lektura Migrating your Eclipse projects to NetBeans i już było wiadomo, że muszę ją najpierw zainstalować, bo domyślnie nie jest dostępna w NetBeans. Korzystam z wersji rozwojowej NetBeans IDE 6.1, więc to dodatkowo pozwalało "wierzyć", że coś może się (delikatnie mówiąc) zepsuć. Nic to, jak nie spóbuję, to nie będę wiedział.
Wybieram menu Tools > Plugins w NetBeans, gdzie wyszukuję wtyczki.
Po instalacji (przycisk Install w lewym dolnym rogu okienka dialogowego Plugins) nawet nie musiałem restartować NetBeansa. Zaczynałem wierzyć, że pójdzie gładko.
Pojawiło się nowe menu w menu File - Import Project > Eclipse Project....
Wybieram je, a po nim projekt do zaimportowania (a właściwie przestrzeń roboczą Eclipse'a, w którym znajdują się projekty),

wybieram interesujący mnie projekt - jsf-renderer i

zatwierdzam wybór przyciskiem Finish. Potwierdzam jeszcze informację, że chyba nie będzie lekko i import to niełatwa rzecz.

I faktycznie, efekt końcowy mierny. Import zakończył się utworzeniem nowego projektu typu Java Application zamiast oczekiwanego przeze mnie projektu aplikacji webowej. Spodziewałem się więcej. No cóż, nie dane mi było skorzystać z dobrodziejstw wtyczki. Mówię jej Do następnego razu! i wracam do tematu głównego, jakim jest mój zacny renderer przenosząc projekt z Eclipse do NetBeans ręcznie. Nie ma tego wiele, więc nie zajmie mnie na długo.
Nadeszła chwila prawdy. Cały projekt znajduje się w NetBeans, więc definiuję konfigurację uruchomieniową (wskazanie Relative URL na /faces/index.jsp) i można uruchamiać.

Pora na długooczekiwany Run. Jak to zwykle bywa w takich momentach, wstrzymuję oddech i...

Działa! Na konsoli pojawiły się następujące komunikaty:
Pytanie dla wytrwałych: Jaką klasę należy rozszerzyć podczas tworzenia własnego renderera? oraz bardziej dociekliwe: Jakie metody renderera uczestniczą w wyrysowywaniu kontrolki podczas budowania widoku JSF?. Nagród nie ma.
Utworzyłem projekt typu Dynamic Web Project z rozszerzeniem JSF i utworzyłem stronę index.jsp.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>Następnie stworzyłem własnego renderera, który odpowiadałby za wyrysowywanie kontrolki h:outputText w mój wymyślny sposób - po prostu wyświetlił sam tekst.
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Mój własny JSF Renderer</title>
</head>
<body>
<f:view>
<h:outputText value="Pewien tekst"></h:outputText>
</f:view>
</body>
</html>
package pl.jaceklaskowski.jsf.renderers;Jeszcze konfiguracja renderera i związanych z nim kontrolek JSF w pliku faces-config.xml
import java.io.IOException;
import java.util.logging.Logger;
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
import javax.servlet.ServletContext;
public class DodajTekstRenderer extends Renderer {
Logger logger = Logger.getLogger(DodajTekstRenderer.class.getName());
public DodajTekstRenderer() {
super();
logger.info("Utworzono renderer");
}
@Override
public void decode(FacesContext facesContext, UIComponent component) {
logger.info("Wywołano decode");
super.decode(facesContext, component);
}
@Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
logger.info("Wywołano encodeBegin");
ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
ResponseWriter writer = context.getResponseWriter();
writer.write("Zmieniono: " + ((UIOutput) component).getValue());
super.encodeBegin(context, component);
}
@Override
public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
logger.info("Wywołano encodeEnd");
super.encodeEnd(facesContext, component);
}
}
<?xml version='1.0' encoding='UTF-8'?>i skończone. Projekt jest gotowy do uruchomienia.
<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<render-kit>
<renderer>
<display-name>Mój własny JSF renderer</display-name>
<component-family>javax.faces.Output</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>pl.jaceklaskowski.jsf.renderers.DodajTekstRenderer</renderer-class>
</renderer>
</render-kit>
</faces-config>
Kilka słów wyjaśnienia, po co i dlaczego tak. Postawione zadanie polegało na stworzeniu renderera dla dostarczanej domyślnie przez JSF kontrolki h:outputText. Każda kontrolka JSF ma związany z nią renderer, który wie, w jaki sposób wyrysować ją w danym środowisku graficznym, np. przeglądarce HTML. Można sobie wyobrazić sytuację, w której chcielibyśmy stworzyć renderera dla technologii Mozilla XUL, PDF, czy SWT/JFace, czy innych. Zaletą tworzenia aplikacji opartych o JSF jest to, że nie zależy ona od sposobu wyświetlania (renderowania) i to właśnie rendererowi pozostawia się obowiązek jej wyrysowywania. Twórca aplikacji JSF odpowiada (jedynie) za rozkład elementów - kontrolek JSF - na stronie. Specyfikacja JSF zobowiązuje dostawców implementacji JSF, aby domyślny zestaw rendererów dla kompletu kontrolek JSF obsługiwał HTML. Wsparcie dla innych technologi wyrysowywania pozostawione są w gestii danej implementacji JSF.
Po kilku nieudanych próbach uruchomienia przykładu było już wiadomo, że wtopiłem. Renderer nie działał (!) Zacząłem poszukiwać odpowiedzi w źródłach MyFaces i zapoznałem się z artykułem Extending Trinidad’s default renderers. Niestety nic nie pomogło. Kompletnie zniechęcony napisałem na grupę użytkowników Apache MyFaces przedstawiając mój problem - Custom renderer for h:outputText - possible?. Niestety, mając nadzieję, że otrzymam odpowiedź w krótkim czasie, po dniu zniechęcony postanowiłem napisać na forum Web Tier APIs - JavaServer Faces na Sun Forums - Custom renderer for h:outputText - possible?. Tam odpowiedź nadeszła w przeciągu 2 godzin (!) Okazało się, że problemem mogła być implementacja JSF, którą do tej pory był Apache MyFaces, a sugerowano użycie JSF RI dystrybuowanego przez GlassFisha.
Yes it is possible. Have you tried running your code on GlassFish to rule out an implementation bug in MyFaces or Geronimo? You can download glassfish and deploy your web application directly on it to test: https://glassfish.dev.java.net/public/downloadsindex.html
Good luck!
Ken Paulsen
https://jsftemplating.dev.java.net
Zaraz wziąłem się za próbowanie z NetBeans IDE 6.1 (wersja rozwojowa) i GlassFish. Ku mojemu zdziwieniu...nie jeszcze tego nie napiszę, to byłoby jak poznać zakończenie kryminału zanim się jeszcze zacznie go czytać ;-)
Utworzyłem projekt w NetBeans i już miałem przełożyć klasy z projektu w Eclipse, kiedy przypomniałem sobie, aby właśnie w tym momencie popróbować się z wtyczką Eclipse Project Importer do importowania projektów z Eclipse do NetBeans. Lektura Migrating your Eclipse projects to NetBeans i już było wiadomo, że muszę ją najpierw zainstalować, bo domyślnie nie jest dostępna w NetBeans. Korzystam z wersji rozwojowej NetBeans IDE 6.1, więc to dodatkowo pozwalało "wierzyć", że coś może się (delikatnie mówiąc) zepsuć. Nic to, jak nie spóbuję, to nie będę wiedział.
Wybieram menu Tools > Plugins w NetBeans, gdzie wyszukuję wtyczki.
Po instalacji (przycisk Install w lewym dolnym rogu okienka dialogowego Plugins) nawet nie musiałem restartować NetBeansa. Zaczynałem wierzyć, że pójdzie gładko.Pojawiło się nowe menu w menu File - Import Project > Eclipse Project....
Wybieram je, a po nim projekt do zaimportowania (a właściwie przestrzeń roboczą Eclipse'a, w którym znajdują się projekty),
wybieram interesujący mnie projekt - jsf-renderer i

zatwierdzam wybór przyciskiem Finish. Potwierdzam jeszcze informację, że chyba nie będzie lekko i import to niełatwa rzecz.

I faktycznie, efekt końcowy mierny. Import zakończył się utworzeniem nowego projektu typu Java Application zamiast oczekiwanego przeze mnie projektu aplikacji webowej. Spodziewałem się więcej. No cóż, nie dane mi było skorzystać z dobrodziejstw wtyczki. Mówię jej Do następnego razu! i wracam do tematu głównego, jakim jest mój zacny renderer przenosząc projekt z Eclipse do NetBeans ręcznie. Nie ma tego wiele, więc nie zajmie mnie na długo.
Nadeszła chwila prawdy. Cały projekt znajduje się w NetBeans, więc definiuję konfigurację uruchomieniową (wskazanie Relative URL na /faces/index.jsp) i można uruchamiać.

Pora na długooczekiwany Run. Jak to zwykle bywa w takich momentach, wstrzymuję oddech i...

Działa! Na konsoli pojawiły się następujące komunikaty:
Wywołano encodeBeginBardzo pomocna była lektura artykułu Creating an AJAX enabled JSF component - Part 1. Gorąco zachęcam do jego lektury wszystkim zainteresowanym aspektami tworzenia własnych rendererów.
Wywołano encodeEnd
Pytanie dla wytrwałych: Jaką klasę należy rozszerzyć podczas tworzenia własnego renderera? oraz bardziej dociekliwe: Jakie metody renderera uczestniczą w wyrysowywaniu kontrolki podczas budowania widoku JSF?. Nagród nie ma.
Subskrybuj:
Posty (Atom)