Professional Documents
Culture Documents
Spis treci
Przykadowy rozdzia
Katalog ksiek
Katalog online
Zamw drukowany
katalog
Twj koszyk
Dodaj do koszyka
Cennik i informacje
Zamw informacje
o nowociach
Zamw cennik
Czytelnia
Fragmenty ksiek
online
Kontakt
Helion SA
ul. Kociuszki 1c
44-100 Gliwice
tel. 32 230 98 63
e-mail: helion@helion.pl
Helion 19912011
JavaServer Faces.
Wydanie III
Autorzy: David Geary, Cay S. Horstmann
Tumaczenie: Mikoaj Szczepaniak
ISBN: 978-83-246-2904-6
Tytu oryginau: Core JavaServer Faces (3rd Edition)
Format: 172245, stron: 584
Spis treci
Przedmowa .................................................................................................................... 9
Podzikowania ............................................................................................................. 13
JavaServer Faces
Zasig dania ....................................................................................................... 62
Zasig aplikacji ....................................................................................................... 63
Zasig konwersacji
........................................................................................... 63
Zasig widoku
.............................................................................................. 64
Zasigi niestandardowe
................................................................................. 65
Konfigurowanie komponentw ....................................................................................... 65
Wstrzykiwanie komponentw CDI
....................................................................... 65
..................................................... 66
Wstrzykiwanie komponentw zarzdzanych
Adnotacje cyklu ycia komponentu ............................................................................ 66
Konfigurowanie komponentw zarzdzanych na poziomie XML-a ................................. 67
Skadnia jzyka wyrae ................................................................................................ 72
Tryby l-wartoci i r-wartoci ....................................................................................... 72
Stosowanie nawiasw kwadratowych ........................................................................ 73
Wyraenia odwoujce si do map i list ..................................................................... 73
Wywoywanie metod i funkcji <rysunek JSF 2.0> ........................................................ 74
Przetwarzanie wyrazu pocztkowego ......................................................................... 76
Wyraenia zoone ................................................................................................... 77
Wyraenia odwoujce si do metod ......................................................................... 78
Parametry wyrae odwoujcych si do metod
................................................ 79
Podsumowanie ............................................................................................................ 80
Spis treci
Rozdzia 5. Facelety
....................................................................................................................175
JavaServer Faces
Bdy konwersji ..................................................................................................... 239
Kompletny przykad konwertera .............................................................................. 244
Stosowanie standardowych mechanizmw weryfikujcych .............................................. 247
Weryfikacja dugoci acuchw i przedziaw liczbowych .......................................... 247
Weryfikacja wartoci wymaganych .......................................................................... 249
Wywietlanie komunikatw o bdach weryfikacji ..................................................... 250
Pomijanie procesu weryfikacji ................................................................................. 250
Kompletny przykad mechanizmu weryfikacji ............................................................ 252
Weryfikacja na poziomie komponentw Javy
....................................................... 254
Programowanie z wykorzystaniem niestandardowych konwerterw
i mechanizmw weryfikujcych .................................................................................. 259
Implementacja klas konwerterw niestandardowych ................................................. 259
Wskazywanie konwerterw
........................................................................... 262
Raportowanie bdw konwersji .............................................................................. 264
Uzyskiwanie dostpu do komunikatw o bdach
zapisanych w pakiecie komunikatw .................................................................... 265
Przykadowa aplikacja zbudowana na bazie konwertera niestandardowego ................. 269
Przekazywanie konwerterom atrybutw .................................................................... 272
Implementacja klas niestandardowych mechanizmw weryfikacji .............................. 273
Rejestrowanie wasnych mechanizmw weryfikacji ................................................... 274
Weryfikacja danych wejciowych za pomoc metod komponentw Javy ...................... 277
Weryfikacja relacji czcych wiele komponentw ..................................................... 277
Implementacja niestandardowych znacznikw konwerterw i mechanizmw weryfikacji .... 279
Podsumowanie .......................................................................................................... 285
...............................................................................................325
Spis treci
........................................................................................................................359
JavaServer Faces
Rozdzia 12. Usugi zewntrzne .............................................................................................................451
Dostp do bazy danych za porednictwem interfejsu JDBC ............................................ 451
Wykonywanie wyrae jzyka SQL ........................................................................... 451
Zarzdzanie poczeniami ...................................................................................... 453
Eliminowanie wyciekw pocze ............................................................................ 453
Stosowanie gotowych wyrae ................................................................................ 455
Transakcje ........................................................................................................... 456
Uywanie bazy danych Derby .................................................................................. 457
Konfigurowanie rda danych ..................................................................................... 459
Uzyskiwanie dostpu do zasobw zarzdzanych przez kontener ................................ 459
Konfigurowanie zasobw baz danych w ramach serwera GlassFish ............................ 460
Konfigurowanie zasobw baz danych w ramach serwera Tomcat ............................... 460
Kompletny przykad uycia bazy danych ................................................................... 462
Stosowanie architektury JPA ........................................................................................ 470
Krtki kurs architektury JPA ................................................................................... 470
Stosowanie architektury JPA w aplikacjach internetowych ......................................... 472
Stosowanie komponentw zarzdzanych i bezstanowych komponentw sesyjnych ...... 476
Stanowe komponenty sesyjne
.......................................................................... 479
Uwierzytelnianie i autoryzacja zarzdzana przez kontener ............................................... 481
Wysyanie poczty elektronicznej ................................................................................... 492
Stosowanie usug sieciowych ...................................................................................... 497
Podsumowanie .......................................................................................................... 503
Skorowidz .............................................................................................................................................563
3
Nawigacja
W tym krtkim rozdziale omwimy sposb konfigurowania regu nawigacji w ramach budowanej aplikacji internetowej. W szczeglnoci wyjanimy, jak aplikacja moe przechodzi
od jednej do drugiej strony internetowej w zalenoci od czynnoci wykonywanych przez
uytkownika i decyzji podejmowanych na poziomie logiki biznesowej.
Nawigacja statyczna
Przeanalizujmy teraz sytuacj, w ktrej uytkownik aplikacji internetowej wypenia formularz na stronie internetowej. Uytkownik moe wpisywa dane w polach tekstowych, klika
przyciski opcji i wybiera elementy list.
Wszystkie te dziaania s realizowane na poziomie przegldarki internetowej uytkownika.
Kiedy uytkownik klika przycisk akceptujcy i wysyajcy dane formularza, zmiany s przekazywane na serwer.
Aplikacja internetowa analizuje wwczas dane wpisane przez uytkownika i na ich podstawie decyduje, ktrej strony JSF naley uy do wizualizacji odpowiedzi. Za wybr kolejnej
strony JSF odpowiada mechanizm obsugujcy nawigacj (ang. navigation handle).
W przypadku prostych aplikacji internetowych nawigacja pomidzy stronami ma charakter
statyczny. Oznacza to, e kliknicie okrelonego przycisku zawsze powoduje przejcie do
tej samej strony JSF odpowiedzialnej za wizualizacj odpowiedzi. W podrozdziale Prosty
przykad w rozdziale 1. Czytelnicy mieli okazj zapozna si z najprostszym mechanizmem
zapisywania regu nawigacji statycznej pomidzy stronami JSF.
Dla kadego przycisku definiujemy atrybut action przykad takiego rozwizania przedstawiono poniej:
<h:commandButton label="Zaloguj" action="welcome"/>
82
JavaServer Faces
Podczas lektury rozdziau 4. bdzie si mona przekona , e akcje nawigacji mona
przypisywa take do hiperczy.
Warto atrybutu action okrela si mianem wyniku (ang. outcome). Wrcimy do tematu
wyniku w punkcie Odwzorowywanie wynikw na identyfikatory widokw w nastpnym
podrozdziale okazuje si, e wynik mona opcjonalnie odwzorowywa na identyfikatory
widokw. W specyfikacji JavaServer Faces mianem widoku (ang. view) okrela si stron JSF.
Jeli programista nie zdefiniuje takiego odwzorowania dla okrelonego wyniku, wynik jest
przeksztacany w identyfikator widoku wedug nastpujcych regu:
1. Jeli wynik nie obejmuje rozszerzenia pliku, dopisuje si do niego rozszerzenie
biecego widoku.
2. Jeli wynik nie rozpoczyna si od prawego ukonika (/), poprzedza si go ciek
do biecego widoku.
Na przykad wynik welcome w widoku /index.xhtml zostanie automatycznie przeksztacony
w identyfikator widoku docelowego /welcome.xhtml.
Odwzorowania wynikw na identyfikatory widokw s opcjonalne, poczwszy od wersji JSF 2.0. We wczeniejszych wersjach programista musia wprost
okrela reguy nawigacji dla kadego wyniku.
Nawigacja dynamiczna
W przypadku wikszoci aplikacji internetowych nawigacja nie ma charakteru statycznego.
cieka przechodzenia pomidzy stronami nie zaley tylko od klikanych przyciskw, ale
take od danych wejciowych wpisywanych przez uytkownika. Na przykad wysyajc dane
ze strony logowania (zwykle nazw uytkownika i haso), moemy oczekiwa dwch odpowiedzi ze strony serwera: akceptacji tych danych bd ich odrzucenia. Odpowied serwera
zaley wic od pewnych oblicze (w tym konkretnym przypadku od poprawnoci nazwy
uytkownika i hasa).
Aby zaimplementowa nawigacj dynamiczn, przycisk akceptacji formularza naley zwiza z wyraeniem odwoujcym si do metody:
<h:commandButton label="Zaloguj" action="#{loginController.verifyUser}"/>
Rozdzia 3.
Nawigacja
83
W standardzie JSF 1.1 metody bdce przedmiotem odwoa w tego rodzaju wyraeniach musiay zwraca wartoci typu String. W technologii JSF 1.2 zwracana
warto moe by obiektem dowolnego typu. Taka moliwo jest szczeglnie wana
w przypadku typw wyliczeniowych, poniewa eliminuje ryzyko przeoczenia literwek
w nazwach akcji (wychwytywanych przez kompilator).
Powysza metoda zwraca jeden z dwch acuchw wynikowych: "success" lub "failure".
Na podstawie tej wartoci identyfikuje si nastpny widok.
Metoda akcji moe zwrci warto null, aby zasygnalizowa konieczno ponownego wywietlenia tej samej strony. W takim przypadku zasig widoku (ktry omwilimy w rozdziale 2.) jest zachowywany. Kady wynik inny ni null powoduje wyczyszczenie tego zasigu, nawet jeli widok wynikowy jest taki sam jak widok biecy.
Krtko mwic, za kadym razem, gdy uytkownik klika przycisk polecenia, dla ktrego
zdefiniowano wyraenie odwoujce si do metody w atrybucie action, implementacja JSF
podejmuje nastpujce kroki:
1. uzyskuje dostp do wskazanego komponentu;
2. wywouje wskazan metod;
3. przeksztaca acuch wynikowy w identyfikator widoku;
4. wywietla odpowiedni stron (na podstawie identyfikatora widoku).
84
JavaServer Faces
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/welcome.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Przytoczona regua okrela, e wynik success na stronie /index.xhtml ma kierowa uytkownika na stron /welcome.xhtml.
Jeli programista odpowiednio dobierze acuchy wynikw, bdzie mg zebra wiele regu
nawigacji w jednym miejscu. Programista moe na przykad stworzy jedn regu dla
wszystkich przyciskw skojarzonych z akcj logout (dostpnych na wielu stronach danej
aplikacji). Wszystkie te przyciski mog powodowa przejcie na stron loggedOut.xhtml
wystarczy zdefiniowa jedn regu:
<navigation-rule>
<navigation-case>
<from-outcome>logout</from-outcome>
<to-view-id>/loggedOut.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Ta regua jest stosowana dla wszystkich stron, poniewa nie zdefiniowano elementu fromview-id.
Istnieje te moliwo scalania regu nawigacji z tym samym elementem from-view-id.
Przykad takiego rozwizania pokazano poniej:
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/welcome.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/newuser.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Rozdzia 3.
Nawigacja
85
Aplikacja JavaQuiz
W tym punkcie umiecimy zapisy dotyczce nawigacji w przykadowym programie prezentujcym uytkownikowi sekwencj pyta quizu (patrz rysunek 3.1).
Rysunek 3.1.
Pytanie quizu
Kiedy uytkownik klika przycisk Sprawd odpowied , aplikacja sprawdza, czy podana odpowied jest prawidowa. Jeli nie, uytkownik otrzymuje jeszcze jedn szans rozwizania tego
samego problemu (patrz rysunek 3.2).
Rysunek 3.2.
Jedna bdna
odpowied
sprbuj
ponownie
86
JavaServer Faces
Rysunek 3.3.
Dwie bdne
odpowiedzi
kontynuuj
Rysunek 3.4.
Quiz zako
czony
punktacja
Nasza aplikacja skada si z dwch klas. Klasa Problem (przedstawiona na listingu 3.1) opisuje
pojedynczy problem, czyli pytanie, odpowied oraz metod weryfikacji, czy dana odpowied
jest prawidowa.
Listing 3.1. Zawarto pliku javaquiz/src/java/com/corejsf/Problem.java
1. package com.corejsf;
2.
3. import java.io.Serializable;
4.
5. public class Problem implements Serializable {
6.
private String question;
7.
private String answer;
8.
9.
public Problem(String question, String answer) {
10.
this.question = question;
11.
this.answer = answer;
12.
}
Rozdzia 3.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22. }
Nawigacja
87
Klasa QuizBean opisuje quiz obejmujcy szereg pyta. Egzemplarz tej klasy dodatkowo ledzi
biece pytanie i czn punktacj uzyskan przez uytkownika. Kompletny kod tej klasy
przedstawiono na listingu 3.2.
Listing 3.2. Zawarto pliku javaquiz/src/java/com/corejsf/QuizBean.java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
package com.corejsf;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import javax.inject.Named;
// lub import javax.faces.bean.ManagedBean;
import javax.enterprise.context.SessionScoped;
// lub import javax.faces.bean.SessionScoped;
@Named // lub @ManagedBean
@SessionScoped
public class QuizBean implements Serializable {
private int currentProblem;
private int tries;
private int score;
private String response = "";
private String correctAnswer;
// Poniej zakodowano problemy na stae. W rzeczywistej aplikacji
// najprawdopodobniej odczytywalibymy je z bazy danych.
private ArrayList<Problem> problems = new ArrayList<Problem>(Arrays.asList(
new Problem(
"Jaki slogan reklamowa programowanie w Javie? Write once, ...",
"run anywhere"),
new Problem(
"Jak wygldaj 4 pierwsze bajty kadego pliku klasy (szesnastkowo)?",
"CAFEBABE"),
new Problem(
"Co zostanie wywietlone przez to wyraenie? System.out.println(1+\"2\");",
"12"),
new Problem(
"Ktre sowo kluczowe Javy suy do definiowania podklasy?",
"extends"),
new Problem(
"Jak brzmiaa oryginalna nazwa jzyka programowania Java?",
"Oak"),
88
JavaServer Faces
41.
new Problem(
42.
"Ktra klasa pakietu java.util opisuje punkt w czasie?",
43.
"Date")));
44.
45.
public String getQuestion() { return problems.get(currentProblem).getQuestion(); }
46.
47.
public String getAnswer() { return correctAnswer; }
48.
49.
public int getScore() { return score; }
50.
51.
public String getResponse() { return response; }
52.
public void setResponse(String newValue) { response = newValue; }
53.
54.
public String answerAction() {
55.
tries++;
56.
if (problems.get(currentProblem).isCorrect(response)) {
57.
score++;
58.
nextProblem();
59.
if (currentProblem == problems.size()) return "done";
60.
else return "success";
61.
}
62.
else if (tries == 1) return "again";
63.
else {
64.
nextProblem();
65.
if (currentProblem == problems.size()) return "done";
66.
else return "failure";
67.
}
68.
}
69.
70.
public String startOverAction() {
71.
Collections.shuffle(problems);
72.
currentProblem = 0;
73.
score = 0;
74.
tries = 0;
75.
response = "";
76.
return "startOver";
77.
}
78.
79.
private void nextProblem() {
80.
correctAnswer = problems.get(currentProblem).getAnswer();
81.
currentProblem++;
82.
tries = 0;
83.
response = "";
84.
}
85. }
W analizowanym przykadzie wanie klasa QuizBean jest waciwym miejscem dla metod
odpowiedzialnych za nawigacj. Wspomniany komponent dysponuje pen wiedz o dziaaniach uytkownika i moe bez trudu okreli, ktra strona powinna by wywietlona jako
nastpna.
Logik nawigacji zaimplementowano w metodzie answerAction klasy QuizBean. Metoda
answerAction zwraca jeden z kilku moliwych acuchw: "success" lub "done" (jeli uytkownik prawidowo odpowiedzia na pytanie), "again" (jeli uytkownik po raz pierwszy
udzieli bdnej odpowiedzi) oraz "failure" lub "done" (jeli po raz drugi pada za odpowied ).
Rozdzia 3.
Nawigacja
89
Z przyciskami na kadej z tych stron wiemy wyraenie odwoujce si do metody answer
Action. Na przykad strona index.xhtml zawiera nastpujcy element:
<h:commandButton value="#{msgs.checkAnswer}" action="#{quizBean.answerAction}"/>
Na rysunku 3.5 przedstawiono struktur katalogw naszej aplikacji. Na listingu 3.3 przedstawiono kod strony gwnej aplikacji quizu: index.xhtml. Kodem stron success.xhtml i failure.
xhtml nie bdziemy si zajmowa, poniewa rni si od kodu strony index.xhtml tylko
komunikatem wywietlanym w grnej czci.
Rysunek 3.5.
Struktura
katalogw
aplikacji quizu
o Javie
90
JavaServer Faces
9.
<h:body>
10.
<h:form>
11.
<p>#{quizBean.question}</p>
12.
<p><h:inputText value="#{quizBean.response}"/></p>
13.
<p>
14.
<h:commandButton value="#{msgs.checkAnswer}"
15.
action="#{quizBean.answerAction}"/>
16.
</p>
17.
</h:form>
18.
</h:body>
19. </html>
Metoda startOverAction wykonuje wszelkie dziaania niezbdne do przywrcenia oryginalnego stanu gry. Dziaanie tej metody polega na przypadkowym uporzdkowaniu pyta i wyzerowaniu wyniku:
public String startOverAction() {
Collections.shuffle(problems);
currentProblem = 0;
Rozdzia 3.
Nawigacja
91
score = 0;
tries = 0;
response = "";
return "startOver";
}
Podczas lektury rozdziau 8. Czytelnicy przekonaj si, e istnieje moliwo doczania do przyciskw take obiektw nasuchujcych akcji. Kiedy uytkownik klika
tak zdefiniowany przycisk, nastpuje wykonanie kodu metody processAction obiektu
nasuchujcego. Warto jednak pamita , e obiekt nasuchujcy akcji nie komunikuje
si z mechanizmem odpowiedzialnym za nawigacj.
Na listingu 3.5 przedstawiono plik konfiguracyjny tej aplikacji obejmujcy midzy innymi
reguy nawigacji. Aby lepiej zrozumie te reguy, warto rzuci okiem na diagram przechodzenia pomidzy stronami, pokazany na rysunku 3.6.
Listing 3.5. Zawarto pliku javaquiz/web/WEB-INF/faces-config.xml
1. <?xml version="1.0"?>
2. <faces-config xmlns="http://java.sun.com/xml/ns/javaee"
3.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4.
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
5.
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
6.
version="2.0">
7.
<navigation-rule>
8.
<navigation-case>
9.
<from-outcome>startOver</from-outcome>
10.
<to-view-id>/index.xhtml</to-view-id>
11.
</navigation-case>
12.
</navigation-rule>
13.
<navigation-rule>
14.
<from-view-id>/again.xhtml</from-view-id>
15.
<navigation-case>
16.
<from-outcome>failure</from-outcome>
17.
<to-view-id>/failure.xhtml</to-view-id>
18.
</navigation-case>
19.
</navigation-rule>
20.
<navigation-rule>
21.
<navigation-case>
22.
<from-outcome>failure</from-outcome>
23.
<to-view-id>/again.xhtml</to-view-id>
24.
</navigation-case>
25.
</navigation-rule>
26.
27.
<application>
28.
<resource-bundle>
29.
<base-name>com.corejsf.messages</base-name>
30.
<var>msgs</var>
92
JavaServer Faces
Rysunek 3.6.
Diagram przej
aplikacji quizu
o Javie
31.
</resource-bundle>
32.
</application>
33. </faces-config>
Dla trzech spord naszych wynikw ("success", "again" i "done") nie zdefiniowano regu
nawigacji. Wymienione wyniki zawsze kieruj uytkownika odpowiednio na strony /success.
xhtml, /again.xhtml oraz /done.xhtml. Wynik "startOver" odwzorowujemy na stron
/index.xhtml. Nieco trudniejsza jest obsuga wyniku failure, ktry pocztkowo kieruje uytkownika na stron /again.xhtml, stwarzajc mu drug okazj do udzielenia odpowiedzi. Jeli
jednak take odpowied wpisana na tej stronie okazuje si bdna, ten sam wynik kieruje
uytkownika na stron /failure.xhtml:
<navigation-rule>
<from-view-id>/again.xhtml</from-view-id>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/failure.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/again.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Warto pamita o tym, e kolejno regu nie jest bez znaczenia. Druga regua jest uwzgldniana w sytuacji, gdy biec stron nie jest /again.xhtml.
Rozdzia 3.
Nawigacja
93
Przekierowania
Programista moe wymusi na implementacji technologii JavaServer Faces przekierowanie
(ang. redirection) uytkownika do nowego widoku. Implementacja JSF wysya nastpnie
przekierowanie protokou HTTP do klienta. Odpowied przekierowania wskazuje klientowi
adres URL kolejnej strony na tej podstawie klient generuje danie GET na odpowiedni
adres URL.
Przekierowywanie jest czasochonne, poniewa wymaga powtrzenia caego cyklu komunikacji z udziaem przegldarki. Przekierowanie ma jednak t zalet, e stwarza przegldarce
moliwo aktualizacji jej pola adresu.
Na rysunku 3.7 pokazano, jak zmienia si zawarto pola adresu wskutek uycia mechanizmu
przekierowania.
Bez przekierowania oryginalny adres URL (localhost:8080/javaquiz/faces/index.xhtml)
pozostaby niezmieniony przy okazji przejcia uytkownika ze strony /index.xhtml na stron
/success.xhtml. Przekierowanie powoduje, e przegldarka wywietla nowy adres URL
(localhost:8080/javaquiz/faces/success.xhtml).
Jeli nie stosujemy regu nawigacji, powinnimy uzupeni acuch wyniku o nastpujcy zapis:
?faces-redirect=true
Po wprowadzeniu tej zmiany przykadowy acuch wyniku moe mie nastpujc posta:
<h:commandButton label="Zaloguj" action="welcome?faces-redirect=true"/>
94
JavaServer Faces
Rozdzia 3.
Nawigacja
95
nie tylko zwraca warto klucza message przechowywan w obiekcie flash, ale te dodaje t
warto ponownie z myl o kolejnym cyklu dania.
Jeli z czasem ilo danych przerzucanych pomidzy obiektem flash a komponentem staje si naprawd dua, warto rozway uycie zasigu konwersacji.
96
JavaServer Faces
regu przyjtych przez jego twrcw. Na potrzeby operacji wyszukiwania naley stosowa
dania GET. dania PUT, POST i DELETE powinny by wykorzystywane odpowiednio do tworzenia, modyfikowania i usuwania.
Zwolennicy stylu REST najbardziej ceni sobie adresy URL w nastpujcej formie:
http://serwer.pl/catalog/item/1729
Architektura REST nie narzuca nam jednak jednego stylu. Na przykad dla dania GET
z parametrem mona by uy nastpujcego adresu:
http://serwer.pl/catalog?item=1729
nie byoby waciwe. dania GET powinny by idempotentne. Oznacza to, e dwukrotne
uycie tego samego dania nie powinno prowadzi do rezultatw innych ni jednorazowe
danie. Wanie od tego zaley moliwo przechowywania da w pamici podrcznej.
danie dodaj do koszyka z natury rzeczy nie jest idempotentne jego dwukrotne wysanie spowoduje dodanie dwch takich samych towarw do koszyka. W tym kontekcie duo
odpowiedniejsze byoby danie POST. Oznacza to, e nawet aplikacje internetowe zgodne ze
stylem REST musz korzysta z da POST.
Technologia JSF nie oferuje obecnie standardowego mechanizmu generowania ani przetwarzania tzw. dobrych adresw URL, jednak poczwszy od wersji JSF 2.0, moemy liczy
na obsug da GET. Omwimy ten aspekt w kolejnych punktach tego podrozdziau.
Parametry widoku
Przeanalizujmy teraz danie GET, ktre ma spowodowa wywietlenie informacji o konkretnym produkcie:
http://serwer.pl/catalog?item=1729
Rozdzia 3.
Nawigacja
97
Strona JSF moe zawiera dowoln liczb parametrw widoku. Jak wszystkie parametry dania, parametry widoku mona konwertowa i sprawdza pod ktem poprawnoci. (Zagadnienia zwizane z konwersj i weryfikacj zostan szczegowo omwione w rozdziale 7.).
Czsto niezbdne jest uzyskiwanie dodatkowych danych ju po ustawieniu parametrw widoku.
Na przykad po ustawieniu parametru widoku item moe zaistnie potrzeba uzyskania waciwoci tego produktu z bazy danych, aby wygenerowa stron opisujc ten produkt. W rozdziale 8. omwimy sposb implementacji tego rodzaju mechanizmw w ramach metody
obsugujcej zdarzenie preRenderView.
Drugi zapis powoduje wywoanie metody getSkipOutcome. Metoda ta musi zwrci acuch
wyniku, ktry trafia do mechanizmu obsugi nawigacji, gdzie jest przetwarzany w tradycyjny
sposb w celu okrelenia identyfikatora widoku docelowego.
Istnieje zasadnicza rnica dzielca atrybut outcome znacznika h:button od atrybutu action
znacznika h:commandButton. Atrybut outcome jest przetwarzany przed wizualizacj strony,
zatem odpowiednie cze moe by osadzone w kodzie tej strony. Atrybut action jest natomiast przetwarzany dopiero po klikniciu przycisku polecenia przez uytkownika. Wanie
dlatego w specyfikacji JSF mona spotka termin nawigacji wyprzedzajcej (ang. preemptive navigation) stosowany w kontekcie wyznaczania identyfikatorw widokw docelowych
dla da GET.
Wyraenie jzyka wyrae (EL) przypisane atrybutowi outcome jest wyraeniem
reprezentujcym warto , nie wyraeniem odwoujcym si do metody. Oglnie,
akcja skojarzona z przyciskiem polecenia moe w ten czy inny sposb zmienia stan
aplikacji. Naley jednak pamita , e przetwarzanie wyniku cza dania GET nie powinno
skutkowa adnymi zmianami takie cze jest przecie umieszczane na stronie
z myl o potencjalnym wykorzystaniu w przyszoci.
98
JavaServer Faces
acucha wyniku,
parametrw widoku,
Jeli ten sam parametr zostanie okrelony wicej ni raz, pierwszestwo ma warto zdefiniowana przez p niejsze rdo z poniszej listy (najwyszy priorytet maj wic zagniedone
znaczniki f:param).
Przeanalizujmy teraz szczegy kadego z tych rozwiza.
Parametry mona okrela w ramach acucha wyniku, na przykad:
<h:link outcome="index?q=1" value="Skip">
Mechanizm obsugujcy nawigacj wyodrbnia parametry z acucha wyniku, okrela identyfikator widoku docelowego i dopisuje wyodrbnione wczeniej parametry do tego identyfikatora. Oznacza to, e w tym przypadku identyfikatorem widoku docelowego bdzie /index.
xhtml?q=1.
W razie zdefiniowania wielu parametrw koniecznie naley zastpi separator & odpowiedni
sekwencj specjaln (ucieczki):
<h:link outcome="index?q=1&score=0" value="Skip">
W ten sposb mona atwo przenosi wszystkie parametry widoku z jednej strony na drug,
co jest do typowym wymaganiem stawianym aplikacjom zgodnym z architektur REST.
Parametry widoku mona nadpisa, stosujc znacznik f:param. Przykad takiego rozwizania
pokazano poniej:
<h:link outcome="index" includeViewParams="true" value="Skip">
<f:param name="q" value="#{quizBean.currentProblem + 1}"/>
</h:link>
Rozdzia 3.
Nawigacja
99
Moliwo wczania parametrw widoku znacznie uatwia take definiowanie czy przekierowa, ktre take maj posta da GET. Zamiast jednak ustawia atrybut w znaczniku,
naley doda odpowiedni parametr do wyniku:
<h:commandLink action="index?faces-redirect=true&includeViewParams=true"
value="Skip"/>
Nie naley przywizywa zbyt duej wagi do drobnych niekonsekwencji widocznych w powyszej konstrukcji skadniowej. Czytelnik powinien je traktowa raczej jako rodek do podniesienia poziomu czujnoci i tym samym udoskonalenia swoich umiejtnoci programistycznych.
Metoda getSkipOutcome klasy QuizBean zwraca acuch "index" lub "done" w zalenoci od
tego, czy s dostpne jeszcze jakie pytania:
100
JavaServer Faces
public String getSkipOutcome() {
if (currentProblem < problems.size() - 1) return "index";
else return "done";
}
Tak zdefiniowane cze bdzie miao nastpujc posta (patrz rysunek 3.8):
http://localhost:8080/javaquiz-rest/faces/index.xhtml?q=1
Rysunek 3.8.
Przykad cza
zgodnego
z architektur
REST
Rozdzia 3.
Nawigacja
101
17.
<p><h:commandButton value="#{msgs.checkAnswer}"
18.
action="#{quizBean.answerAction}"/></p>
19.
<p><h:link outcome="#{quizBean.skipOutcome}" value="Skip">
20.
<f:param name="q" value="#{quizBean.currentProblem + 1}"/>
21.
</h:link>
22.
</p>
23.
</h:form>
24.
</h:body>
25. </html>
package com.corejsf;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import javax.inject.Named;
// lub import javax.faces.bean.ManagedBean;
import javax.enterprise.context.SessionScoped;
// lub import javax.faces.bean.SessionScoped;
@Named // lub @ManagedBean
@SessionScoped
public class QuizBean implements Serializable {
private int currentProblem;
private int tries;
private String response = "";
private String correctAnswer;
// Poniej zakodowano problemy na stae. W rzeczywistej aplikacji
// najprawdopodobniej odczytywalibymy je z bazy danych.
private ArrayList<Problem> problems = new ArrayList<Problem>(Arrays.asList(
new Problem(
"Jaki slogan reklamowa programowanie w Javie? Write once, ...",
"run anywhere"),
new Problem(
"Jak wygldaj 4 pierwsze bajty kadego pliku klasy (szesnastkowo)?",
"CAFEBABE"),
new Problem(
"Co zostanie wywietlone przez to wyraenie? System.out.println(1+\"2\");",
"12"),
new Problem(
"Ktre sowo kluczowe Javy suy do definiowania podklasy?",
"extends"),
new Problem(
"Jak brzmiaa oryginalna nazwa jzyka programowania Java?",
"Oak"),
new Problem(
"Ktra klasa pakietu java.util opisuje punkt w czasie?",
"Date")));
private int[] scores = new int[problems.size()];
public String getQuestion() {
return problems.get(currentProblem).getQuestion();
102
JavaServer Faces
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103. }
}
public String getAnswer() { return correctAnswer; }
public int getScore() {
int score = 0;
for (int s : scores) score += s;
return score;
}
public String getResponse() { return response; }
public void setResponse(String newValue) { response = newValue; }
public int getCurrentProblem() { return currentProblem; }
public void setCurrentProblem(int newValue) { currentProblem = newValue; }
public String getSkipOutcome() {
if (currentProblem < problems.size() - 1) return "index";
else return "done";
}
public String answerAction() {
tries++;
if (problems.get(currentProblem).isCorrect(response)) {
scores[currentProblem] = 1;
nextProblem();
if (currentProblem == problems.size()) return "done";
else return "success";
}
else {
scores[currentProblem] = 0;
if (tries == 1) return "again";
else {
nextProblem();
if (currentProblem == problems.size()) return "done";
else return "failure";
}
}
}
public String startOverAction() {
Collections.shuffle(problems);
currentProblem = 0;
for (int i = 0; i < scores.length; i++)
scores[i] = 0;
tries = 0;
response = "";
return "startOver";
}
private void nextProblem() {
correctAnswer = problems.get(currentProblem).getAnswer();
currentProblem++;
tries = 0;
response = "";
}
Rozdzia 3.
Nawigacja
103
104
JavaServer Faces
Symbole wieloznaczne
W elementach from-view-id wykorzystywanych w ramach regu nawigacji mona stosowa
symbole wieloznaczne. Poniej przedstawiono odpowiedni przykad:
<navigation-rule>
<from-view-id>/secure/*</from-view-id>
<navigation-case>
...
</navigation-case>
</navigation-rule>
Tak zdefiniowana regua bdzie stosowana dla wszystkich stron rozpoczynajcych si od
przedrostka /secure/. Dopuszczalny jest tylko jeden znak gwiazdki (*), ktry musi si znajdowa na kocu acucha identyfikatora.
Jeli bdzie istniao wiele dopasowa do wzorca zdefiniowanego z uyciem symbolu wieloznacznego, zostanie wykorzystane dopasowanie najdusze.
Zamiast rezygnowa z elementu from-view-id, mona zastosowa jedn z dwch
poniszych konstrukcji definiujcych regu stosowan dla wszystkich stron:
<from-view-id>/*</from-view-id>
lub
<from-view-id>*</from-view-id>
Rozdzia 3.
Nawigacja
105
Mechanizm odpowiedzialny za nawigacj nie wywouje metody otoczonej konstrukcj #{...}. Odpowiednia metoda jest wywoywana, zanim jeszcze wspomniany mechanizm przystpuje do pracy. W tej sytuacji mechanizm nawigacji ogranicza si do wykorzystania acucha zdefiniowanego w elemencie from-action w roli klucza umoliwiajcego odnalezienie pasujcego przypadku.
Podsumowanie
W tym rozdziale omwilimy wszystkie elementy technologii JavaServer Faces w zakresie
zarzdzania nawigacj. Naley pamita, e nawigacja w najprostszej formie jest wyjtkowo
atwa do zaimplementowania akcje przyciskw polece i czy mog po prostu zwraca
wynik wskazujcy nastpn stron. Jeli jednak programista potrzebuje wikszej kontroli,
framework JSF udostpnia mu niezbdne narzdzia.
W nastpnym rozdziale bdziemy koncentrowali si wycznie na standardowych komponentach frameworku JSF.