Cykl życia strony JSF

W najprostszej formie cykl życia strony JSF nie rożni się od wywołania zwykłej strony JSP: klient wysyła żądanie pobrania wybranej strony a serwer generuje stroną poprzez wywołanie odpowiedniego serwletu. Jednakże model działania stron JSF jest bardziej skomplikowany, wymaga on aby komponenty były odpowiednio sprawdzane, pozwala na przechwycenie odpowiednich zdarzeń, pozwala na przesyłanie danych i tak dalej.

Poniższy rysunek (z dokumentacji The JEE 5 Tutorial, The Life Cycle of a JavaServer Faces Page) prezentuje poszczególne elementy cyklu życia aplikacji:

Standardowy cykl życia strony JSF

Standardowy cykl życia strony JSF

Powyższy diagram zawiera opis dwóch typów zapytań: żądanie początkowe oraz żądanie wyświetlenie ponowne. Żądanie początkowe występuje wtedy, gdy użytkownik wyświetla daną stronę po raz pierwszy, natomiast z wyświetleniem ponownym do czynienia mamy w momencie np. przesłania formularza, który był wcześniej wczytany w fazie pierwszej. Jeżeli następuje żądanie początkowe, to wykonywane są tylko kroki związane z przywróceniem widoku oraz wygenerowaniem odpowiedzi, ponieważ nie ma żadnych danych do przetworzenia. Natomiast z drugim przypadku cykl życia obejmuje wszystkie fazy.

Jeżeli żądanie wyświetlania strony JSF pochodzi z kliknięci ana linka o zwykle jest początkowe żądanie wyświetlenia strony. W takim przypadku zostaje utworzony nowy widok i zapisany w instancji klasy FacesConfig. Aplikacja następnie pobiera obiekty niezbędne do wyświetlenia widoku i wywołuje metodę FacesContext.renderResponse, która powoduje natychmiastowe utworzenie strony z pominięcie Render Response Phase. Operacja ta jest widoczna na diagramie pod nazwą Render Response.

Istnieje czasem potrzeba przekierowanie strony w jakiejś inne miejsce (dostęp do jakiegoś pliku, usługi) lub też strona nie zawiera żadnych komponentów JSF. W takiej sytuacji należy pominąć krok Render Response Phase poprzez wywołanie metody FacesContext.responseComplete. Sytuacja taka znajduje się na diagramie oznaczona nazwą Response Complete.

Restore View Phase

Pierwszą fazą w cyklu życia strony JSF jest Restoe View Phase. Jest ona wywoływana po tym, jak serwer zostanie poproszony o wyświetlenie strony po wybraniu np. jakieś linka. Podczas tej fazy biblioteka JSF tworzy widok, wiąże odpowiednie uchwyty zdarzeń oraz walidatory z odpowiednimi komponentami na widoku, oraz zapisu tak przygotowaną stronę w swojej pamięci podręcznej.

Jeżeli jest to żądanie początkowe zostaje zvudowany pusty widok i następuje przejście do kroku Render Response Phase, gdzie pusty widok jest wypełniany odpowiednimi komponentami znajdującymi się na stronie (czyli następuje utworzenie strony HTML)

Jeżeli natomiast mamy do czynienie z żądaniem ponownym, to widok odpowiadający danej stronie już istnieje w pamięci JSF. Następuje wtedy jego przywrócenie przy użyciu informacji o stanie zapisanych po stronie klienta lub serwera i przejście do następnego kroku.

Apply Request Values Phase

Po odczytaniu struktury komponentu z pamięci podręcznej JSF w pamięci jest już utworzone drzewo komponentów i teraz każdy z nich odczytuje nowe parametry czy też wartości z parametrów przekazanych w zapytaniu o stronie. Odczytana wartość zostaje lokalnie zapisane w danym komponencie. Jeżeli z jakiś powodów nie uda się poprawnie odczytać wartości, zostanie utworzony komunikat o błędzie skojarzony z odpowiednim komunikatem i wysłany do kolejki komunikatów FacesContext. Zostanie on potem wyświetlony już w trakcie tworzenia strony HTML, łącznie z innymi komunikatami które zostały czy też zostaną w kolejnych fazach utworzone.

Process Validations Phase

Podczas tego kroku następuje sprawdzenie poprawności danych zapisanych w poszczególnych komponentach. Sprawdzeniu zostają poddane odpowiednie atrybuty komponentów i są one testowane pod kątek zdefiniowanych reguł oraz ograniczeń.

Jeżeli wystąpi błąd podczas testów, zostaje wygenerowany komunikat błędu i dodany do kolejki komunikatów w FacesContext. W takim przypadku następuje także przejście do fazy odpowiedzialnej za utworzenie strony HTML (Render Response Phase), gdzie nastąpi wyświetlenie wszystkich komunikatów o błędach.

Trzy uwagi:

  • jeżeli jakakolwiek metoda wywoływana podczas tej fazy wywoła metodę FacesConext.renderResponse nastąpi przejście do kroku tworzenia strony HTML (Render Response Phase)
  • jeżeli aplikacje chce przekierować zapytań do innego zasobu (strony) lub też na stronie nie ma komponentów JSF, może wywołać metodę FacesContext.responseComplete
  • jeżeli jakieś zdarzenie zostaną zakolejkowane to JSF prześle je do nasłuchujących obiektów

Update Model Values Phase

Po sprawdzeniu, że dane są poprawne, JSP może zająć się ustawianiem odpowiednich wartości w obiektach znajdujących sie po stronie serwera. Zaktualizowane zostaną tyle te wartości, które zostały przesłane do aktualizacji w zapytaniu o stronę. Jeżeli wystąpią błędy podczas przypisywania wartości, to JSF przejdzie do kroku tworzenia strony HTML (Render Response Phase).

Trzy uwagi (jak wyżej):

  • jeżeli jakakolwiek metoda wywoływana podczas tej fazy wywoła metodę FacesConext.renderResponse nastąpi przejście do kroku tworzenia strony HTML (Render Response Phase)
  • jeżeli aplikacje chce przekierować zapytań do innego zasobu (strony) lub też na stronie nie ma komponentów JSF, może wywołać metodę FacesContext.responseComplete
  • jeżeli jakieś zdarzenie zostaną zakolejkowane to JSF prześle je do nasłuchujących obiektów

Invoke Application Phase

Podczas tego kroku JSF przetwarza wszelkiego rodzaju zdarzenia mające miejsce na poziomie aplikacji, takie jak wysłanie formularza czy też linkowania do innej strony.

Trzy uwagi (jak wyżej):

  • jeżeli jakakolwiek metoda wywoływana podczas tej fazy wywoła metodę FacesConext.renderResponse nastąpi przejście do kroku tworzenia strony HTML (Render Response Phase)
  • jeżeli aplikacje chce przekierować zapytań do innego zasobu (strony) lub też na stronie nie ma komponentów JSF, może wywołać metodę FacesContext.responseComplete
  • jeżeli jakieś zdarzenie zostaną zakolejkowane to JSF prześle je do nasłuchujących obiektów

Render Response Phase

Podczas tej fazy JSF generuje stronę przy użyciu JSP (jeżeli używamy JSP do generowania stron). W przypadku żądania początkowego komponenty znajdujące się na stronie zostaną dodane do drzewa komponentów jak tylko kontener JSP wykona stronę. Każdy komponent będzie samodzielnie tworzył odpowiedni kod HTML w monecie wywołania przez JSP.

W przypadku, gdy pojawią się jakieś błędy z poprzednich faz, zostanie wyświetlona oryginalna strona wraz z odpowiednimi komunikatami o błędach.

Po poprawnym utworzeniu strony jej stan zosanie zapisany, tak aby dało się go ponownie wykorzystać w razie potrzeby.

Źródła

Tags: , , , , ,

Czym jest JSF (JavaServer Faces)?

JavaServer Faces jest biblioteką przeznaczoną do budowania interfejsów użytkownika w aplikacjach WWW. Składa się ona z:

  • różnego zestawu API, na które składają się odpowiednie komponenty reprezentujące poszczególne elementu interfejsu użytkownika i pozwalające na zarządzanie ich stanem, przechwytywaniem zdarzeń, walidacji danych wejściowych, definicję nawigacji pomiędzy stronami, wpierające internacjonalizację;
  • zestawu komponentów JavaServer Pages (JSP) pozwalających na odwoływanie się do komponentów JSF na typowych stronach JSP

Powstanie JSF jest odpowiedzią na problemy, które istnieją podczas budowy stron tylko przy użyciu standardowych stron JSP, takich jak:

  • konieczność częstego powtarzania kodu
  • bezpośrednia praca z protokołem HTTP (pobieranie danych, wysyłanie strony do klienta)
  • konieczność ręcznej walidacji danych
  • brak wsparcie ze stron IDE
  • i pewnie wile innych, jak w każdej bibliotece niskopoziomowej

JSF miała się stać intuicyjną bibliotekę, która ułatwiła tworzenie aplikacji. A to dzięki:

  • umożliwienie prostego umieszczania wybranych komponentów na stronie WWW
  • powiązanie zdarzeń występujących po stronie użytkownika z odpowiednim kodem wykonywanym po stronie serwera
  • powiązanie komponentów graficznych ze strony z danymi znajdującymi się po stronie serwera
  • tworzenie interfejsu użytkownika poprzez komponenty, które mogą być łatwo rozszerzane i wykorzystywane w innych miejscach
  • zapisywanie i odzyskiwanie stanu interfejsu użytkownika ponad czas trwanie zwykłego zapytania do serwera

Czemu JSF

JSF zostało rozwinięte w ramach Java Community Process (JCP) w ramach JSR-252. Projekt zakładał, że z biliteki tej będa korzystali nie tylko programiście, ale także ludzie tacy jak:

  • twórcy stron WWW – są odpowiedzialni za tworzenie wyglądu strony, definiują go m.in. poprzez użycie odpowiednich, dostarczonych komponentów;
  • programiści aplikacji – integrują aplikacje z wygląd, tworzą obiekty, oprogramowują zdarzenia i inne operacje;
  • twórcy komponentów – tworzą komponentu graficzne, wykorzystując możliwości JSF pod względem rozszerzania oraz ponownego używania kodu;
  • architekci aplikacji – projektują aplikację, definiują nawigację pomiędzy stronami, zapewniają odpowiednią skalowalność aplikacji;
  • dostarczyciele narzędzi – tworzą odpowiednie narzędzia, które mają ułatwić korzystanie z technologii JSF (np, JBoss Tools).

JSF powstało wg wzorca projektowego Model-View-Controller (MVC). Dlatego też łatwiej się projektuje aplikacje przy użyciu JSF (w porównaniu ze zwykłymi stronami JSP) oraz są one prostsze (i tańsze) w późniejszym utrzymaniu. Zalety korzystania z JSF:

  • JSF to zbiór standardowych, wielokrotnie używalnych komponentów pozwalających na tworzenie interfejsu użytkownika
  • w JSF znajduje się wiele bibliotek tagów, które pozwalają na dostęp oraz modyfikację komponentów
  • pozwala na automatyczne zapisanie danych oraz ponowne ich wczytanie gdy są wyświetlane ponownie po stronie klienta
  • ukrywa przed programistami operacje przechwytywania zdarzeń oraz wyświetlania komponentów, pozwalając skoncentrować się po prostu na ich obsłudze
  • łatwe tworzenie własnych rozszerzeń i używanie ich łącznie ze standardowymi elementami JSF
  • możliwość łatwego tworzenia nawigacji pomiędzy różnymi stronami
  • wsparcie dla wielu różnych urządzeń występujących po stronie klienta (ważne, gdy tworzymy stronę mającą także działać poprawnie z telefonami komórkowymi)
  • wsparcie dla tłumaczenia zawartości strony

Źródła

Tags: , , ,

Brak uzupełniania kodu podczas edycji strony JSF w Eclipse

Czasami zdarza się, że brakuje autouzpełniania kodu (np. beanów) podczas edycji stron JSF (lub XHTML) w Eclipsie. Podczas otwierania takiej strony pojawia się następujące ostrzeżenie:

Brak właściwości JSF

Brak właściwości JSF

Informuje ono, że nie zostały włączone właściwości związane z JSF. Od razu także kieruje na stronę JBosstoolsVisualEditorFAQ, gdzie można znaleźć opis problemu i jego rozwiązanie. Niestety, w moim przypadku rozwiązanie nie zadziałało do końca ;), więc poniżej szczegółowa recepta co zrobić, aby włączyć obsługę autouzupełniania kodu na stronach JSF

Pierwszym krokiem jest taka konfiguracja projektu, aby Eclipse wiedział, że używamy JSF. Należy zaznaczyć projekt w widoku Project Explorer, wywoałć menu przy użyciu prawego klawisza myszy, wybrać pozycję Configure, i na końcu Add JSF Capabilities.

Dodanie możliwości związane z JSF

Dodanie możliwości związane z JSF

Zostanie uruchomiony kreator, w którym należy zdefiniować podstawowe informacje o projekcie.

W pierwszym kroku należy podać nazwę projektu, oraz wskazać lokalizację pliku web.xml danego projektu. W moim przypadku obie wartości były zdefiniowane poprawnie.

Kreator dodania właściwości JSF, strona 1

Kreator dodania właściwości JSF, strona 1

W drugim kroku należy zdefiniować trochę więcej parametrów:

  • Web Root – ścieżka dostępu do zasobów WWW
  • Source Folder – ścieżka dostępu do plików źródłowych
  • Classes Folder – ścieżka dostępu do skompilowanych plików źródłowych
  • Lib Folder
  • Servlet Version
  • Context Path
  • Runtime – serwer, na którym będzie publikowana aplikacja

W moim przypadku musiałem skonfigurować dwa parametry ręcznie:

  • Classes Folder – został błędnie wykryty przez kreator, trzeba było zmienić ścieżka do katalogu build/classes
  • Runtime – podać właściwy serwer, który ma być używany do uruchamiania aplikacji
Kreator dodania właściwości JSF, strona 2

Kreator dodania właściwości JSF, strona 2

Po tych modyfikacjach powinno już działać autouzpełnianie beanów zarówno na strona JSF jak i XHTML.

Tags: , , , , , ,

Poziom izolacji transakcji w JDBC

Dostępny interfejs dostępu do baz danych w Javie (JDBC) udostępnia kilka różnych poziomów izolacji poszczególnych transakcji. Pozwala na określenie, jak bardzo poszczególne transakcje mają być oddzielone od siebie. Niezależnie od poziomu izolacji transakcji, operacje takie jak wstawianie (INSERT), usuwanie (DELETE) oraz modyfikowanie (UPDATE) rekordów zachowują się zawsze tak samo, jedynie zachowanie operacji pobierającej (SELECT) dane z tabeli może być rożne.

Poziom transakcji jest ustawiany w ramach pojedynczego połączenia z bazą danych. Można go ustawia się go przy użyciu metody Connection.setTransactionIsolation(). Im wyższy poziom izolacji transakcji tym generalnie mniejsza wydajność operacji na bazie danych oraz większe prawdopodobieństwo wystąpienia blokad w dostępie do bazy danych.

Anomalie występujące w transakcjach

Poniżej znajduje się zestawienie anomalii, jakie mogą wystąpić w transakcjach:

Anomalie występujące w transakcjach
Nazwa anomalii Przykład działania anomalii
Dirty Reads

Mamy z nią do czynienia wtedy, gdy następuje w danej transakcji A odczyt zmodyfikowanych w transakcji B danych, a transakcja ta (B) nie została jeszcze zatwierdzona.

Transakcja A rozpoczyna się, i wywołuje:

SELECT * FROM zamowienia

Transakcja B w tym samym czasie wykonuje:

UPDATE zamowienie
SET wartosc_zamowienia=100
WHERE nr_zamowienia=123

Istnieje możliwość, że w transakcji A zostanie odczytana nowa wartość pola wartosc_zamowienia, nawet jeżeli nie zostanie to zapytanie zatwierdzone.

Non-Repeatable Reads

Ze zdarzeniem takim mamy do czynienia wtedy, gdy zapytania A wykonane w różnych momentach jednej transakcji może zwrócić inne wyniki (to samo zapytanie nie daje tego samego rezultatu). Zdarzyć się tak może, gdy w trakcie działania transakcji dane zostaną zmodyfikowane przez inną operacje na bazie danych.

Transakcja A rozpoczyna się, i wywołuje:

SELECT * FROM zamowienia
WHERE nr_zamowienia=123

Transakcja B w tym samym czasie wykonuje:

UPDATE zamowienie
SET wartosc_zamowienia=100
WHERE nr_zamowienia=123;

COMMIT;

Wykonanie ponowne zapytania w transakcji A spowoduje, że zostanie tym razem zwrócony zmodyfikowany rekord.

Phantom Reads

Z taką sytuacją mamy do czynienia wtedy, gdy transakcja A odczytuje dane z bazy danych, w trakcie jej trwanie transakcja B umieści w bazie danych rekord, który spełnia warunki zapytania z transakcji A. Jeżeli teraz w transakcji ponownie zostanie wykonane zapytanie, nowy rekord także zostanie zwrócony, co powoduje niezgodność wyniku działania dwóch zapytań w ramach tej samej transakcji.

Transakcja A odczytuje dane:

SELECT * FROM zamowienia
WHERE nr_zamowienia > 123

Transakcja B wstawia nowy wiersz do tabeli:

INSERT INTO zamowienia
(nr_zamowienia, nazwa)
VALUES ('140', 'Babol złapany');

COMMIT;

Jeżeli teraz w transakcji A ponownie wykonamy zapytanie, to nowy rekord także zostanie pobrany.

Poziomy transakcji

Rozróżniane są następujące poziomy transakcji:

  • TRANSACTION_READ_UNCOMMITTED

    Brak izolacji. Wszelkie zmiany, także te które nie są zatwierdzone jeszcze, są widoczne dla wszystkich zapytań w bazie danych.

  • TRANSACTION_READ_COMMITTED

    Minimalna izolacja, transakcje widzą tylko takie dane, które już są zatwierdzone i zapisane w bazie danych.

  • TRANSACTION_REPEATABLE_READ

    Poziom ten zapewnia powtarzalność odczytu danych. Jeżeli jakiś rekord zostanie odczytany, to nawet jego zatwierdzona modyfikacja w innej transakcji nie zmieni jego wartości przy ponownym odczycie.

  • TRANSACTION_SERIALIZABLE

    Najwyższy poziom transakcji, zwany szeregowym. Zapewnia on najlepszą izolację poszczególnych transakcji, które nie widzą swoich wzajemnych działań i nie wpływają na siebie. W momencie rozpoczęcia transakcji, stan bazy danych jest „zamrażany” i tylko na takim stanie transakcja może działać.

Lista anomalii jakie występują przy określonych typach transakcji, w zależności od sposobu blokowania danych:
Nazwa transakcji Blokada tabeli Blokada wiersza Wydajność
TRANSACTION_READ_UNCOMMITTED Możliwe: dirty reads, non-repeatable reads, phantom reads Możliwe: dirty reads, non-repeatable reads, phantom reads najszybsza
TRANSACTION_READ_COMMITTED Możliwe: non-repeatable reads i phantom reads Możliwe: non-repeatable reads i phantom reads szybka
TRANSACTION_REPEATABLE_READ Ponieważ blokowana jest cała tabela, to phantom reads nie są możliwe Możliwe są phantom reads średnia
TRANSACTION_SERIALIZABLE Brak anomalii Brak anomalii wolna

Źródła

Tags: , , , ,

Wielkość liter w nazwach tabel w MySQL

Baza danych MySQL na Linuksach jest wrażliwa na wielkość znaków w nazwach tabel. Czyli dwa takie zapytania:

1
2
3
SELECT FROM tabela;

SELECT FROM TABELA;

Może się okazać, że wykonanie jednego z nich spowoduje wyrzucenie komunikatu, mówiącego że podana tabela nie istnieje.

Co można zrobić w takiej sytuacji:

  1. Zmodyfikować aplikację, tak aby odwoływała się do tabel tak, jak są nazywane w bazie danych.
    Fajne, ale raz dużo pracy, dwa nie zawsze mamy kody źródłowe, trzy nie chcemy nikomu za to płacić.
  2. Zmodyfikować konfigurację serwera bazy danych oraz bazę danych
    Łatwiejsze niż modyfikacja kodu źródłowego, ale dotyczyć będzie wszystkich baz danych oraz aplikacji z niej korzystających.

Jak zmodyfikować konfigurację serwera aby nie było problemów z wielkością znaków w tabelach?

  1. Zmiana wielkości znaków w tabelach
    Pierwszym krokiem jest zmiana wielkości znaków nazw tabel we wszystkich bazach danych na małe litery. Pomocny może być ten skrypt, produkujący odpowiednie zapytania, które należy następnie wykonać (autor Anders Eriksson):

    SELECT CONCAT('rename table ', TABLE_NAME, ' to ' , LOWER(TABLE_NAME) , ';')
    FROM information_schema.`tables`
    WHERE table_schema = 'nazwa_bazy_danych';

    Wynik zapytania należy wykonać na bazie danych, spowoduje to zmianę nazw tabel na pisane tylko małymi znakami.

    Małe ostrzeżenie: Jeżeli w bazie danych istnieją dwie tak samo nazywające się tabele ale zapisane różną wielkością znaków, to MySQL zgłosi błąd podczas wykonywania powyższej operacji.

  2. Modyfikacja pliku konfiguracyjnego /etc/mysql/my.cnf
    Ostatnim krokiem jest odpowiednia konfiguracji bazy danych, tak aby zawsze już były używane małe litery do oznaczania tabel. Należy do pliku /etc/mysql/my.cnf, w sekcji mysqld dodać linię z parametrem lower_case_table_names

    31
    32
    [mysqld]
    lower_case_table_names=1

Od tej pory nie powinno już być problemów z różną wielkością znaków na nazwach tabel. Więcej informacji na temat tej opcji konfiguracyjnej można znaleźć na stronach MySQL.

Źródła

Tags: ,