Java EE 6. Zaawansowany przewodnik. [4 ed.]

Java Enterprise Edition 6 (Java EE6) to nowa jakość w tworzeniu korporacyjnych, zaawansowanych aplikacji. Wyjątkowo łatw

645 197 5MB

Polish Pages [503] Year 2013

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Java EE 6. Zaawansowany przewodnik. [4 ed.]

Table of contents :
Spis treści
Wstęp
Zanim przeczytasz tę książkę
Dokumentacja powiązana z książką
Konwencje typograficzne
Domyślnie ścieżki i nazwy plików
Inne witryny z dodatkowymi informacjami
Podziękowania
Część I. Wprowadzenie
Rozdział 1. Przegląd technologii
Najważniejsze cechy platformy Java EE 6
Model aplikacji Javy EE
Rozproszone, wielowarstwowe aplikacje
Bezpieczeństwo
Komponenty Javy EE
Klienty Javy EE
Komponenty webowe
Komponenty biznesowe
Warstwa danych
Kontenery Javy EE
Usługi kontenera
Typy kontenerów
Obsługa usług sieciowych
XML
Protokół transportowy SOAP
Standard formatu WSDL
Budowanie i wdrażanie aplikacji Javy EE
Pakowanie aplikacji
Role w procesie wytwarzania aplikacji
Dostawca oprogramowania Java EE
Dostawca narzędzi
Dostawca komponentów aplikacji
Budowniczy aplikacji
Wdrożeniowiec oraz administrator
API Javy EE 6
Technologia Enterprise JavaBeans
Technologia Java Servlet
Technologia JavaServer Faces
Technologia JavaServer Pages
Biblioteka JavaServer Pages Standard Tag Library
Java Persistence API
Java Transaction API
API Javy dla usług sieciowych typu REST
Managed Beans
Contexts and Dependency Injection for the Java EE Platform (JSR 299)
Dependency Injection for Java (JSR 330)
Bean Validation
Java Message Service API
Architektura Java EE Connector
JavaMail API
Java Authorization Contract for Containers
Java Authentication Service Provider Interface for Containers
API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7
Java Database Connectivity API
Java Naming and Directory Interface API
JavaBeans Activation Framework
Java API for XML Processing
Java Architecture for XML Binding
SOAP with Attachments API for Java
Java API for XML Web Services
Java Authentication And Authorization Service
Narzędzia serwera GlassFish
Rozdział 2. Używanie przykładowych aplikacji z samouczka
Wymagane oprogramowanie
Java Platform, Standard Edition
Java EE 6 Software Development Kit
Komponent samouczka Javy EE 6
NetBeans IDE
Apache Ant
Uruchamianie i zatrzymywanie serwera GlassFish
Uruchamianie konsoli administracyjnej
Uruchamianie i zatrzymywanie serwera Java DB
Budowanie przykładowych aplikacji
Struktura katalogów z przykładami samouczka
Pobieranie najnowszych aktualizacji samouczka
Debugowanie aplikacji Javy EE
Używanie logów serwera
Używanie debuggera
Część II. Warstwa webowa
Rozdział 3. Technologia JavaServer Faces — tematy zaawansowane
Cykl życia aplikacji JavaServer Faces
Omówienie cyklu życia JavaServer Faces
Faza przywrócenia widoku
Faza zastosowania wartości zapytania
Faza przetwarzania walidacji
Faza aktualizacji wartości modelu
Faza wywołania aplikacji
Faza renderowania odpowiedzi
Częściowe przetwarzanie i rendering
Cykl życia aplikacji faceletów
Model komponentów interfejsu użytkownika
Klasy komponentów interfejsu użytkownika
Model renderingu komponentów
Model konwersji
Model zdarzeń i procesów ich obsługi
Model walidacji
Model nawigacji
Rozdział 4. Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces
Technologia Ajax — wprowadzenie
Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces
Wykorzystanie technologii Ajax wraz z faceletami
Użycie znacznika f:ajax
Wysłanie żądania Ajax
Użycie atrybutu event
Użycie atrybutu execute
Użycie atrybutu immediate
Użycie atrybutu listener
Monitorowanie zdarzeń po stronie klienta
Obsługa błędów
Otrzymywanie odpowiedzi Ajax
Cykl życia żądania Ajax
Grupowanie komponentów
Wczytywanie kodu JavaScript jako zasobu
Użycie API dla kodu JavaScript w aplikacji z faceletami
Użycie adnotacji @ResourceDependency w klasie ziarna
Przykładowa aplikacja ajaxguessnumber
Pliki źródłowe
Uruchomienie przykładu ajaxguessnumber
Dodatkowe informacje na temat użycia technologii Ajax wraz z technologią JavaServer Faces
Rozdział 5. Komponenty złożone — tematy zaawansowane i przykłady
Atrybuty komponentu złożonego
Wywoływanie zarządzanego ziarna
Walidacja wartości komponentu złożonego
Przykładowa aplikacja compositecomponentlogin
Plik komponentu złożonego
Strona wykorzystująca komponent
Zarządzane ziarno
Uruchomienie przykładu compositecomponentlogin
Rozdział 6. Tworzenie własnych komponentów UI i innych obiektów
Określanie, czy potrzebny jest własny komponent lub renderer
Kiedy użyć własnego komponentu?
Kiedy zastosować własny renderer?
Kombinacje komponentów, rendererów i znaczników
Analiza przykładu z mapą obrazu
Dlaczego mam korzystać z technologii JavaServer Faces do implementacji mapy obrazu?
Działanie zrenderowanego kodu HTML
Omówienie strony faceletu
Konfiguracja danych modelu
Podsumowanie klas mapy obrazu
Kroki niezbędne do utworzenia własnego komponentu
Tworzenie własnych klas komponentów
Określenie rodziny komponentu
Przeprowadzenie kodowania
Przeprowadzenie dekodowania
Umożliwienie właściwościom komponentu przyjmowania wyrażeń
Zapis i przywracanie stanu
Przekazanie renderowania do renderera
Tworzenie klasy renderera
Określenie rodzaju renderera
Implementacja klasy nasłuchiwania zdarzeń
Implementacja klasy nasłuchiwania zdarzeń zmiany wartości
Implementacja klas nasłuchujących akcji
Obsługa zdarzeń dla samodzielnie wykonanych komponentów
Definicja znacznika własnego komponentu w deskryptorze biblioteki znaczników
Użycie własnego komponentu
Utworzenie i użycie własnego konwertera
Tworzenie własnego konwertera
Użycie własnego konwertera
Utworzenie i użycie własnego walidatora
Implementacja interfejsu Validator
Określanie własnego znacznika
Użycie własnego walidatora
Wiązanie wartości i instancji komponentów z właściwościami zarządzanego ziarna
Powiązanie wartości komponentu z właściwością
Powiązanie wartości komponentu z niejawnym obiektem
Powiązanie instancji komponentu z właściwością ziarna
Wiązanie konwerterów, walidatorów i obsługi zdarzeń z właściwościami zarządzanego ziarna
Rozdział 7. Konfiguracja aplikacji JavaServer Faces
Wykorzystanie adnotacji do konfiguracji zarządzanych ziaren
Korzystanie z zasięgów zarządzanych ziaren
Plik zasobu konfiguracji aplikacji
Kolejność plików zasobów konfiguracji aplikacji
Konfiguracja zarządzanych ziaren
Użycie elementu managed-bean
Inicjalizacja właściwości przy użyciu elementu managed-property
Inicjalizacja odwzorowań i list
Rejestracja komunikatów aplikacji
Użycie FacesMessage do utworzenia komunikatu
Dostęp do komunikatów o błędach
Korzystanie z walidatorów domyślnych
Rejestracja własnego walidatora
Rejestracja własnego konwertera
Konfiguracja reguł nawigacyjnych
Niejawne reguły nawigacyjne
Rejestracja własnego renderera w zestawie rendererów
Rejestracja własnego komponentu
Podstawowe wymagania stawiane aplikacjom JavaServer Faces
Konfiguracja aplikacji przy użyciu deskryptora wdrożenia
Konfiguracja etapu projektu
Dołączanie klas, stron i innych zasobów
Rozdział 8. Przesył plików do serwera w technologii Java Servlet
Adnotacja @MultipartConfig
Metody getParts i getPart
Przykładowa aplikacja fileupload
Architektura przykładowej aplikacji
Uruchomienie przykładu fileupload
Rozdział 9. Umiędzynarodowienie i lokalizacja aplikacji webowych
Klasy umiędzynarodowienia platformy Javy
Lokalizacja komunikatów i etykiet
Określanie dostępnych języków i regionów
Określenie paczki zasobów
Pobranie komunikatów w odpowiednim języku
Formatowanie dat i czasu
Kodowanie i zestawy znaków
Zestawy znaków
Kodowanie znaków
Część III. Usługi sieciowe
Rozdział 10. JAX-RS — tematy zaawansowane oraz przykład
Adnotacje dla pól i właściwości ziarna w klasach zasobów
Wydobycie parametrów ścieżki
Wydobycie parametrów zapytania
Wydobycie danych formularza
Wydobycie typu Javy dla żądania lub odpowiedzi
Podzasoby i dobór zasobów w trakcie działania usługi
Metody podzasobów
Lokalizator podzasobu
Integracja JAX-RS z technologią EJB i CDI
Warunkowe żądania HTTP
Negocjacja treści w trakcie działania usługi
Użycie JAX-RS z JAXB
Wykorzystanie obiektów Javy do modelowania własnych danych
Rozpoczynanie pracy od definicji schematu XML
Użycie formatu JSON wraz z JAX-RS i JAXB
Przykładowa aplikacja customer
Omówienie elementów przykładowej aplikacji
Klasy encji Customer i Address
Klasa CustomerService
Klasy CustomerClientXML i CustomerClientJSON
Modyfikacja przykładu, by generował klasy encji z istniejącego schematu
Uruchomienie przykładu customer
Część IV. Komponenty EJB
Rozdział 11. Przykład ziarna sterowanego komunikatami
Omówienie przykładu simplemessage
Klient aplikacji simplemessage
Klasa ziarna sterowanego komunikatami
Metoda onMessage
Uruchomienie przykładu simplemessage
Obiekty administrowane związane z przykładem simplemessage
Usunięcie administrowanych obiektów z przykładu simplemessage
Rozdział 12. Korzystanie z osadzonego kontenera komponentów EJB
Omówienie osadzonego kontenera komponentów EJB
Tworzenie aplikacji z EJB z możliwością osadzania
Uruchamianie osadzonych aplikacji
Tworzenie kontenera EJB
Wyszukiwanie referencji do ziaren sesyjnych
Wyłączanie kontenera EJB
Przykładowa aplikacja standalone
Rozdział 13. Wywoływanie metod asynchronicznych ziaren sesyjnych
Wywoływanie metod asynchronicznych
Tworzenie asynchronicznych metod biznesowych
Wywoływanie metod asynchronicznych z poziomu klientów EJB
Przykładowa aplikacja async
Architektura przykładowej aplikacji async
Uruchomienie przykładu async
Część V. Konteksty oraz wstrzykiwanie zależności na platformie Java EE
Rozdział 14. Konteksty oraz wstrzykiwanie zależności na platformie Java EE — tematy zaawansowane
Wykorzystanie alternatyw w aplikacjach CDI
Specjalizacje
Wykorzystanie w aplikacjach CDI metod produkujących, pól produkujących i metod usuwających
Użycie metody produkującej
Użycie pól produkujących do generowania zasobów
Metody usuwające
Użycie predefiniowanych ziaren w aplikacjach CDI
Wykorzystanie zdarzeń w aplikacjach CDI
Definiowanie zdarzeń
Użycie metod obserwatorów do obsługi zdarzeń
Zgłaszanie zdarzeń
Użycie interceptorów w aplikacjach CDI
Użycie dekoratorów w aplikacjach CDI
Użycie stereotypów w aplikacjach CDI
Rozdział 15. Uruchamianie zaawansowanych przykładów dotyczących kontekstów i wstrzykiwania zależności
Przykład encoder — użycie alternatyw
Interfejs Coder i jego implementacje
Strona faceletu i zarządzane ziarno
Uruchomienie przykładowej aplikacji encoder
Przykład producermethods — użycie metody produkującej do wyboru implementacji ziarna
Składniki przykładu producermethods
Uruchomienie przykładowej aplikacji producermethods
Przykład producerfields — użycie pól produkujących do generowania zasobów
Pole produkujące w przykładzie producerfields
Ziarno sesyjne i encja producerfields
Zarządzane ziarno i strony faceletów
Uruchomienie przykładowej aplikacji producerfields
Przykład billpayment — zdarzenia i interceptory
Klasa zdarzenia PaymentEvent
Klasa nasłuchiwania zdarzeń PaymentHandler
Strony faceletów i zarządzane ziarno przykładu billpayment
Klasa interceptora LoggedInterceptor
Uruchomienie przykładowej aplikacji billpayment
Przykład decorators — dekorowanie ziarna
Elementy przykładu decorators
Uruchomienie przykładowej aplikacji decorators
Część VI. Java Persistence API
Rozdział 16. Tworzenie i używanie tekstowych zapytań z kryteriami
Wprowadzenie do zapytań tekstowych w Criteria API
Tworzenie zapytań tekstowych
Wykonywanie zapytań tekstowych
Rozdział 17. Sterowanie współbieżnym dostępem do danych encji przy użyciu blokad
Omówienie blokowania encji i współbieżności
Użycie blokad optymistycznych
Tryby blokad
Ustawienie trybu blokady
Użycie blokad pesymistycznych
Rozdział 18. Wykorzystanie pamięci cache drugiego poziomu w aplikacjach Java Persistence API
Wprowadzenie do pamięci cache drugiego poziomu
Określanie, czy encje można umieścić w cache
Określanie ustawień trybu cache w celu poprawy wydajności
Ustawienie trybu pobierania i zapisu w cache
Sterowanie cache drugiego poziomu w sposób programowy
Część VII. Bezpieczeństwo
Rozdział 19. Bezpieczeństwo w Javie EE — tematy zaawansowane
Korzystanie z certyfikatów cyfrowych
Tworzenie certyfikatu serwera
Dodanie użytkowników do dziedziny certyfikatu
Użycie innego certyfikatu serwera w serwerze GlassFish
Mechanizmy uwierzytelniania
Uwierzytelnianie klienta
Uwierzytelnianie wzajemne
Logowanie przy użyciu formularza w aplikacjach JavaServer Faces
Użycie j_security_check w formularzach JavaServer Faces
Użycie zarządzanego ziarna do uwierzytelniania w aplikacjach JavaServer Faces
Uwierzytelnianie za pomocą JDBC Realm
Zabezpieczanie zasobów HTTP
Zabezpieczenie klientów aplikacji
Użycie modułów logowania
Użycie logowania programowego
Zabezpieczanie aplikacji typu EIS
Logowanie zarządzane przez kontener
Logowanie zarządzane przez komponent
Konfiguracja bezpieczeństwa adapterów zasobów
Konfiguracja bezpieczeństwa przy użyciu deskryptorów wdrożenia
Określanie w deskryptorze wdrożenia zasad bezpieczeństwa dla prostego uwierzytelniania
Wskazanie w deskryptorze wdrożenia niedomyślnego odwzorowania zarządzającego na rolę
Dalsze informacje na temat bezpieczeństwa
Część VIII. Technologie wspomagające Javę EE
Rozdział 20. Zagadnienia technologii JMS
Wprowadzenie do JMS API
Czym jest przekazywanie komunikatów?
Czym jest JMS API?
Kiedy mogę użyć JMS API?
W jaki sposób JMS API współpracuje z platformą Javy EE?
Podstawowe koncepcje JMS API
Architektura JMS API
Dziedziny komunikatów
Konsumpcja komunikatów
Model programistyczny JMS API
Obiekty administracyjne JMS
Połączenia JMS
Sesje JMS
Producenty komunikatów JMS
Konsumenty komunikatów JMS
Komunikaty JMS
Przeglądarki kolejek JMS
Obsługa wyjątków JMS
Tworzenie wydajnych aplikacji JMS
Użycie prostych mechanizmów trwałości
Użycie zaawansowanych mechanizmów niezawodności
Wykorzystanie JMS API w aplikacjach Javy EE
Użycie adnotacji @Resource w komponentach webowych i EJB
Użycie ziaren sesyjnych do produkcji i synchronicznego otrzymywania komunikatów
Wykorzystanie ziaren sterowanych komunikatami do asynchronicznego otrzymywania komunikatów
Zarządzanie transakcjami rozproszonymi
Korzystanie z JMS API w klientach aplikacji i komponentach webowych
Dodatkowe informacje na temat JMS
Rozdział 21. Przykłady wykorzystania JMS
Tworzenie prostych aplikacji JMS
Prosty przykład synchronicznego otrzymywania komunikatów
Prosty przykład asynchronicznego otrzymywania komunikatów
Prosty przykład przeglądania komunikatów w kolejce
Uruchomienie klientów JMS na wielu systemach
Usunięcie wdrożenia i wyczyszczenie systemu po przykładach JMS
Tworzenie rozbudowanych aplikacji JMS
Przykład potwierdzania komunikatu
Przykład trwałej subskrypcji
Przykład transakcji lokalnej
Aplikacja stosująca JMS API w połączeniu z ziarnem sesyjnym
Tworzenie komponentów aplikacji dla przykładu clientsessionmdb
Tworzenie zasobów dla przykładu clientsessionmdb
Uruchomienie przykładu clientsessionmdb
Aplikacja stosująca JMS API w połączeniu z encją
Opis przykładowej aplikacji clientmdbentity
Tworzenie komponentów przykładowej aplikacji clientmdbentity
Tworzenie zasobów dla przykładu clientmdbentity
Uruchomienie przykładu clientmdbentity
Przykład aplikacji konsumującej komunikaty z zewnętrznego serwera
Opis modułów przykładu consumeremote
Tworzenie komponentów modułu dla przykładu consumeremote
Tworzenie zasobów dla przykładu consumeremote
Użycie dwóch serwerów aplikacji dla przykładu consumeremote
Uruchomienie przykładu consumeremote
Przykład aplikacji wdrażającej ziarno sterowane komunikatami na dwóch serwerach
Opis modułów przykładu sendremote
Tworzenie komponentów modułów dla przykładu sendremote
Tworzenie zasobów dla przykładu sendremote
Uruchomienie przykładu sendremote
Rozdział 22. Mechanizm Bean Validation — tematy zaawansowane
Tworzenie własnych ograniczeń
Użycie wbudowanych ograniczeń do tworzenia własnych ograniczeń
Dostosowywanie komunikatów walidatorów
Paczka zasobów ValidationMessages
Grupowanie ograniczeń
Dostosowanie kolejności walidacji grup
Rozdział 23. Wykorzystanie interceptorów Javy EE
Wprowadzenie do interceptorów
Klasy interceptorowe
Cykl życia interceptorów
Interceptory i CDI
Użycie interceptorów
Wywołania metod przechwytujących
Unknown
Użycie wielu interceptorów metod
Dostęp do parametrów metody celu z poziomu klasy interceptorowej
Przechwytywanie zdarzeń wywołań zwrotnych cyklu życia
Przechwytywanie zdarzeń upłynięcia czasu
Przykładowa aplikacja interceptor
Uruchomienie przykładu interceptor
Rozdział 24. Przykład z adapterem zasobów
Adapter zasobów
Ziarno sterowane komunikatami
Aplikacja webowa
Uruchomienie przykładu mailconnector
Część IX. Przykładowe scenariusze użycia
Rozdział 25. Przykładowy scenariusz użycia — księgarnia Duke’a
Projekt i architektura księgarni Duke’a
Interfejs aplikacji
Encja Book korzystająca z Java Persistence API
Komponenty EJB wykorzystywane w przykładzie
Strony faceletów i zarządzane ziarna używane w przykładowej aplikacji
Własne komponenty i inne własne obiekty wykorzystywane w księgarni Duke’a
Pliki właściwości używane przez aplikację
Deskryptory wdrożeń użyte w przykładowej aplikacji
Uruchomienie aplikacji księgarnia Duke’a
Rozdział 26. Przykładowy scenariusz użycia — ćwiczenia Duke’a
Projekt i architektura aplikacji
Interfejs główny
Encje Java Persistence API wykorzystywane przez interfejs główny
Komponenty EJB wykorzystywane w interfejsie głównym
Pliki faceletów wykorzystywane w interfejsie głównym
Klasy pomocnicze używane w interfejsie głównym
Pliki właściwości
Deskryptory wdrożenia wykorzystywane przez aplikację
Interfejs administracyjny
Komponenty EJB wykorzystywane przez interfejs administracyjny
Pliki faceletów wykorzystywane przez interfejs administracyjny
Uruchomienie przykładowej aplikacji ćwiczenia Duke’a
Konfiguracja serwera GlassFish
Uruchomienie aplikacji ćwiczenia Duke’a
Rozdział 27. Przykładowy scenariusz użycia — las Duke’a
Projekt i architektura aplikacji las Duke’a
Projekt events
Projekt entities
Projekt dukes-payment
Projekt dukes-resources
Projekt sklepu Duke’a
Projekt wysyłka Duke’a
Budowanie i wdrażanie aplikacji las Duke’a
Zadanie przygotowawcze
Uruchamianie aplikacji las Duke’a
Skorowidz

Citation preview

Spis treści

Wstęp ...............................................................................................................15 Część I. Wprowadzenie ................................................................................................19 Rozdział 1. Przegląd technologii ......................................................................................21 Najważniejsze cechy platformy Java EE 6 ................................................................................... 22 Model aplikacji Javy EE ................................................................................................................. 23 Rozproszone, wielowarstwowe aplikacje .................................................................................... 23 Bezpieczeństwo ........................................................................................................................ 25 Komponenty Javy EE .............................................................................................................. 25 Klienty Javy EE ......................................................................................................................... 25 Komponenty webowe ............................................................................................................. 27 Komponenty biznesowe ......................................................................................................... 28 Warstwa danych ...................................................................................................................... 29 Kontenery Javy EE .......................................................................................................................... 29 Usługi kontenera ..................................................................................................................... 30 Typy kontenerów ..................................................................................................................... 30 Obsługa usług sieciowych ............................................................................................................. 31 XML ........................................................................................................................................... 32 Protokół transportowy SOAP ................................................................................................ 32 Standard formatu WSDL ....................................................................................................... 33 Budowanie i wdrażanie aplikacji Javy EE ................................................................................... 33 Pakowanie aplikacji ........................................................................................................................ 33 Role w procesie wytwarzania aplikacji ........................................................................................ 35 Dostawca oprogramowania Java EE ..................................................................................... 36 Dostawca narzędzi ................................................................................................................... 36 Dostawca komponentów aplikacji ........................................................................................ 36 Budowniczy aplikacji .............................................................................................................. 37 Wdrożeniowiec oraz administrator ...................................................................................... 37 API Javy EE 6 .................................................................................................................................. 37 Technologia Enterprise JavaBeans ........................................................................................ 39 Technologia Java Servlet ......................................................................................................... 40 Technologia JavaServer Faces ................................................................................................ 41 Technologia JavaServer Pages ............................................................................................... 42 Biblioteka JavaServer Pages Standard Tag Library ............................................................. 42 Java Persistence API ................................................................................................................ 42

Spis treści

Java Transaction API ..............................................................................................................43 API Javy dla usług sieciowych typu REST ...........................................................................43 Managed Beans ........................................................................................................................43 Contexts and Dependency Injection for the Java EE Platform (JSR 299) .......................44 Dependency Injection for Java (JSR 330) .............................................................................44 Bean Validation .......................................................................................................................44 Java Message Service API .......................................................................................................44 Architektura Java EE Connector ...........................................................................................45 JavaMail API .............................................................................................................................45 Java Authorization Contract for Containers .......................................................................45 Java Authentication Service Provider Interface for Containers .......................................46 API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7 ............46 Java Database Connectivity API ............................................................................................46 Java Naming and Directory Interface API ...........................................................................47 JavaBeans Activation Framework .........................................................................................47 Java API for XML Processing ................................................................................................48 Java Architecture for XML Binding ......................................................................................48 SOAP with Attachments API for Java ..................................................................................48 Java API for XML Web Services ............................................................................................48 Java Authentication And Authorization Service ................................................................49 Narzędzia serwera GlassFish .........................................................................................................49

Rozdział 2. Używanie przykładowych aplikacji z samouczka ....................................... 51 Wymagane oprogramowanie .......................................................................................................51 Java Platform, Standard Edition ............................................................................................51 Java EE 6 Software Development Kit ....................................................................................52 Komponent samouczka Javy EE 6 ........................................................................................53 NetBeans IDE ...........................................................................................................................53 Apache Ant ...............................................................................................................................54 Uruchamianie i zatrzymywanie serwera GlassFish ...................................................................55 T Uruchamianie serwera GlassFish z poziomu środowiska NetBeans IDE .......................56 Uruchamianie konsoli administracyjnej .....................................................................................56 T Uruchamianie konsoli administracyjnej w środowisku NetBeans IDE ..........................56 Uruchamianie i zatrzymywanie serwera Java DB ......................................................................56 T Uruchamianie serwera bazy danych przy użyciu środowiska NetBeans IDE ................57 Budowanie przykładowych aplikacji ...........................................................................................57 Struktura katalogów z przykładami samouczka ........................................................................57 Pobieranie najnowszych aktualizacji samouczka ......................................................................58 T Aktualizacja samouczka za pomocą centrum aktualizacji ................................................58 Debugowanie aplikacji Javy EE ....................................................................................................59 Używanie logów serwera ........................................................................................................59 Używanie debuggera ...............................................................................................................59

4

Java EE 6. Zaawansowany przewodnik

Spis treści

Część II. Warstwa webowa ...........................................................................................61 Rozdział 3. Technologia JavaServer Faces — tematy zaawansowane .........................63 Cykl życia aplikacji JavaServer Faces ........................................................................................... 63 Omówienie cyklu życia JavaServer Faces ............................................................................. 64 Faza przywrócenia widoku ..................................................................................................... 66 Faza zastosowania wartości zapytania .................................................................................. 67 Faza przetwarzania walidacji ................................................................................................. 68 Faza aktualizacji wartości modelu ......................................................................................... 68 Faza wywołania aplikacji ........................................................................................................ 69 Faza renderowania odpowiedzi ............................................................................................. 69 Częściowe przetwarzanie i rendering .......................................................................................... 70 Cykl życia aplikacji faceletów ....................................................................................................... 70 Model komponentów interfejsu użytkownika ........................................................................... 71 Klasy komponentów interfejsu użytkownika ...................................................................... 71 Model renderingu komponentów ......................................................................................... 73 Model konwersji ...................................................................................................................... 74 Model zdarzeń i procesów ich obsługi ................................................................................. 75 Model walidacji ........................................................................................................................ 77 Model nawigacji ....................................................................................................................... 78

Rozdział 4. Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces .....81 Technologia Ajax — wprowadzenie ............................................................................................ 82 Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces .................................. 83 Wykorzystanie technologii Ajax wraz z faceletami ................................................................... 83 Użycie znacznika f:ajax ........................................................................................................... 84 Wysłanie żądania Ajax ................................................................................................................... 86 Użycie atrybutu event ............................................................................................................. 86 Użycie atrybutu execute ......................................................................................................... 86 Użycie atrybutu immediate .................................................................................................... 87 Użycie atrybutu listener .......................................................................................................... 87 Monitorowanie zdarzeń po stronie klienta ................................................................................ 87 Obsługa błędów .............................................................................................................................. 88 Otrzymywanie odpowiedzi Ajax .................................................................................................. 89 Cykl życia żądania Ajax ................................................................................................................. 90 Grupowanie komponentów .......................................................................................................... 90 Wczytywanie kodu JavaScript jako zasobu ................................................................................ 91 Użycie API dla kodu JavaScript w aplikacji z faceletami ................................................... 91 Użycie adnotacji @ResourceDependency w klasie ziarna ................................................. 92 Przykładowa aplikacja ajaxguessnumber .................................................................................... 93 Pliki źródłowe .......................................................................................................................... 93 Uruchomienie przykładu ajaxguessnumber ........................................................................ 95 Dodatkowe informacje na temat użycia technologii Ajax wraz z technologią JavaServer Faces ........................................................................................ 96

Java EE 6. Zaawansowany przewodnik

5

Spis treści

Rozdział 5. Komponenty złożone — tematy zaawansowane i przykłady .................... 97 Atrybuty komponentu złożonego ................................................................................................97 Wywoływanie zarządzanego ziarna .............................................................................................98 Walidacja wartości komponentu złożonego ..............................................................................98 Przykładowa aplikacja compositecomponentlogin ...................................................................99 Plik komponentu złożonego ..................................................................................................99 Strona wykorzystująca komponent .....................................................................................100 Zarządzane ziarno .................................................................................................................100 Uruchomienie przykładu compositecomponentlogin .....................................................101

Rozdział 6. Tworzenie własnych komponentów UI i innych obiektów ........................103 Określanie, czy potrzebny jest własny komponent lub renderer ..........................................105 Kiedy użyć własnego komponentu? ....................................................................................105 Kiedy zastosować własny renderer? ....................................................................................107 Kombinacje komponentów, rendererów i znaczników ...................................................107 Analiza przykładu z mapą obrazu ..............................................................................................108 Dlaczego mam korzystać z technologii JavaServer Faces do implementacji mapy obrazu? ......................................................................................................................109 Działanie zrenderowanego kodu HTML ...........................................................................109 Omówienie strony faceletu ..................................................................................................110 Konfiguracja danych modelu ...............................................................................................111 Podsumowanie klas mapy obrazu .......................................................................................113 Kroki niezbędne do utworzenia własnego komponentu ........................................................113 Tworzenie własnych klas komponentów ..................................................................................114 Określenie rodziny komponentu ........................................................................................117 Przeprowadzenie kodowania ...............................................................................................117 Przeprowadzenie dekodowania ...........................................................................................119 Umożliwienie właściwościom komponentu przyjmowania wyrażeń ............................120 Zapis i przywracanie stanu ...................................................................................................121 Przekazanie renderowania do renderera ..................................................................................122 Tworzenie klasy renderera ...................................................................................................123 Określenie rodzaju renderera ..............................................................................................124 Implementacja klasy nasłuchiwania zdarzeń ...........................................................................125 Implementacja klasy nasłuchiwania zdarzeń zmiany wartości ......................................125 Implementacja klas nasłuchujących akcji ..........................................................................126 Obsługa zdarzeń dla samodzielnie wykonanych komponentów ..........................................127 Definicja znacznika własnego komponentu w deskryptorze biblioteki znaczników .........128 Użycie własnego komponentu ....................................................................................................129 Utworzenie i użycie własnego konwertera ...............................................................................130 Tworzenie własnego konwertera .........................................................................................131 Użycie własnego konwertera ...............................................................................................133 Utworzenie i użycie własnego walidatora .................................................................................135 Implementacja interfejsu Validator ....................................................................................136 Określanie własnego znacznika ...........................................................................................138 Użycie własnego walidatora .................................................................................................138 Wiązanie wartości i instancji komponentów z właściwościami zarządzanego ziarna .......140 Powiązanie wartości komponentu z właściwością ............................................................141 Powiązanie wartości komponentu z niejawnym obiektem .............................................142

6

Java EE 6. Zaawansowany przewodnik

Spis treści

Powiązanie instancji komponentu z właściwością ziarna ...............................................144 Wiązanie konwerterów, walidatorów i obsługi zdarzeń z właściwościami zarządzanego ziarna ..................................................................................................................145

Rozdział 7. Konfiguracja aplikacji JavaServer Faces ....................................................147 Wykorzystanie adnotacji do konfiguracji zarządzanych ziaren ............................................148 Korzystanie z zasięgów zarządzanych ziaren ....................................................................148 Plik zasobu konfiguracji aplikacji ..............................................................................................149 Kolejność plików zasobów konfiguracji aplikacji .............................................................151 Konfiguracja zarządzanych ziaren .............................................................................................152 Użycie elementu managed-bean .........................................................................................153 Inicjalizacja właściwości przy użyciu elementu managed-property ..............................155 Inicjalizacja odwzorowań i list .............................................................................................160 Rejestracja komunikatów aplikacji ............................................................................................160 Użycie FacesMessage do utworzenia komunikatu ...........................................................162 Dostęp do komunikatów o błędach ....................................................................................162 Korzystanie z walidatorów domyślnych ...................................................................................163 Rejestracja własnego walidatora .................................................................................................164 Rejestracja własnego konwertera ...............................................................................................164 Konfiguracja reguł nawigacyjnych .............................................................................................165 T Konfiguracja reguły nawigacyjnej .......................................................................................167 Niejawne reguły nawigacyjne ..............................................................................................168 Rejestracja własnego renderera w zestawie rendererów .........................................................168 Rejestracja własnego komponentu ............................................................................................170 Podstawowe wymagania stawiane aplikacjom JavaServer Faces ...........................................171 Konfiguracja aplikacji przy użyciu deskryptora wdrożenia ............................................172 Konfiguracja etapu projektu ................................................................................................175 Dołączanie klas, stron i innych zasobów ...........................................................................176

Rozdział 8. Przesył plików do serwera w technologii Java Servlet .............................177 Adnotacja @MultipartConfig .....................................................................................................177 Metody getParts i getPart ............................................................................................................178 Przykładowa aplikacja fileupload ...............................................................................................179 Architektura przykładowej aplikacji ...................................................................................179 Uruchomienie przykładu fileupload ...................................................................................182

Rozdział 9. Umiędzynarodowienie i lokalizacja aplikacji webowych .........................185 Klasy umiędzynarodowienia platformy Javy ............................................................................185 Lokalizacja komunikatów i etykiet ............................................................................................186 Określanie dostępnych języków i regionów ......................................................................187 Określenie paczki zasobów ..................................................................................................187 Pobranie komunikatów w odpowiednim języku ..............................................................188 Formatowanie dat i czasu ............................................................................................................189 Kodowanie i zestawy znaków .....................................................................................................189 Zestawy znaków .....................................................................................................................189 Kodowanie znaków ...............................................................................................................190

Java EE 6. Zaawansowany przewodnik

7

Spis treści

Część III. Usługi sieciowe .............................................................................................193 Rozdział 10. JAX-RS — tematy zaawansowane oraz przykład ......................................195 Adnotacje dla pól i właściwości ziarna w klasach zasobów ....................................................195 Wydobycie parametrów ścieżki ...........................................................................................196 Wydobycie parametrów zapytania .....................................................................................197 Wydobycie danych formularza ...........................................................................................197 Wydobycie typu Javy dla żądania lub odpowiedzi ...........................................................198 Podzasoby i dobór zasobów w trakcie działania usługi ..........................................................198 Metody podzasobów .............................................................................................................199 Lokalizator podzasobu ..........................................................................................................199 Integracja JAX-RS z technologią EJB i CDI ..............................................................................200 Warunkowe żądania HTTP ........................................................................................................201 Negocjacja treści w trakcie działania usługi .............................................................................202 Użycie JAX-RS z JAXB ................................................................................................................204 Wykorzystanie obiektów Javy do modelowania własnych danych ................................205 Rozpoczynanie pracy od definicji schematu XML ...........................................................207 Użycie formatu JSON wraz z JAX-RS i JAXB ...................................................................209 Przykładowa aplikacja customer ................................................................................................210 Omówienie elementów przykładowej aplikacji ................................................................210 Klasy encji Customer i Address ...........................................................................................210 Klasa CustomerService .........................................................................................................213 Klasy CustomerClientXML i CustomerClientJSON ........................................................215 Modyfikacja przykładu, by generował klasy encji z istniejącego schematu ..................217 Uruchomienie przykładu customer ....................................................................................219

Część IV. Komponenty EJB ..........................................................................................225 Rozdział 11. Przykład ziarna sterowanego komunikatami ...........................................227 Omówienie przykładu simplemessage ......................................................................................227 Klient aplikacji simplemessage ...................................................................................................228 Klasa ziarna sterowanego komunikatami .................................................................................228 Metoda onMessage ................................................................................................................229 Uruchomienie przykładu simplemessage .................................................................................231 Obiekty administrowane związane z przykładem simplemessage .................................231 T Uruchomienie przykładu simplemessage w środowisku NetBeans IDE ......................231 T Uruchomienie przykładu simplemessage przy użyciu narzędzia Ant ...........................232 Usunięcie administrowanych obiektów z przykładu simplemessage ............................233

Rozdział 12. Korzystanie z osadzonego kontenera komponentów EJB .......................235 Omówienie osadzonego kontenera komponentów EJB .........................................................235 Tworzenie aplikacji z EJB z możliwością osadzania ................................................................235 Uruchamianie osadzonych aplikacji ...................................................................................236 Tworzenie kontenera EJB .....................................................................................................236

8

Java EE 6. Zaawansowany przewodnik

Spis treści

Wyszukiwanie referencji do ziaren sesyjnych ...................................................................237 Wyłączanie kontenera EJB ...................................................................................................238 Przykładowa aplikacja standalone .............................................................................................238 T Uruchomienie przykładowej aplikacji standalone ...........................................................239

Rozdział 13. Wywoływanie metod asynchronicznych ziaren sesyjnych .......................241 Wywoływanie metod asynchronicznych ..................................................................................241 Tworzenie asynchronicznych metod biznesowych ..........................................................242 Wywoływanie metod asynchronicznych z poziomu klientów EJB ................................243 Przykładowa aplikacja async .......................................................................................................244 Architektura przykładowej aplikacji async ........................................................................244 Uruchomienie przykładu async ..........................................................................................245

Część V. Konteksty oraz wstrzykiwanie zależności na platformie Java EE ............249 Rozdział 14. Konteksty oraz wstrzykiwanie zależności na platformie Java EE — tematy zaawansowane ............................................................................251 Wykorzystanie alternatyw w aplikacjach CDI .........................................................................251 Specjalizacje ............................................................................................................................252 Wykorzystanie w aplikacjach CDI metod produkujących, pól produkujących i metod usuwających ................................................................................................................253 Użycie metody produkującej ...............................................................................................254 Użycie pól produkujących do generowania zasobów ......................................................255 Metody usuwające .................................................................................................................255 Użycie predefiniowanych ziaren w aplikacjach CDI ...............................................................256 Wykorzystanie zdarzeń w aplikacjach CDI ..............................................................................257 Definiowanie zdarzeń ...........................................................................................................257 Użycie metod obserwatorów do obsługi zdarzeń .............................................................257 Zgłaszanie zdarzeń ................................................................................................................258 Użycie interceptorów w aplikacjach CDI .................................................................................259 Użycie dekoratorów w aplikacjach CDI ....................................................................................261 Użycie stereotypów w aplikacjach CDI .....................................................................................262

Rozdział 15. Uruchamianie zaawansowanych przykładów dotyczących kontekstów i wstrzykiwania zależności ...............................265 Przykład encoder — użycie alternatyw .....................................................................................265 Interfejs Coder i jego implementacje ..................................................................................266 Strona faceletu i zarządzane ziarno .....................................................................................266 Uruchomienie przykładowej aplikacji encoder ................................................................268 Przykład producermethods — użycie metody produkującej do wyboru implementacji ziarna ............................................................................................270 Składniki przykładu producermethods ..............................................................................270 Uruchomienie przykładowej aplikacji producermethods ...............................................272 Przykład producerfields — użycie pól produkujących do generowania zasobów ..............273 Pole produkujące w przykładzie producerfields ...............................................................273 Ziarno sesyjne i encja producerfields .................................................................................274

Java EE 6. Zaawansowany przewodnik

9

Spis treści

Zarządzane ziarno i strony faceletów .................................................................................276 Uruchomienie przykładowej aplikacji producerfields .....................................................277 Przykład billpayment — zdarzenia i interceptory ...................................................................279 Klasa zdarzenia PaymentEvent ............................................................................................279 Klasa nasłuchiwania zdarzeń PaymentHandler .................................................................280 Strony faceletów i zarządzane ziarno przykładu billpayment .........................................280 Klasa interceptora LoggedInterceptor ................................................................................283 Uruchomienie przykładowej aplikacji billpayment .........................................................284 Przykład decorators — dekorowanie ziarna .............................................................................285 Elementy przykładu decorators ...........................................................................................285 Uruchomienie przykładowej aplikacji decorators ............................................................286

Część VI. Java Persistence API .....................................................................................289 Rozdział 16. Tworzenie i używanie tekstowych zapytań z kryteriami ..........................291 Wprowadzenie do zapytań tekstowych w Criteria API ..........................................................291 Tworzenie zapytań tekstowych ..................................................................................................292 Wykonywanie zapytań tekstowych ............................................................................................293

Rozdział 17. Sterowanie współbieżnym dostępem do danych encji przy użyciu blokad .......................................................................................295 Omówienie blokowania encji i współbieżności .......................................................................295 Użycie blokad optymistycznych ..........................................................................................296 Tryby blokad .................................................................................................................................297 Ustawienie trybu blokady .....................................................................................................298 Użycie blokad pesymistycznych ..........................................................................................298

Rozdział 18. Wykorzystanie pamięci cache drugiego poziomu w aplikacjach Java Persistence API .............................................................301 Wprowadzenie do pamięci cache drugiego poziomu .............................................................301 Określanie, czy encje można umieścić w cache .................................................................302 Określanie ustawień trybu cache w celu poprawy wydajności ..............................................303 Ustawienie trybu pobierania i zapisu w cache ..................................................................303 Sterowanie cache drugiego poziomu w sposób programowy .........................................305

Część VII. Bezpieczeństwo ............................................................................................307 Rozdział 19. Bezpieczeństwo w Javie EE — tematy zaawansowane .............................309 Korzystanie z certyfikatów cyfrowych .......................................................................................309 Tworzenie certyfikatu serwera .............................................................................................310 Dodanie użytkowników do dziedziny certyfikatu ............................................................313 Użycie innego certyfikatu serwera w serwerze GlassFish ................................................313 Mechanizmy uwierzytelniania ....................................................................................................314 Uwierzytelnianie klienta .......................................................................................................314 Uwierzytelnianie wzajemne .................................................................................................314

10

Java EE 6. Zaawansowany przewodnik

Spis treści

Logowanie przy użyciu formularza w aplikacjach JavaServer Faces .....................................318 Użycie j_security_check w formularzach JavaServer Faces ............................................318 Użycie zarządzanego ziarna do uwierzytelniania w aplikacjach JavaServer Faces ......319 Uwierzytelnianie za pomocą JDBC Realm ...............................................................................321 T Konfiguracja dziedziny uwierzytelniania JDBC ...............................................................321 Zabezpieczanie zasobów HTTP .................................................................................................325 Zabezpieczenie klientów aplikacji ..............................................................................................328 Użycie modułów logowania .................................................................................................328 Użycie logowania programowego .......................................................................................329 Zabezpieczanie aplikacji typu EIS ..............................................................................................329 Logowanie zarządzane przez kontener ..............................................................................330 Logowanie zarządzane przez komponent ..........................................................................330 Konfiguracja bezpieczeństwa adapterów zasobów ...........................................................331 T Odwzorowanie zarządcy aplikacji na zarządcę EIS ..........................................................332 Konfiguracja bezpieczeństwa przy użyciu deskryptorów wdrożenia ...................................333 Określanie w deskryptorze wdrożenia zasad bezpieczeństwa dla prostego uwierzytelniania ...........................................................................................333 Wskazanie w deskryptorze wdrożenia niedomyślnego odwzorowania zarządzającego na rolę ........................................................................................................334 Dalsze informacje na temat bezpieczeństwa ............................................................................334

Część VIII. Technologie wspomagające Javę EE ..........................................................335 Rozdział 20. Zagadnienia technologii JMS ......................................................................337 Wprowadzenie do JMS API ........................................................................................................337 Czym jest przekazywanie komunikatów? ..........................................................................337 Czym jest JMS API? ..............................................................................................................338 Kiedy mogę użyć JMS API? ..................................................................................................338 W jaki sposób JMS API współpracuje z platformą Javy EE? ..........................................339 Podstawowe koncepcje JMS API ................................................................................................340 Architektura JMS API ...........................................................................................................340 Dziedziny komunikatów ......................................................................................................341 Konsumpcja komunikatów ..................................................................................................343 Model programistyczny JMS API ..............................................................................................344 Obiekty administracyjne JMS ..............................................................................................344 Połączenia JMS .......................................................................................................................347 Sesje JMS .................................................................................................................................347 Producenty komunikatów JMS ...........................................................................................348 Konsumenty komunikatów JMS .........................................................................................349 Komunikaty JMS ...................................................................................................................351 Przeglądarki kolejek JMS ......................................................................................................353 Obsługa wyjątków JMS .........................................................................................................353 Tworzenie wydajnych aplikacji JMS ..........................................................................................354 Użycie prostych mechanizmów trwałości .........................................................................355 Użycie zaawansowanych mechanizmów niezawodności ................................................359

Java EE 6. Zaawansowany przewodnik

11

Spis treści

Wykorzystanie JMS API w aplikacjach Javy EE .......................................................................363 Użycie adnotacji @Resource w komponentach webowych i EJB ...................................364 Użycie ziaren sesyjnych do produkcji i synchronicznego otrzymywania komunikatów ...........................................................364 Wykorzystanie ziaren sterowanych komunikatami do asynchronicznego otrzymywania komunikatów ......................................................365 Zarządzanie transakcjami rozproszonymi .........................................................................368 Korzystanie z JMS API w klientach aplikacji i komponentach webowych ...................370 Dodatkowe informacje na temat JMS .......................................................................................370

Rozdział 21. Przykłady wykorzystania JMS .....................................................................371 Tworzenie prostych aplikacji JMS ..............................................................................................371 Prosty przykład synchronicznego otrzymywania komunikatów ...................................372 Prosty przykład asynchronicznego otrzymywania komunikatów .................................381 Prosty przykład przeglądania komunikatów w kolejce ....................................................386 Uruchomienie klientów JMS na wielu systemach ............................................................391 Usunięcie wdrożenia i wyczyszczenie systemu po przykładach JMS ............................397 Tworzenie rozbudowanych aplikacji JMS ................................................................................397 Przykład potwierdzania komunikatu .................................................................................397 Przykład trwałej subskrypcji ................................................................................................400 Przykład transakcji lokalnej .................................................................................................402 Aplikacja stosująca JMS API w połączeniu z ziarnem sesyjnym ...........................................407 Tworzenie komponentów aplikacji dla przykładu clientsessionmdb ............................407 Tworzenie zasobów dla przykładu clientsessionmdb ......................................................410 Uruchomienie przykładu clientsessionmdb ......................................................................410 Aplikacja stosująca JMS API w połączeniu z encją .................................................................411 Opis przykładowej aplikacji clientmdbentity ....................................................................412 Tworzenie komponentów przykładowej aplikacji clientmdbentity ...............................413 Tworzenie zasobów dla przykładu clientmdbentity .........................................................415 Uruchomienie przykładu clientmdbentity ........................................................................416 Przykład aplikacji konsumującej komunikaty z zewnętrznego serwera ..............................419 Opis modułów przykładu consumeremote .......................................................................419 Tworzenie komponentów modułu dla przykładu consumeremote ..............................420 Tworzenie zasobów dla przykładu consumeremote ........................................................421 Użycie dwóch serwerów aplikacji dla przykładu consumeremote .................................421 Uruchomienie przykładu consumeremote ........................................................................421 Przykład aplikacji wdrażającej ziarno sterowane komunikatami na dwóch serwerach ....425 Opis modułów przykładu sendremote ...............................................................................425 Tworzenie komponentów modułów dla przykładu sendremote ...................................426 Tworzenie zasobów dla przykładu sendremote ................................................................428 T Uruchomienie wdrożenia na zdalnym serwerze ...............................................................428 T Użycie dwóch serwerów aplikacji dla przykładu sendremote ........................................429 Uruchomienie przykładu sendremote ................................................................................429 T Uruchomienie przykładu sendremote w środowisku NetBeans IDE ............................430 T Uruchomienie przykładu sendremote przy użyciu narzędzia Ant ................................432 T Wyłączenie wdrażania na zdalnym systemie ....................................................................434

12

Java EE 6. Zaawansowany przewodnik

Spis treści

Rozdział 22. Mechanizm Bean Validation — tematy zaawansowane ...........................435 Tworzenie własnych ograniczeń ................................................................................................435 Użycie wbudowanych ograniczeń do tworzenia własnych ograniczeń .........................435 Dostosowywanie komunikatów walidatorów ..........................................................................436 Paczka zasobów ValidationMessages .................................................................................436 Grupowanie ograniczeń ..............................................................................................................437 Dostosowanie kolejności walidacji grup ............................................................................437

Rozdział 23. Wykorzystanie interceptorów Javy EE .......................................................439 Wprowadzenie do interceptorów ..............................................................................................439 Klasy interceptorowe ............................................................................................................440 Cykl życia interceptorów ......................................................................................................440 Interceptory i CDI .................................................................................................................441 Użycie interceptorów ...................................................................................................................441 Wywołania metod przechwytujących ................................................................................441 Przechwytywanie zdarzeń wywołań zwrotnych cyklu życia ...........................................443 Przechwytywanie zdarzeń upłynięcia czasu ......................................................................444 Przykładowa aplikacja interceptor .............................................................................................445 Uruchomienie przykładu interceptor .................................................................................446

Rozdział 24. Przykład z adapterem zasobów ..................................................................449 Adapter zasobów ..........................................................................................................................449 Ziarno sterowane komunikatami ...............................................................................................450 Aplikacja webowa .........................................................................................................................450 Uruchomienie przykładu mailconnector ..................................................................................450 T Przygotowania przed wdrożeniem przykładu mailconnector ........................................450 T Zbudowanie, spakowanie i wdrożenie przykładu mailconnector w środowisku NetBeans IDE ...............................................................................................451 T Zbudowanie, spakowanie i wdrożenie przykładu mailconnector przy użyciu narzędzia Ant ....................................................................................................452 T Uruchomienie przykładu mailconnector ...........................................................................452

Część IX. Przykładowe scenariusze użycia .................................................................453 Rozdział 25. Przykładowy scenariusz użycia — księgarnia Duke’a ..............................455 Projekt i architektura księgarni Duke’a .....................................................................................455 Interfejs aplikacji ..........................................................................................................................456 Encja Book korzystająca z Java Persistence API ...............................................................456 Komponenty EJB wykorzystywane w przykładzie ...........................................................457 Strony faceletów i zarządzane ziarna używane w przykładowej aplikacji .....................457 Własne komponenty i inne własne obiekty wykorzystywane w księgarni Duke’a ......459 Pliki właściwości używane przez aplikację ........................................................................459 Deskryptory wdrożeń użyte w przykładowej aplikacji ....................................................460

Java EE 6. Zaawansowany przewodnik

13

Spis treści

Uruchomienie aplikacji księgarnia Duke’a ...............................................................................461 T Budowanie i wdrażanie aplikacji w środowisku NetBeans IDE .....................................461 T Budowanie i wdrażanie aplikacji przy użyciu narzędzia Ant ..........................................461 T Uruchomienie aplikacji ........................................................................................................462

Rozdział 26. Przykładowy scenariusz użycia — ćwiczenia Duke’a ...............................463 Projekt i architektura aplikacji ...................................................................................................463 Interfejs główny ............................................................................................................................465 Encje Java Persistence API wykorzystywane przez interfejs główny .............................465 Komponenty EJB wykorzystywane w interfejsie głównym .............................................466 Pliki faceletów wykorzystywane w interfejsie głównym ..................................................466 Klasy pomocnicze używane w interfejsie głównym .........................................................467 Pliki właściwości ....................................................................................................................468 Deskryptory wdrożenia wykorzystywane przez aplikację ...............................................469 Interfejs administracyjny .............................................................................................................469 Komponenty EJB wykorzystywane przez interfejs administracyjny .............................469 Pliki faceletów wykorzystywane przez interfejs administracyjny ...................................470 Uruchomienie przykładowej aplikacji ćwiczenia Duke’a .......................................................470 Konfiguracja serwera GlassFish ...........................................................................................470 Uruchomienie aplikacji ćwiczenia Duke’a .........................................................................471

Rozdział 27. Przykładowy scenariusz użycia — las Duke’a ...........................................475 Projekt i architektura aplikacji las Duke’a ................................................................................476 Projekt events .........................................................................................................................478 Projekt entities .......................................................................................................................479 Projekt dukes-payment .........................................................................................................481 Projekt dukes-resources ........................................................................................................481 Projekt sklepu Duke’a ...........................................................................................................481 Projekt wysyłka Duke’a .........................................................................................................486 Budowanie i wdrażanie aplikacji las Duke’a .............................................................................488 Zadanie przygotowawcze .....................................................................................................489 T Zbudowanie i wdrożenie aplikacji las Duke’a w środowisku NetBeans IDE ...............489 T Zbudowanie i wdrożenie aplikacji las Duke’a przy użyciu narzędzia Ant ....................490 Uruchamianie aplikacji las Duke’a ............................................................................................491 T Rejestracja jako klient sklepu ...............................................................................................491 T Zakup produktów ..................................................................................................................491 T Zatwierdzenie wysyłki produktu .........................................................................................492 T Utworzenie nowego produktu .............................................................................................492

Skorowidz ........................................................................................................................495

14

Java EE 6. Zaawansowany przewodnik

Wstęp

Książka ta to drugi tom podręcznika do nauki tworzenia aplikacji na platformy Java, Enterprise Edition 6 (Java EE 6) przy użyciu serwera GlassFish Server Open Source Edition. Oracle GlassFish Server, zgodny z Java EE serwer aplikacji, bazuje na wydaniu GlassFish Server Open Source Edition, która jest wiodącą platformą do tworzenia i wdrażania następnej generacji aplikacji i usług, a przy tym jest prowadzona przez społeczność i zapewnia otwarty dostęp do kodu źródłowego. Wydanie GlassFish Server Open Source Edition, udostępnione przez społeczność skupioną wokół projektu GlassFish na witrynie http://glassfish.java.net/, jest pierwszą implementacją w pełni zgodną ze specyfikacją platformy Java EE 6. Ten lekki, elastyczny serwer aplikacji wydany w stylu open source umożliwia firmom nie tylko wykorzystanie nowych funkcjonalności wprowadzonych wraz ze specyfikacją Java EE 6, ale również lepsze użycie istniejącej funkcjonalności i szybsze przeprowadzanie cykli programowania i wdrażania. Od tego momentu zarówno wersja komercyjna Oracle GlassFish Server, jak i wersja open source GlassFish Server Open Source Edition będzie po prostu nazywana GlassFish Server.

Zanim przeczytasz tę książkę Zanim rozpoczniesz lekturę książki, powinieneś zaznajomić się z tomem pierwszym wydanym pod tytułem Java EE 6. Przewodnik. Wydanie IV. W obu tomach zakładamy, iż posiadasz umiejętność posługiwania się językiem Java. Jeśli Twoja wiedza nie jest wystarczająca, skorzystaj z ćwiczeń i podręczników dostępnych pod adresem http://docs.oracle.com/javase/.

Dokumentacja powiązana z książką Dokumentacja serwera GlassFish omawia planowanie wdrożeń i instalację systemu. Aby uzyskać dostęp do dokumentacji dotyczącej GlassFish Server Open Source Edition, odwiedź witrynę http://glassfish.java.net/docs/. Adres URL dokumentacji wersji komercyjnej, czyli Oracle GlassFish Server, to http://docs. oracle.com/cd/E26576_01/index.htm.

Konwencje typograficzne

Referencyjna dokumentacja wygenerowana za pomocą narzędzia Javadoc dla pakietów udostępnianych wraz z serwerem GlassFish jest dostępna pod następującymi adresami URL. „ Specyfikacja API dla wersji 6. Java EE znajduje się pod adresem http://docs. oracle.com/javaee/6/api/. „ Specyfikacja API GlassFish Server, włącznie z pakietami platformy Java EE 6 oraz innymi pakietami specyficznymi dla produktu GlassFish Server, znajduje się pod adresem http://glassfish.java.net/nonav/docs/v3/api/. Przydatna może okazać się również specyfikacja Java EE dostępna pod adresem http://www.oracle.com/technetwork/java/javaee/tech/index.html. Więcej informacji na temat tworzenia aplikacji typu enterprise w zintegrowanym środowisku programistycznym NetBeans znajduje się pod adresem http://www. netbeans.org/kb/. Dodatkowe informacje na temat użycia bazy danych Java DB wraz z serwerem GlassFish są dostępne pod adresem http://www.oracle.com/technetwork/java/ javadb/overview/index.html. Projekt GlassFish Samples to zbiór przykładowych aplikacji, które w szerokim zakresie prezentują dostępne technologie Java EE. Przykłady znajdują się w Java EE Software Development Kit (SDK), ale można je pobrać również z poziomu witryny projektu GlassFish Samples dostępnej pod adresem http://glassfishsamples.java.net/.

Konwencje typograficzne W tabeli W.1 zawarto krótki opis konwencji typograficznych stosowanych w książce.

Domyślnie ścieżki i nazwy plików W tabeli W.2 zamieszczono listę domyślnych ścieżek i nazw plików wykorzystywanych w książce.

Inne witryny z dodatkowymi informacjami W książce znajdują się odniesienia do niezależnych witryn wraz z pełnymi adresami URL. UWAGA Firma Oracle nie odpowiada za dostępność materiałów wskazanych

na niezależnych witrynach. Oracle nie poleca i nie jest odpowiedzialna za treść, reklamy, produkty i inne materiały dostępne na tych witrynach. Oracle nie jest odpowiedzialna za ewentualne szkody lub straty spowodowane przez korzystanie z zamieszczonych tam informacji, a także przez korzystanie z usług oferowanych przez niezależne witryny, których adresy zostały umieszczone w książce.

16

Java EE 6. Zaawansowany przewodnik

Inne witryny z dodatkowymi informacjami

Tabela W.1. Konwencje typograficzne Krój czcionki

Znaczenie

Przykład

AaBbCc123

Wynik wykonanych poleceń widoczny na ekranie, nazwy metod i fragmenty kodu źródłowego.

nazwa% Masz wiadomość. if (test) { mojaMetoda(argument);

AaBbCc123

Kod, który trzeba samodzielnie wpisać w konsoli.

nazwa% su Hasło:

AaBbCc123

Nazwy folderów i plików, tytuły książek, polecenia interfejsu użytkownika. Fragmenty do zastąpienia.

Zmodyfikuj plik .login.

Nowe terminy i fragmenty szczególnie ważne.

Pamięć podręczna to przechowywana lokalnie kopia.

Wybierz z menu polecenie Plik/Zamknij. Przeczytaj rozdział 6. Podręcznika użytkownika. Usuń plik poleceniem rm

AaBbCc123

plik.

Nie zapisuj pliku. AaBbCc123

Fragmenty ścieżki do zastąpienia.

ścieżka/plik.txt

Tabela W.2. Domyślne ścieżki i nazwy plików Nazwa zastępcza

Opis

Wartość domyślna

as-install

Wskazuje główny folder instalacji serwera GlassFish lub SDK, którego ten serwer jest częścią.

Instalacje w systemach operacyjnych Solaris, Linux i Mac OS: folder-domowyużytkownika/glassfish3/ glassfish Instalacje w systemie Windows: NapędSystemowy:\glassfish3\ glassfish

as-install-parent

Wskazuje folder nadrzędny względem folderu serwera GlassFish.

Instalacje w systemach operacyjnych Solaris, Linux i Mac OS: folder-domowy-użytkownika/ glassfish3 Instalacje w systemie Windows: NapędSystemowy:\glassfish3

tut-install

Wstęp

Wskazuje podstawowy folder instalacji dla ćwiczeń Java EE po zainstalowaniu serwera GlassFish lub zainstalowaniu SDK i uruchomieniu narzędzia aktualizacji.

as-install/docs/javaee-tutorial

17

Podziękowania

Tabela W.2. Domyślne ścieżki i nazwy plików — ciąg dalszy Nazwa zastępcza

Opis

Wartość domyślna

domain-root-dir

Wskazuje folder, w którym domyślnie tworzone są domeny.

as-install/domains/

domain-dir

Wskazuje folder przechowujący konfigurację folderu.

domain-root-dir/nazwadomeny

Podziękowania Zespół tworzący przewodnik Java EE chciałby podziękować osobom odpowiedzialnym za prowadzenie prac nad specyfikacją Java EE: Robertowi Chinniciemu, Billowi Shannonowi, Kennethowi Saksowi, Lindzie DeMichiel, Edowi Burnsowi, Rogerowi Kitainowi, Ronowi Monzilli, Binodowi PG, Sivakumarowi Thyagarajanowi, Kin-Manowi Chungowi, Jitendrajowi Kotamraju, Marcowi Hadleyowi, Paulowi Sandozo, Gavinowi Kingowi, Emmanuelowi Bernardowi, Rodowi Johnsonowi, Bobowi Lee i Rajiv Mordani. Dziękujemy również Alejandrowi Murilli za oryginalną wersję przykładu dotyczącego konektora. Dziękujemy zespołowi Java EE 6 SDK, a w szczególności Carli Carlson, Snjezananowi Sevo-Zenzerovicowi, Adamowi Leftikowi i Johnowi Clinganowi. Rozdziały dotyczące technologii JavaServer Faces powstały z wykorzystaniem sugestii Manfreda Riema i kierowników specyfikacji. Rozdziały dotyczące technologii EJB, Java Persistence API i Criteria API powstały przy zdecydowanym udziale zespołów EJB i Persistence, a szczególnie pomogli Marina Vatkina i Metesh Meswan. Dziękujemy Sivakumarowi Thyagarajanowi za ocenę rozdziałów CDI, a Timowi Quinnowi za pomoc z kontenerem aplikacji klienckiej. Dziękujemy również zespołom programistycznym i dokumentacyjnym NetBeans, szczególnie Petrowi Jiriczce, Johnowi Jullionowi-Ceccarelliemu i Troyowi Giuniperowi za pomoc w umożliwieniu łatwej obsługi przykładów przez NetBeans IDE. Chang Feng, Alejandro Murillo i Scott Fordin pomogli umiędzynarodowić studium przypadku Duke. Dziękujemy naszemu menedżerowi — Alanowi Sommererowi — za jego wsparcie i stały wpływ na prace nad książką. Chcielibyśmy również podziękować Jordanowi Douglasowi i Dawnowi Tylerowi za wykonanie i aktualizację ilustracji. Sheila Cepero na wiele sposobów pomogła zapewnić płynność prac redakcyjnych. Steve Cogorno zapewnił nieocenioną pomoc przy wykorzystywanych narzędziach. Na końcu chcielibyśmy wyrazić ogromną wdzięczność Gregowi Doenchowi, Johnowi Fullerowi, Elizabeth Ryan, Steve’owi Freedkinowi i zespołowi produkcyjnemu z Addison-Wesley za umożliwienie publikacji tej pozycji.

18

Java EE 6. Zaawansowany przewodnik

CZĘŚĆ I

Wprowadzenie Część I stanowi wprowadzenie do platformy, samouczka i zawartych w nim przykładów. Składa się z następujących rozdziałów: „ „

Rozdział 1., „Przegląd technologii”, Rozdział 2., „Używanie przykładowych aplikacji z samouczka”.

‹

‹

‹

1

ROZDZIAŁ 1

Przegląd technologii

Aktualnie programiści coraz częściej podejmują się tworzenia rozproszonych, transakcyjnych i przenośnych aplikacji, które wykorzystują szybkość, zabezpieczenia i niezawodność technologii po stronie serwera. Aplikacje typu enterprise dostarczają przedsiębiorstwom logikę biznesową. Są centralnie zarządzane i niejednokrotnie podejmują interakcję z innym oprogramowaniem typu enterprise. W świecie technologii informacyjnej aplikacje typu enterprise muszą być projektowane, budowane oraz wykonywane taniej, szybciej i przy mniejszym nakładzie środków. Tworzenie aplikacji typu enterprise w technologii Java nigdy nie było tak proste i szybkie jak z pomocą Java Platform, Enterprise Edition (Java EE, w skrócie JEE). Twórcy platformy Java EE mają na celu utworzenie rozbudowanego zestawu API i dostarczenie go programistom. Zestaw powinien pomóc w opracowywaniu oprogramowania, skracając czas wytwarzania, redukując złożoność aplikacji oraz poprawiając jej wydajność. Platforma JEE, tak jak wszystkie technologie Javy, rozwijana jest przez Java Community Process (JCP). Grupy ekspertów złożone z osób zainteresowanych tworzą dokumenty Java Specification Request (JSR), które definiują różne technologie JEE. Udział społeczności Java Community w programie JCP pomaga w zapewnieniu stabilności i międzyplatformowej kompatybilności standardowi technologii Java. Platforma Java EE wykorzystuje uproszczony model programowania. Deskryptory wdrożenia w języku XML są opcjonalne. Zamiast nich programista może po prostu przekazać informację w postaci adnotacji bezpośrednio w kodzie źródłowym Javy, a serwer Javy EE skonfiguruje komponent podczas jego wdrożenia lub działania. Adnotacje te używane są najczęściej do zagnieżdżenia w kodzie programu danych, które w innym przypadku znalazłyby się w deskryptorze wdrożenia. Za pomocą adnotacji można specyfikować konfigurację elementu programu bezpośrednio przy jego wystąpieniu w kodzie źródłowym. Platforma Java EE pozwala na zastosowanie wstrzykiwania zależności do wszystkich zasobów, jakich dany komponent potrzebuje, a to efektywnie usuwa z kodu źródłowego aplikacji fragmenty odpowiedzialne za tworzenie oraz wyszukiwanie zasobów. Wstrzykiwanie zależności może być użyte w kontenerze EJB, kontenerze webowym (ang. web container) oraz klientach aplikacji. Pozwala ono kontenerowi JEE na automatyczne wstrzykiwanie referencji do innych wymaganych komponentów lub zasobów przy użyciu adnotacji.

Najważniejsze cechy platformy Java EE 6

W tym samouczku opisujemy, z użyciem przykładów, elementy platformy Java EE wspomagające wytwarzanie aplikacji typu enterprise. Bez względu na to, czy jesteś nowicjuszem, czy doświadczonym programistą aplikacji biznesowych, podane tutaj przykłady i towarzyszący im tekst powinny być cennym i łatwo dostępnym źródłem wiedzy przydatnym do tworzenia własnych rozwiązań. Jeśli budowanie aplikacji typu enterprise w oparciu o Javę EE jest dla Ciebie nowością, rozdział ten powinien stanowić dobry punkt startowy. Zapoznasz się tutaj z podstawami tworzenia aplikacji, architekturą oraz API Javy EE, poznasz ważne terminy i pojęcia oraz dowiesz się, w jaki sposób podejść do programowania, budowania i wdrażania aplikacji opartych na Javie EE. W rozdziale: „ „ „ „ „ „ „ „ „ „ „

Najważniejsze cechy platformy Java EE, Model aplikacji Javy EE, Rozproszone, wielowarstwowe aplikacje, Kontenery Javy EE, Obsługa usług sieciowych, Budowanie i wdrażanie aplikacji Javy EE, Pakowanie aplikacji, Role w procesie wytwarzania aplikacji, API Javy EE 6, API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7, Narzędzia serwera GlassFish.

Najważniejsze cechy platformy Java EE 6 Głównym celem platformy Java EE 6 jest uproszczenie procesu wytwarzania oprogramowania poprzez dostarczenie wspólnych podstaw dla różnorodnych komponentów platformy Java EE. Zmniejszenie ilości konfiguracji w języku XML na rzecz adnotacji, nacisk na wykorzystanie obiektów POJO (ang. Plain Old Java Object) oraz uproszczone pakowanie spowodowały, że twórcy oprogramowania mogą znacznie zwiększyć swoją produktywność. Niżej przedstawiamy kilka nowych elementów platformy Java EE 6. „

„

22

Profile: konfiguracje platformy Java EE dedykowane wybranym typom aplikacji. Platforma JEE 6 wprowadza lekki profil webowy (ang. Web Profile) ukierunkowany na aplikacje internetowe najnowszej generacji i pełen profil (ang. Full Profile) zawierający wszystkie technologie wchodzące w skład Javy EE; w ten sposób w aplikacjach typu enterprise znajduje się pełna funkcjonalność platformy Java EE 6. Nowe technologie, a szczególnie: „ API Javy dla usług sieciowych typu REST (JAX-RS), „ Managed Beans,

Java EE 6. Zaawansowany przewodnik

Model aplikacji Javy EE

Contexts and Dependency Injection for the Java EE Platform (JSR 299), potocznie nazywana CDI, „ Dependency Injection for Java (JSR 330), „ Bean Validation (JSR 303), „ Java Authentication Service Provider Interface for Containers (JASPIC). Nowe funkcjonalności komponentów EJB — Enterprise JavaBeans (szczegóły w tym rozdziale, w punkcie „Technologia Enterprise JavaBeans”). Nowe funkcjonalności serwletów (szczegóły w tym rozdziale, w punkcie „Technologia Java Servlet”. Nowe funkcjonalności komponentów JavaServer Faces (szczegóły w tym rozdziale, w punkcie „Technologia JavaServer Faces”. „

„

„

„

Model aplikacji Javy EE Podstawą modelu aplikacji Javy EE są język programowania Java oraz wirtualna maszyna Javy, wpływające na przenośność, bezpieczeństwo oraz produktywność programistów. Java EE została zaprojektowana do obsługi aplikacji implementujących usługi enterprise dla klientów, pracowników, dostawców, partnerów oraz innych podmiotów powiązanych z przedsiębiorstwem. Aplikacje takie są z natury złożone, potencjalnie korzystają z różnorodnych źródeł danych i dystrybuują programy do różnorakich klientów. W celu zapewnienia większych możliwości kontroli tych aplikacji i zarządzania nimi funkcje biznesowe wspierające różnych wspomnianych wyżej użytkowników działają w warstwie logiki (ang. middle tier). Warstwa logiki to środowisko ściśle kontrolowane przez dział technologii informacyjnej danego przedsiębiorstwa. Jest ona zazwyczaj uruchamiana na dedykowanym serwerze sprzętowym i ma dostęp do wszystkich usług aplikacyjnych w przedsiębiorstwie. Model aplikacji Javy EE definiuje architekturę implementowanych usług jako wielowarstwową aplikację, dbającą o skalowalność, dostępność oraz zarządzanie, które to opcje są wymagane przez aplikacje poziomu enterprise. Model ten dzieli pracę, jaką wykonywać ma wielowarstwowa usługa, na dwie części: „ „

logikę biznesową i prezentacji, implementowaną przez programistę, standardowe usługi systemu dostarczane przez platformę Java EE.

Twórcy oprogramowania mogą polegać na platformie, która zawiera rozwiązania trudnych problemów poziomu systemowego, na jakie napotkać można, rozwijając wielowarstwową usługę.

Rozproszone, wielowarstwowe aplikacje W platformie JEE do aplikacji typu enterprise zastosowano model rozproszonej, wielowarstwowej aplikacji. Logika aplikacji podzielona jest na komponenty, zgodnie z ich funkcją. Komponenty aplikacji, które składają się na aplikację JEE,

Rozdział 1 y Przegląd technologii

23

Rozproszone, wielowarstwowe aplikacje

instalowane są na różnych maszynach, zależnie od tego, do której warstwy wielowarstwowego środowiska Javy EE należą. Na rysunku 1.1 przedstawiamy podział dwóch wielowarstwowych aplikacji Javy EE na warstwy opisane poniżej. Elementy aplikacji JEE ukazane na rysunku omówione są w tym rozdziale, w punkcie „Komponenty Javy EE”. Oto one: „ „ „ „

warstwa klienta (ang. client-tier), działająca na maszynie klienta, warstwa webowa (ang. web-tier), działająca na serwerze JEE, warstwa logiki biznesowej (ang. business-tier), działająca na serwerze JEE, warstwa danych (ang. Enterprise Information System, w skrócie EIS), działająca na serwerze EIS.

Rysunek 1.1. Aplikacje wielowarstwowe

Pomimo iż aplikacja JEE składać się może, jak na rysunku 1.1, z trzech lub czterech warstw, wielowarstwowe aplikacje JEE są zazwyczaj traktowane jak trójwarstwowe, ponieważ rozproszone są pomiędzy trzema lokalizacjami, takimi jak maszyny klientów, maszyna z serwerem Javy EE oraz maszyny z bazami danych lub starszym oprogramowaniem (jest to tak zwany back-end). Trójwarstwowe aplikacje działające w opisany powyżej sposób są rozszerzeniem standardowego, dwuwarstwowego modelu klient-serwer, bo umiejscawiają wielowątkowy serwer aplikacji pomiędzy aplikacją kliencką a warstwą przechowywania danych.

24

Java EE 6. Zaawansowany przewodnik

Rozproszone, wielowarstwowe aplikacje

Bezpieczeństwo Wiele modeli aplikacji enterprise wymaga specyficznych dla danej platformy środków bezpieczeństwa w każdej aplikacji, jednak środowisko zabezpieczeń Javy EE pozwala na definiowanie reguł bezpieczeństwa w czasie wdrażania. Platforma Javy EE sprawia, że aplikacja jest przenośna pomiędzy różnorodnymi implementacjami zabezpieczeń poprzez odgrodzenie twórców aplikacji od złożoności implementacji elementów zabezpieczeń. Platforma JEE została wyposażona w standardowe, deklaratywne reguły kontroli dostępu definiowane przez programistę, a interpretowane podczas wdrożenia aplikacji na serwer. Twórcy w swoich aplikacjach nie muszą implementować standardowych mechanizmów logowania, które również dostarczane są przez platformę JEE. Ta sama aplikacja będzie mogła działać w oparciu o różne środowiska zabezpieczeń bez zmian w kodzie źródłowym.

Komponenty Javy EE Aplikacje JEE zbudowane są z komponentów. Komponent Javy EE jest niezależną, funkcjonalną jednostką oprogramowania wbudowaną w aplikację JEE (wraz z powiązanymi klasami oraz plikami) i komunikującą się z innymi komponentami. W specyfikacji JEE zdefiniowano następujące komponenty Javy EE: „

„

„

aplikacje klienckie i aplety, które są komponentami uruchamianymi po stronie klienta, komponenty technologii Java Servlet, JavaServer Faces oraz JavaServer Pages (JSP), które są komponentami webowymi działającymi na serwerze, komponenty Enterprise JavaBeans (EJB, zwane także ziarnami EJB) będące komponentami biznesowymi działającymi na serwerze.

Komponenty Javy EE pisane są w języku programowania Java i kompilowane w taki sam sposób jak każdy inny program w tym języku. Różnica pomiędzy komponentami JEE i „standardowymi” klasami języka Java polega na tym, że komponenty JEE składane są w aplikację Javy EE i wdrażane w środowisku produkcyjnym, gdzie działają na serwerze Javy EE i są przez ten serwer zarządzane.

Klienty Javy EE Klientem Javy EE jest zazwyczaj klient przeglądarkowy lub aplikacja kliencka.

Klient przeglądarkowy Klient przeglądarkowy składa się z dwóch części:

Rozdział 1 y Przegląd technologii

25

Rozproszone, wielowarstwowe aplikacje

„

„

dynamicznych stron internetowych zawierających różne typy języków znaczników (HTML, XML i tym podobne), które są generowane przez komponenty webowe działające w warstwie webowej, przeglądarki internetowej, która wyświetla strony pobrane z serwera.

Klient przeglądarkowy nazywany jest czasem cienkim klientem. Cienki klient zazwyczaj nie wykonuje zapytań do bazy danych, złożonych operacji biznesowych ani nie łączy się z aplikacjami starszego typu. Kiedy używa się cienkiego klienta, wszystkie operacje „wagi ciężkiej” delegowane są do komponentów EJB działających na serwerze Javy EE, gdzie mogą korzystać z zabezpieczeń, szybkości, dostępnych usług oraz niezawodności technologii JEE umieszczonych po stronie serwera.

Aplikacje klienckie Aplikacje klienckie działają na maszynie klienta i umożliwiają użytkownikom wykonywanie zadań, które wymagają interfejsu bogatszego niż oferowany przez języki znaczników. Aplikacja kliencka zazwyczaj wyposażona jest w graficzny interfejs użytkownika (GUI) tworzony z wykorzystaniem API Swing lub AWT (ang. Abstract Window Toolkit), istnieje jednak możliwość opracowania aplikacji działających z wiersza poleceń. Aplikacje klienckie mają bezpośredni dostęp do komponentów EJB działających w warstwie logiki biznesowej. Jeśli jednak specyfikacja aplikacji tego wymaga, może ona zestawić połączenie HTTP, by rozpocząć komunikację z serwletem działającym w warstwie webowej. Aplikacje klienckie pisane w języku innym niż Java mogą komunikować się z serwerami Javy EE, co pozwala platformie JEE na współpracę z systemami zastanymi, innymi klientami oraz językami innymi niż Java.

Aplety Strona internetowa odebrana z warstwy webowej może zawierać dołączony aplet. Napisany w języku Java aplet jest niewielką aplikacją kliencką wykonywaną na wirtualnej maszynie Javy zainstalowanej w przeglądarce. Jednak istnieje duże prawdopodobieństwo, że systemy klienckie, na których uruchomiony ma zostać aplet, do jego wykonania potrzebować będą w przeglądarce wtyczki Javy oraz pliku definiującego politykę bezpieczeństwa. Komponenty webowe są preferowanym API do tworzenia programu będącego klientem internetowym, ponieważ od systemu klienckiego nie wymagają instalowania wtyczek bądź określania polityki bezpieczeństwa. Dodatkowo komponenty webowe pozwalają na bardziej przejrzystą i modularną konstrukcję aplikacji, ponieważ ułatwiają oddzielenie programowania aplikacji od projektowania stron internetowych. Pracownicy zaangażowani w projektowanie stron internetowych nie muszą zatem rozumieć składni języka Java, aby wykonywać swoją pracę.

26

Java EE 6. Zaawansowany przewodnik

Rozproszone, wielowarstwowe aplikacje

Architektura komponentów JavaBeans Warstwy serwera oraz klienta także mogą zawierać komponenty oparte o architekturę komponentów JavaBeans (czyli tak zwane komponenty JavaBeans) w celu zarządzania przepływem danych pomiędzy: „

„

aplikacją kliencką bądź apletem a komponentami działającymi na serwerze Javy EE, komponentami serwerowymi a bazą danych.

Komponenty JavaBeans nie są uznawane przez specyfikację Javy EE za komponenty JEE. Komponenty JavaBeans zawierają pola oraz metody get i set pozwalające na dostęp do tych pól. Są one zazwyczaj używane w prostych projektach i implementacjach, powinny jednak być zgodne z konwencjami nazewnictwa oraz projektowania opisanymi w architekturze komponentów JavaBeans.

Komunikacja z serwerem Javy EE Na rysunku 1.2 przedstawiamy różne elementy, które mogą składać się na warstwę klienta. Klient komunikuje się z warstwą logiki biznesowej działającą na serwerze Javy EE bezpośrednio lub poprzez przejście przez strony internetowe lub serwlety działające w warstwie webowej, gdy jest klientem przeglądarkowym.

Rysunek 1.2. Komunikacja z serwerem

Komponenty webowe Komponenty webowe Javy EE są albo serwletami, albo stronami internetowymi utworzonymi przy użyciu technologii JavaServer Faces i (lub) technologii JSP (strony JSP). Serwlety są klasami języka Java, które dynamicznie przetwarzają żądania i konstruują odpowiedzi. Strony JSP to dokumenty tekstowe wykonywane

Rozdział 1 y Przegląd technologii

27

Rozproszone, wielowarstwowe aplikacje

jako serwlety, dające jednak możliwość bardziej naturalnego tworzenia statycznej treści. Technologia JavaServer Faces oparta jest na technologii serwletów oraz JSP i dostarcza framework zawierający komponenty interfejsu użytkownika do tworzenia aplikacji internetowych. Statyczne strony w języku HTML oraz aplety są pakowane razem z komponentami webowymi w czasie budowania aplikacji, nie są jednak traktowane przez specyfikację Javy EE jak komponenty webowe. Klasy użytkowe po stronie serwera mogą również zostać dołączone do tej paczki, jednak, tak samo jak strony HTML, nie są traktowane jak komponenty webowe. Jak pokazano na rysunku 1.3, warstwa webowa, tak jak warstwa klienta, może zawierać komponenty JavaBeans służące do zarządzania danymi wprowadzanymi przez użytkownika oraz do wysyłania tych danych do przetworzenia w komponentach EJB działających w warstwie logiki biznesowej.

Rysunek 1.3. Warstwa webowa i aplikacje JEE

Komponenty biznesowe Kod logiki biznesowej, będący logiką rozwiązującą problemy bądź zaspokajającą potrzeby danej dziedziny biznesu, takiej jak bankowość, sprzedaż detaliczna lub finanse, wykonywany jest przez ziarna EJB działające w warstwach webowej bądź logiki biznesowej. Na rysunku 1.4 można zobaczyć komponent EJB, który odbiera dane z programów klienckich, przetwarza je, jeśli trzeba, a następnie wysyła do warstwy danych w celu składowania. Ziarno EJB otrzymuje także dane z warstwy EIS, przetwarza je, jeśli to konieczne, i przesyła z powrotem do programu klienckiego.

28

Java EE 6. Zaawansowany przewodnik

Kontenery Javy EE

Rysunek 1.4. Warstwy biznesowa i EIS

Warstwa danych Warstwa danych obsługuje oprogramowanie EIS i zawiera infrastrukturę systemów przedsiębiorstwa, takich jak zarządzanie zasobami przedsiębiorstwa (ang. Enterprise Resource Planning, w skrócie ERP), przetwarzanie transakcji na komputerach dużej mocy, systemy baz danych oraz inne istniejące już systemy informatyczne. Przykładowo komponenty aplikacji JEE mogą potrzebować dostępu do systemów informatycznych enterprise w celu połączenia z bazą danych.

Kontenery Javy EE Tworzenie wielowarstwowych aplikacji z cienkim klientem jest zazwyczaj trudne, ponieważ zawierają wiele linii skomplikowanego kodu odpowiedzialnego za zarządzanie transakcjami i stanem, obsługę wielowątkowości, tworzenie puli zasobów oraz inne niskopoziomowe szczegóły. Niezależna od platformy, oparta o komponenty architektura Javy EE sprawia, że aplikacje JEE pisze się łatwo, ponieważ logika biznesowa podzielona jest pomiędzy komponenty, które można wielokrotnie wykorzystywać. Poza tym, serwer Javy EE dostarcza podstawowe

Rozdział 1 y Przegląd technologii

29

Kontenery Javy EE

usługi w formie komponentów. Ponieważ samodzielne implementowanie tych usług nie jest konieczne, możesz poświęcić swoją uwagę rozwiązywaniu innych problemów.

Usługi kontenera Kontenery są interfejsem pomiędzy komponentami a niskopoziomowymi, specyficznymi dla danej platformy funkcjami obsługującymi działanie komponentu. Aby komponenty EJB, webowy czy aplikacji klienckiej, mogły zostać uruchomione, należy uprzednio zbudować z nich moduł Javy EE i wdrożyć go na kontenerze JEE. Proces budowania obejmuje specyfikację ustawień kontenera dla całej aplikacji JEE i dla każdego jej komponentu. Ustawienia kontenera dostosowują usługi serwera Javy EE wspierające aplikację, między innymi usługi zapewniające bezpieczeństwo oraz zarządzające transakcjami, wyszukiwanie poprzez API interfejsu JNDI (ang. Java Naming and Directory Interface) oraz połączenia zdalne. Do najważniejszych cech tych usług możemy zaliczyć: „

„

„

„

dostarczanie przez model zabezpieczeń Javy EE możliwości konfigurowania komponentów webowych oraz EJB w taki sposób, aby dostęp do zasobów systemu mieli tylko autoryzowani użytkownicy, dostarczanie przez model transakcji Javy EE możliwości specyfikowania zależności pomiędzy metodami składającymi się na pojedynczą transakcję, tak aby wszystkie te metody traktowane były jak całość, dostarczanie przez usługi wyszukiwania JNDI jednolitego interfejsu do wielu usług katalogowych przedsiębiorstwa, dzięki czemu komponenty aplikacji mogą odwoływać się do tych usług, zarządzanie poprzez model połączeń zdalnych Javy EE niskopoziomową komunikacją między klientami a komponentami EJB. Kiedy komponenty te zostaną utworzone, klient może wywoływać ich metody tak, jakby działały na tej samej wirtualnej maszynie.

Ponieważ architektura Javy EE zawiera konfigurowalne usługi, komponenty tej samej aplikacji JEE mogą zachowywać się inaczej, w zależności od tego, gdzie zostaną wdrożone, na przykład ziarno EJB może posiadać różne ustawienia zabezpieczeń pozwalające na pewien poziom dostępu do bazy danych w różnych środowiskach produkcyjnych. Kontener zarządza także usługami, takimi jak cykl życia serwletów oraz komponentów EJB, tworzenie puli połączeń do zasobów bazodanowych, zapisywanie danych oraz dostęp do API platformy Javy EE (patrz podrozdział „API Javy EE 6” w tym rozdziale), których konfiguracja nie jest możliwa.

Typy kontenerów Proces wdrażania instaluje komponenty aplikacji JEE na serwerze Javy EE w sposób przedstawiony na rysunku 1.5.

30

Java EE 6. Zaawansowany przewodnik

Obsługa usług sieciowych

Rysunek 1.5. Serwer i kontenery Javy EE „

„

„

„

„

Serwer Javy EE — środowisko uruchomieniowe aplikacji JEE. Serwer Javy EE dostarcza kontener EJB oraz kontener webowy. Kontener Enterprise JavaBeans (EJB) — zarządza wykonywaniem ziaren EJB w aplikacjach JEE. Komponenty EJB i ich kontener działają na serwerze Javy EE. Kontener webowy — zarządza działaniem stron internetowych, serwletów i niektórych komponentów EJB aplikacji JEE. Komponenty webowe i ich kontener działają na serwerze Javy EE. Kontener aplikacji klienckich — zarządza działaniem komponentów aplikacji klienckiej. Aplikacje klienckie i ich kontener działają po stronie klienta. Kontener apletów — zarządza wykonywaniem apletów. Składa się z przeglądarki internetowej oraz wtyczki Java uruchomionych jednocześnie po stronie klienta.

Obsługa usług sieciowych Usługi sieciowe są internetowymi aplikacjami typu enterprise, które do obsługi danych z wywołującymi je klientami korzystają z otwartych standardów i protokołów transportowych języka XML. Platforma Javy EE oferuje API i narzędzia napisane w języku XML, przy użyciu których możesz szybko zaprojektować, utworzyć, przetestować i wdrożyć usługi sieciowe oraz klienty w pełni współpracujące z innymi usługami sieciowymi i klientami działającymi zarówno na opartych o Javę platformach, jak i takich, które nie są z Javą powiązane. Rozdział 1 y Przegląd technologii

31

Obsługa usług sieciowych

Pisząc usługi sieciowe i ich klienty za pomocą API XML-a w Javie EE, musisz tylko podać wartości parametrów do wywołań metody i przetworzyć zwrócone wyniki. W usługach sieciowych opartych na wymianie dokumentów wysyłane są w jedną i w drugą stronę dokumenty zawierające dane usługi. Nie wymaga to niskopoziomowego programowania, ponieważ implementacje API XML-a wykonują tłumaczenie danych aplikacji ze strumienia danych XML i na takiż strumień; dane są przesyłane po ustandaryzowanych protokołach transportowych języka XML. W kolejnych punktach przedstawiono wspomniane standardy oraz protokoły XML-a. Tłumaczenie danych na ustandaryzowany strumień danych XML jest tym, co sprawia, że pisane przy użyciu opracowanego w języku XML API Javy EE usługi sieciowe i ich klienty są w pełni interoperacyjne. Nie oznacza to jednak, że przesyłane dane muszą koniecznie zawierać znaczniki XML — mogą być one zwykłym tekstem, dokumentem XML lub danymi binarnymi w dowolnej postaci, na przykład danymi audio, wideo, mapami, plikami programów, dokumentami zawierającymi projekty wspomagane komputerowo (dokumenty CAD) i podobnymi. Kolejny punkt stanowi wprowadzenie do języka XML; wyjaśniamy w nim, w jaki sposób komercyjne przedsiębiorstwa mogą używać znaczników i schematów XML-a do merytorycznej wymiany danych.

XML Język XML (ang. Extensible Markup Language) jest międzyplatformowym, rozszerzalnym, tekstowym standardem reprezentacji danych. Strony wymieniające się danymi w XML-u mogą tworzyć własne znaczniki do opisu danych, budować schematy specyfikujące użycie znaczników w danym rodzaju dokumentu oraz używać arkuszy stylów XML-a do zarządzania wyświetlaniem danych i operowaniem nimi. Przykładowo w usłudze sieciowej można użyć XML-a i schematów, aby wyprodukować cennik, a firmy otrzymujące cennik i jego schemat mogą posiadać własny arkusz stylów pozwalający obsłużyć dane w sposób, jaki spełnia ich oczekiwania, na przykład tak: „

„

„

jedna z firm może przetworzyć dokument XML-a zawierający cennik w programie, który przetłumaczy go na dokument HTML, tak aby cennik mógł zostać umieszczony w firmowym intranecie, firma partnerska może przetworzyć dokument XML-a zawierający cennik w narzędziu do tworzenia prezentacji marketingowych, inna firma może natomiast wczytać dokument XML-a zawierający cennik do aplikacji w celu jego przetworzenia.

Protokół transportowy SOAP Żądania klienta i odpowiedzi usługi sieciowej są przesyłane jako wiadomości protokołu SOAP (ang. Simple Object Access Protocol) w standardzie HTTP, w celu zapewnienia w pełni interoperacyjnej wymiany pomiędzy klientami a usługami

32

Java EE 6. Zaawansowany przewodnik

Budowanie i wdrażanie aplikacji Javy EE

działającymi na odmiennych platformach i w różnych punktach sieci internetowej. HTTP wykorzystujący model żądanie-odpowiedź jest znanym standardem pozwalającym na przesyłanie wiadomości w internecie, a SOAP jest opartym o język XML protokołem zbudowanym na modelu żądanie-odpowiedź specyfikowanym przez HTTP. Część protokołu SOAP przekazywanej wiadomości pełni następujące funkcje: „

„

„

określa sposób opakowania danych przez XML, aby opisać, co zawiera wiadomość i jak ją przetworzyć, zawiera reguły kodowania XML-a, aby opisać wystąpienia specyficznych dla aplikacji typów danych występujących w wiadomości, określa przyjętą konwencję reprezentowania w języku XML żądania do zdalnej usługi i odpowiedzi na nie.

Standard formatu WSDL WSDL (ang. Web Services Description Language) jest ustandaryzowanym formatem XML-a służącym do opisywania usług sieciowych. Opis zawiera nazwę usługi, jej lokalizację na serwerze oraz sposób komunikacji z tą usługą. Opisy WSDL usług mogą zostać opublikowane w internecie. Serwer GlassFish zawiera narzędzie do generowania specyfikacji WSDL usługi sieciowej używającej do komunikacji z klientami mechanizmu zdalnych wywołań procedur (RPC).

Budowanie i wdrażanie aplikacji Javy EE Aplikacje JEE są pakowane w jedną lub więcej ustandaryzowanych jednostek, które można wdrażać na platformie zgodnej ze specyfikacją platformy Javy EE. Każda taka jednostka zawiera: „

„

komponent lub komponenty funkcjonalne, takie jak ziarno EJB, strona internetowa, serwlet lub aplet, opcjonalny deskryptor wdrożenia opisujący jej zawartość.

Utworzona jednostka Javy EE jest gotowa do wdrożenia. Proces ten zazwyczaj polega na użyciu narzędzi do wdrażania dostarczanych przez daną platformę w celu podania informacji specyficznych dla danej instalacji, takich jak lista użytkowników mających dostęp do instancji aplikacji oraz nazwa lokalnej bazy danych. Kiedy aplikacja zostanie wdrożona na lokalną platformę, jest gotowa do użycia.

Pakowanie aplikacji Aplikacje Javy EE są dystrybuowane w plikach JAR (ang. Java Archive), WAR (ang. Web Archive) lub EAR (ang. Enterprise Archive). Pliki WAR i EAR są standardowymi plikami JAR (.jar) z rozszerzeniem, odpowiednio, .war lub .ear.

Rozdział 1 y Przegląd technologii

33

Pakowanie aplikacji

Użycie plików oraz modułów JAR, WAR i EAR pozwala na złożenie kilku różnych aplikacji JEE przy użyciu części tych samych komponentów. Nie wymaga to dodatkowego programowania, jest jedynie kwestią budowania (pakowania) różnych modułów Javy EE w pliki JAR, WAR lub EAR. Struktura pliku EAR, przedstawiona na rysunku 1.6, zawiera moduły Javy EE oraz, opcjonalnie, deskryptor wdrożenia. Deskryptor wdrożenia (ang. deployment descriptor) — dokument XML-a z rozszerzeniem .xml — opisuje ustawienia wdrożenia aplikacji, modułu bądź komponentu. Ponieważ informacja w nim zawarta jest deklaratywna, może zostać zmieniona bez konieczności modyfikowania kodu źródłowego aplikacji. W trakcie działania aplikacji serwer czyta deskryptor wdrożenia i odpowiednio wpływa na aplikację, moduł lub komponent.

Rysunek 1.6. Struktura pliku EAR

Wyróżniamy dwa typy deskryptorów wdrożenia — deskryptor wdrożenia Javy EE oraz deskryptor wdrożenia środowiska uruchomieniowego. Deskryptor wdrożenia Javy EE (ang. Java EE deployment descriptor) jest zdefiniowany przez specyfikację Javy EE i może być użyty do konfigurowania ustawień wdrożenia na którejkolwiek z implementacji platformy Javy EE zgodnej z jej specyfikacją. Deskryptor wdrożenia środowiska uruchomieniowego (ang. runtime deployment descriptor) używany jest w celu skonfigurowania parametrów specyficznych dla konkretnej implementacji platformy Javy EE. Przykładowo deskryptor wdrożenia środowiska uruchomieniowego serwera GlassFish zawiera takie informacje jak główny kontekst (ang. context root) aplikacji internetowych, a również specyficzne dla implementacji serwera GlassFish parametry, takie jak ustawienia pamięci podręcznej. Deskryptory wdrożenia środowiska uruchomieniowego serwera GlassFish nazywane są glassfish-typModułu.xml i umieszczane, tak samo jak deskryptor wdrożenia Javy EE, w katalogu META-INF.

34

Java EE 6. Zaawansowany przewodnik

Role w procesie wytwarzania aplikacji

Moduł Javy EE składa się z jednego komponentu (lub większej ich ilości) uruchamianego na tym samym typie kontenera i, opcjonalnie, jednego deskryptora wdrożenia komponentu tego typu. Deskryptor wdrożenia modułu EJB na przykład deklaruje atrybuty transakcji oraz reguły autoryzacji komponentów EJB. Moduł Javy EE może być wdrożony jako samodzielny moduł. Oto typy modułów Javy EE: „

„

„

„

moduły EJB, zawierające pliki klas ziaren EJB oraz deskryptor wdrożenia EJB; moduły EJB są pakowane do plików JAR z rozszerzeniem .jar, moduły webowe, które zawierają pliki klas serwletów, klas pomocniczych, dynamiczne dokumenty WWW, pliki GIF i HTML oraz deskryptor wdrożenia aplikacji; moduły webowe pakowane są do plików JAR z rozszerzeniem .war, moduły aplikacji klienckich, zawierające pliki klas i deskryptor wdrożenia aplikacji klienckiej; moduły te pakowane są do plików JAR z rozszerzeniem .jar, moduły adapterów zasobów, które zawierają wszystkie interfejsy, klasy, natywne biblioteki oraz inną dokumentację Javy, wraz z deskryptorem wdrożenia adaptera zasobów. Wspólnie implementują architekturę Java EE Connector (patrz punkt „Architektura Java EE Connector” w tym rozdziale) dla danego EIS. Moduły te pakowane są do plików JAR z rozszerzeniem .rar (ang. resource adapter archive).

Role w procesie wytwarzania aplikacji Możliwość wielokrotnego użycia modułów sprawia, że w procesie tworzenia i wdrażania aplikacji można wyodrębnić role w taki sposób, aby różne osoby lub firmy miały możliwość wykonywania odmiennych fragmentów procesu. Pierwsze dwie role, to jest dostawca oprogramowania Java EE oraz dostawca narzędzi, wymagają zakupu oraz instalacji oprogramowania Java EE i narzędzi. Kiedy oprogramowanie jest już kupione i zainstalowane, dostawcy komponentów aplikacji mogą rozpocząć tworzenie komponentów, które następnie są budowane przez budowniczych aplikacji (ang. application assemblers) oraz wdrażane przez wdrożeniowców. W dużych firmach każda z tych ról może być przypisana do różnych osób lub zespołów. Podział pracy jest skuteczny, ponieważ każda z ról wytwarza przenośny plik, który jest punktem wyjścia dla kolejnej roli, na przykład na etapie tworzenia komponentów aplikacji twórca komponentów EJB dostarcza zawierające je archiwa JAR. Następnie osoba pełniąca rolę budowniczego aplikacji może złożyć te archiwa w aplikację JEE i zapisać ją w pliku EAR. Administrator systemu, pełniący rolę wdrożeniowca, może teraz użyć dostarczonego mu pliku EAR, aby zainstalować aplikację na serwerze Javy EE u klienta. Poszczególne role nie muszą być przydzielone różnym osobom. Jeśli na przykład pracujesz w małej firmie lub piszesz prototyp aplikacji, możesz wykonać zadania każdej z ról we wszystkich etapach.

Rozdział 1 y Przegląd technologii

35

Role w procesie wytwarzania aplikacji

Dostawca oprogramowania Java EE Dostawcą oprogramowania Java EE jest firma tworząca implementacje API oraz innych elementów definiowanych przez specyfikację platformy Javy EE i umożliwiająca ich zakup. Rolę tę pełnią zazwyczaj dostawcy serwerów aplikacji implementujących platformę Javy EE i zgodnych ze specyfikacją Java EE 6 Platform.

Dostawca narzędzi Rolę dostawcy narzędzi pełnią osoby lub firmy opracowujące narzędzia do tworzenia, budowania i pakowania aplikacji, wykorzystywane przez dostawców komponentów, budowniczych i wdrożeniowców.

Dostawca komponentów aplikacji Dostawca komponentów aplikacji to osoba (lub firma) tworząca komponenty webowe, EJB, aplety oraz aplikacje klienckie używane w aplikacjach JEE.

Twórca komponentów EJB W celu dostarczenia archiwum JAR, zawierającego jedno lub więcej ziaren EJB, twórca komponentów EJB wykonuje następujące czynności: „ „ „

tworzy oraz kompiluje kod źródłowy komponentów, tworzy deskryptor wdrożenia (opcjonalnie), pakuje pliki .class i deskryptor wdrożenia do archiwum JAR modułu EJB.

Twórca komponentów webowych W celu dostarczenia archiwum WAR, zawierającego jeden lub więcej komponentów webowych, twórca komponentów webowych wykonuje następujące czynności: „ „ „ „

tworzy oraz kompiluje kod źródłowy serwletów, tworzy pliki JavaServer Faces, JSP oraz HTML, tworzy deskryptor wdrożenia (opcjonalnie), pakuje pliki .class, .jsp, .html oraz deskryptor wdrożenia do archiwum WAR.

Twórca aplikacji klienckich W celu dostarczenia archiwum JAR, zawierającego aplikację kliencką, twórca aplikacji klienckiej wykonuje następujące czynności: „ „ „

36

tworzy oraz kompiluje kod źródłowy aplikacji klienckiej, tworzy deskryptor wdrożenia aplikacji klienckiej (opcjonalnie), pakuje pliki .class i deskryptor wdrożenia do archiwum JAR.

Java EE 6. Zaawansowany przewodnik

API Javy EE 6

Budowniczy aplikacji Budowniczy aplikacji to osoba (lub firma), która otrzymuje moduły aplikacji od dostawców komponentów i składa je w plik EAR aplikacji JEE. Budowniczy lub wdrożeniowiec mogą wprowadzać zmiany w deskryptorze wdrożenia zarówno bezpośrednio w pliku, jak przy użyciu narzędzi pozwalających dodać znaczniki XML-a do modyfikowalnych części dokumentu przy użyciu interaktywnych formularzy. W celu dostarczenia pliku EAR, zawierającego aplikację Javy EE, programista wykonuje następujące czynności: „

„ „

składa pliki JAR modułów EJB oraz pliki WAR, utworzone w poprzednich etapach, w plik archiwum EAR aplikacji JEE, tworzy deskryptor wdrożenia aplikacji Javy EE (opcjonalnie), sprawdza, czy zawartość archiwum EAR posiada odpowiednią strukturę i jest zgodna ze specyfikacją Javy EE.

Wdrożeniowiec oraz administrator Wdrożeniowiec i administrator aplikacji to osoba (lub firma), która konfiguruje oraz wdraża klienty aplikacji, aplikacje webowe, komponenty EJB, aplikację JEE, zarządza infrastrukturą obliczeniową i sieciową miejsca, w którym jest wdrażana, oraz nadzoruje środowisko uruchomieniowe. Do obowiązków tej roli należy konfiguracja ustawień transakcji i zabezpieczeń oraz parametrów połączenia do bazy danych. Podczas konfiguracji wdrożeniowiec postępuje zgodnie z instrukcjami dostarczonymi przez dostawcę komponentu aplikacji w celu rozwiązania zewnętrznych zależności, określenia ustawień zabezpieczeń oraz przypisania atrybutów transakcji. Podczas instalacji wdrożeniowiec przenosi komponenty aplikacji na serwer i generuje klasy oraz interfejsy specyficzne dla danego kontenera. W celu zainstalowania oraz skonfigurowania aplikacji Javy EE wdrożeniowiec lub administrator systemów wykonuje następujące czynności: „ „

„

konfiguruje aplikację Javy EE pod środowisko, w którym ma działać, sprawdza, czy zawartość archiwum EAR posiada odpowiednią strukturę i jest zgodna ze specyfikacją Javy EE, wdraża (instaluje) archiwum EAR z aplikacją na serwerze Javy EE.

API Javy EE 6 Na rysunku 1.7 ukazujemy zależności pomiędzy kontenerami Javy EE.

Rozdział 1 y Przegląd technologii

37

API Javy EE 6

Rysunek 1.7. Kontenery Javy EE

Na rysunku 1.8 pokazujemy dostępność API Javy EE 6 w kontenerze webowym.

Rysunek 1.8. API Javy EE w kontenerze webowym

38

Java EE 6. Zaawansowany przewodnik

API Javy EE 6

Na rysunku 1.9 przedstawiamy dostępność API Javy EE 6 w kontenerze EJB.

Rysunek 1.9. API Javy EE w kontenerze EJB

Na rysunku 1.10 można obejrzeć dostępność API Javy EE 6 w kontenerze aplikacji klienckich. W kolejnych punktach opisane zostaną pokrótce technologie wymagane przez platformę Java EE oraz API używane przez aplikacje JEE.

Technologia Enterprise JavaBeans Komponenty EJB (ang. Enterprise JavaBeans), zwane także ziarnami EJB, są fragmentami kodu zawierającymi pola oraz metody implementujące części logiki biznesowej. Możesz wyobrazić sobie, że ziarna EJB to klocki, które mogą działać samodzielnie lub być łączone z innymi ziarnami EJB, by wykonywać logikę biznesową na serwerze Javy EE.

Rozdział 1 y Przegląd technologii

39

API Javy EE 6

Rysunek 1.10. API Javy EE w kontenerze aplikacji klienckich

Komponenty EJB dzielimy na: „

„

komponenty sesyjne, reprezentujące czasową wymianę informacji z klientem; kiedy klient zakończy wykonywanie, komponent sesyjny oraz dane w nim zawarte są usuwane, komponenty sterowane komunikatami (ang. message-driven), składające się z komponentu sesyjnego oraz mechanizmu nasłuchiwania komunikatów, które pozwalają komponentowi biznesowemu odbierać komunikaty w sposób asynchroniczny. Komunikaty te są zazwyczaj komunikatami usługi Java Message Service (JMS).

Platforma Javy EE 6 wprowadza do ziaren EJB nowe funkcjonalności, między innymi: „ „

„

możliwość dołączania wywoływanych lokalnie ziaren EJB do archiwów WAR, komponenty sesyjne typu singleton, pozwalające na łatwe udostępnianie i współdzielenie ich stanu, lekki podzbiór funkcjonalności Enterprise JavaBeans (EJB Lite), dostarczany przy użyciu profili Javy EE, takich jak profil webowy Javy EE.

Platforma Java EE 6 wymaga Enterprise JavaBeans 3.1 i Interceptors 1.1. Wchodząca w skład specyfikacji EJB 3.1 specyfikacja interceptorów sprawia, że mechanizm ten, zdefiniowany jako część specyfikacji EJB 3.0, jest bardziej dostępny.

Technologia Java Servlet Technologia Java Servlet pozwala na definiowanie własnych, specyficznych dla protokołu HTTP klas serwletów. Serwlety rozszerzają możliwości serwera hostującego aplikacje o dostępie opartym na modelu żądanie-odpowiedź. Pomimo iż serwlety mogą odpowiadać na dowolne żądania, zazwyczaj używane są jako rozszerzenia aplikacji na serwerach webowych.

40

Java EE 6. Zaawansowany przewodnik

API Javy EE 6

W poczet nowych cech technologii Java Servlet, wprowadzonych w Javie EE 6, zalicza się między innymi: „ „ „ „ „

obsługę adnotacji, obsługę asynchroniczności, łatwość konfiguracji, ulepszenia istniejącego API, dodawanie serwletów za pomocą API w trakcie działania aplikacji (ang. pluggablity).

Platforma Java EE 6 wymaga technologii Servlet w wersji 3.0.

Technologia JavaServer Faces Technologia JavaServer Faces jest frameworkiem służącym do budowania interfejsu użytkownika w aplikacjach internetowych. Do głównych komponentów technologii JavaServer Faces należą: „ „

„

framework oferujący komponenty graficznego interfejsu użytkownika (GUI), elastyczny model wyświetlania komponentów w różnych rodzajach języka HTML, językach znaczników oraz technologiach; obiekt Renderer generuje znacznik wyświetlający komponent i konwertuje dane przechowywane w obiekcie modelu danych na typy, które mogą zostać wyświetlone w widoku, standardowa implementacja klasy RenderKit generująca znaczniki zgodne z HTML/4.01.

Poniżej wymieniono elementy wspierające funkcjonalność komponentów GUI: „ „ „ „ „ „

walidacja danych wejściowych, obsługa zdarzeń, konwersja danych pomiędzy obiektami modelu danych a komponentami, zarządzany proces tworzenia obiektów modelu danych, konfiguracja nawigacji strony, język wyrażeń Expression Language (EL).

Wszystkie te funkcje dostępne są za pomocą standardowych API Javy oraz plików konfiguracyjnych XML-a. Wśród nowych elementów technologii JavaServer Faces, wprowadzonych w Javie EE 6, wymienić należy: „

„

„ „ „

możliwość oznaczania komponentów zarządzanych adnotacją, a nie wpisem w pliku konfiguracyjnym, Facelets — technologię wyświetlania korzystającą z XHTML-a, zastępującą dotychczas używaną technologię JavaServer Pages (JSP), obsługę technologii Ajax, złożone komponenty, domyślną nawigację.

Rozdział 1 y Przegląd technologii

41

API Javy EE 6

Platforma Java EE 6 wymaga technologii JavaServer Faces w wersji 2.0 i Expression Language w wersji 2.2.

Technologia JavaServer Pages Technologia JavaServer Pages (JSP) pozwala na umieszczanie fragmentów kodu serwletu (tak zwanych snippetów, ang. snippets) bezpośrednio w dokumencie tekstowym. Strona JSP jest dokumentem tekstowym zawierającym dwa rodzaje tekstu: „

„

statyczne dane, które mogą być wyrażone w którymkolwiek z tekstowych formatów, takich jak HTML czy XML, elementy JSP określające, w jaki sposób na stronie konstruowane są dynamiczne treści.

Więcej informacji na temat technologii JSP znajdziesz na stronie The Java EE 5 Tutorial dostępnej pod adresem http://docs.oracle.com/javaee/5/tutorial/doc/. Platforma Java EE 6 wymaga technologii JavaServer Pages w wersji 2.2 w celu zapewnienia zgodności z wcześniejszymi wydaniami, ale w nowych aplikacjach zaleca stosowanie technologii Facelets.

Biblioteka JavaServer Pages Standard Tag Library Standardowa biblioteka znaczników JavaServer Pages (ang. JavaServer Pages Standard Tag Library, w skrócie JSTL) zawiera podstawową funkcjonalność wspólną dla wielu aplikacji JSP. Zamiast mieszania w swojej aplikacji JSP znaczników od wielu różnych dostawców, używasz jednego, ustandaryzowanego zbioru znaczników. Standaryzacja pozwalająca na wdrażanie aplikacji na którykolwiek z kontenerów JSP obsługujący JSTL zwiększa prawdopodobieństwo, że implementacja znaczników jest optymalna. JSTL zawiera znaczniki iteratorów oraz instrukcji warunkowych umożliwiające zarządzanie przepływem, znaczniki służące do operowania na dokumentach XML, znaczniki pozwalające na internacjonalizację aplikacji, dostęp do bazy danych za pomocą SQL-a oraz inne, często używane funkcje. Platforma Java EE 6 wymaga JSTL w wersji 1.2.

Java Persistence API Java Persistence API (JPA) to oparte na standardach rozwiązanie Javy dla warstwy trwałości danych. W warstwie tej użyto odwzorowania obiektowo-relacyjnego, aby utworzyć połączenie między modelem obiektowym i relacyjną bazą danych. Technologia Java Persistence API może być również używana poza środowiskiem JEE, w aplikacjach Javy SE. Java Persistence składa się z następujących elementów:

42

Java EE 6. Zaawansowany przewodnik

API Javy EE 6

„ „ „

Java Persistence API, języka zapytań, metadanych odwzorowania obiektowo-relacyjnego.

Platforma Java EE 6 wymaga Java Persistence API w wersji 2.0.

Java Transaction API Java Transaction API (JTA) oferuje standardowy interfejs do określania transakcji. Architektura Javy EE zawiera domyślny mechanizm automatycznego zatwierdzania, obsługującego operacje zatwierdzenia i wycofania transakcji. Automatyczne zatwierdzanie oznacza, że wszystkie inne aplikacje przeglądające dane będą „widziały” zmienione dane po każdej operacji odczytu i zapisu do bazy. Ponieważ aplikacja może wykonywać dwie zależne od siebie operacje dostępu do bazy danych, konieczne jest użycie API JTA, aby oznaczyć miejsca, w których transakcja spinająca wszystkie te operacje ma swój początek oraz koniec (poprzez wywołanie operacji commit lub rollback). Platforma Java EE 6 wymaga Java Transaction API w wersji 1.1.

API Javy dla usług sieciowych typu REST API Javy dla usług sieciowych typu REST (JAX-RS) pozwala na tworzenie usług sieciowych zgodnie z architekturą REST (ang. Representational State Transfer). Aplikacja JAX-RS jest aplikacją internetową składającą się z klas pakowanych jako serwlety do archiwum WAR, wraz z wymaganymi bibliotekami. API JAX-RS zostało wprowadzone w Javie EE 6. Platforma Java EE 6 wymaga JAX-RS w wersji 1.1.

Managed Beans Managed Beans to lekkie, zarządzane przez kontener obiekty POJO o minimalnych wymaganiach; obsługują niewielki podzbiór podstawowych usług, takich jak wstrzykiwanie zasobów, odwołania do cyklu życia oraz interceptory. Są one uogólnieniem komponentów zarządzanych opisanych w specyfikacji technologii JavaServer Faces i mogą być używane nie tylko w modułach webowych, ale w każdej aplikacji Javy EE. Specyfikacja Managed Beans jest częścią specyfikacji platformy Java EE 6 (JSR 316). Managed Beans zostały wprowadzone w Javie EE 6. Platforma Java EE 6 wymaga Managed Beans w wersji 1.0.

Rozdział 1 y Przegląd technologii

43

API Javy EE 6

Contexts and Dependency Injection for the Java EE Platform (JSR 299) Contexts and Dependency Injection (w skrócie CDI) Javy, czyli wstrzykiwanie kontekstów i zależności, definiuje zbiór kontekstowych usług, dostarczanych przez kontenery Javy EE, które pozwalają na łatwe użycie przez twórców aplikacji internetowych ziaren EJB wraz z technologią JavaServer Faces. Zbiór CDI utworzony do wykorzystania z obiektami stanowymi (ang. stateful) ma o wiele szersze zastosowanie, bo pozwala programistom na niezwykle elastyczne integrowanie różnych typów komponentów: łączy je w luźny, ale i bezpieczny, z punktu widzenia typowania, sposób. CDI został wprowadzony w Javie EE 6. Platforma Java EE 6 wymaga CDI w wersji 1.0.

Dependency Injection for Java (JSR 330) Dependency Injection for Java (w skrócie DI), czyli wstrzykiwanie zależności dla Javy, określa standardowy zestaw adnotacji (oraz jeden interfejs) używanych na wstrzykiwanych klasach. W platformie Javy EE zbiór CDI zapewnia obsługę wstrzykiwania zależności. Oznacza to, że punktów wstrzykiwania określonych za pomocą DI można użyć tylko w aplikacji korzystającej z CDI. Dependency Injection został wprowadzony w Javie EE 6. Platforma Java EE 6 wymaga Dependency Injection for Java w wersji 1.0.

Bean Validation Specyfikacja technologii Bean Validation definiuje model metadanych oraz API służące do walidacji danych przechowywanych w komponentach JavaBeans. Zamiast rozpraszać walidację danych na kilku warstwach, takich jak przeglądarka i strona serwerowa, możesz zdefiniować reguły walidacji w jednym miejscu i współdzielić je pomiędzy warstwami. Bean Validation została wprowadzona w Javie EE 6. Platforma Java EE 6 wymaga Bean Validation w wersji 1.0.

Java Message Service API Java Message Service API (JMS) jest standardem komunikacji pozwalającym komponentom aplikacji JEE tworzyć, wysyłać, odbierać i odczytywać wiadomości. Umożliwia rozproszoną, luźno powiązaną, niezawodną i asynchroniczną komunikację. Platforma Java EE 6 wymaga JMS w wersji 1.1.

44

Java EE 6. Zaawansowany przewodnik

API Javy EE 6

Architektura Java EE Connector Java EE Connector Architecture (JCA) jest wykorzystywana przez dostawców narzędzi oraz integratorów systemów do tworzenia adapterów zasobów, które można podłączyć do dowolnego produktu JEE, a które wspierają dostęp do systemów informatycznych enterprise. Adapter zasobu to element oprogramowania pozwalający komponentom aplikacji Javy EE na dostęp i interakcję z przykrytym nim zarządcą zasobów systemu EIS. Ponieważ adapter zasobu jest specyficzny dla danego zarządcy zasobów, istnieje wiele adapterów dla różnych typów bazy danych czy systemu EIS. Architektura Java EE Connector dostarcza narzędzia pozwalające na wydajną, bezpieczną, skalowalną, wykorzystującą przesyłanie komunikatów i transakcyjną integrację opartych o Javę EE usług sieciowych z istniejącymi systemami EIS zarówno w sposób synchroniczny, jak i asynchroniczny. Aplikacje i systemy EIS zintegrowane przy użyciu JEE Connector Architecture z platformą Javy EE mogą zostać upublicznione za pomocą JAX-WS i modelu komponentów Javy EE jako usługi sieciowe XML-a. Z tego powodu JAX-WS i architektura Java EE Connector to uzupełniające się wzajemnie technologie w systemach integracji aplikacji typu enterprise (EAI, ang. Enterprise Application Integration) oraz całościowej integracji biznesowej. Platforma Java EE 6 wymaga Java EE Connector w wersji 1.6.

JavaMail API W aplikacjach Javy EE zastosowano API JavaMail do wysyłania wiadomości e-mail. API to składa się z dwóch części: „

„

interfejsu aplikacyjnego używanego przez komponenty aplikacji do wysyłania wiadomości, interfejsu dostawcy usługi.

Platforma Javy EE zawiera API JavaMail wraz z dostawcą usługi, który pozwala komponentom aplikacji na wysyłanie wiadomości elektronicznych. Platforma Java EE 6 wymaga JavaMail w wersji 1.4.

Java Authorization Contract for Containers Java Authorization Contract for Containers (JACC), czyli kontrakt autoryzacji kontenerów Javy, określa kontrakt wiążący kontener aplikacji Javy EE i dostawcę polityki autoryzacji. Wszystkie kontenery Javy EE stosują się do tego kontraktu. Specyfikacja JACC definiuje rozszerzenia klasy uprawnień java.security. ´Permission implementujące model autoryzacji Javy EE. Specyfikacja ustala powiązania między instancjami tych klas a decyzjami kontenera dotyczącymi

Rozdział 1 y Przegląd technologii

45

API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7

dostępu do zasobów. Określa także składnię dla dostawców polityki bezpieczeństwa, używających nowych klas uprawnień, by spełnić wymagania dotyczące autoryzacji na platformie Javy EE, włącznie z definiowaniem i używaniem ról. Platforma Java EE 6 wymaga JACC w wersji 1.4.

Java Authentication Service Provider Interface for Containers Specyfikacja Java Authentication Service Provider Interface for Containers (JASPIC), czyli interfejsu dostawcy usług uwierzytelniania dla kontenerów Javy, określa interfejs dostawcy usług (SPI, ang. Service Provider Interface), przez który dostawcy usług uwierzytelniania implementujący mechanizmy uwierzytelniania komunikatów mogą integrować klienckie bądź serwerowe kontenery oraz środowiska przetwarzania komunikatów. Dostawcy usług uwierzytelniania zintegrowani przez ten interfejs operują na wiadomościach sieciowych dostarczonych im przez wywołujący je kontener. Transformują wychodzące wiadomości tak, aby ich nadawca mógł zostać uwierzytelniony przez odbierający je kontener, a odbiorca wiadomości mógł być uwierzytelniony przez jej nadawcę. Dostawcy tych usług uwierzytelniają przychodzące wiadomości i zwracają do odpytującego kontenera tożsamość ustaloną w wyniku uwierzytelnienia wiadomości. JASPIC została wprowadzona w Javie EE 6. Platforma Java EE 6 wymaga JASPIC w wersji 1.0.

API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7 Niektóre z API wymaganych przez Javę EE 6 są częścią platformy Java Platform, Standard Edition 6 i 7 (Java SE 6 i 7), dzięki czemu dostępne są dla aplikacji JEE.

Java Database Connectivity API API Java Database Connectivity (JDBC API), czyli API służące do łączenia się z bazą danych, pozwala na wykonywanie zapytań i poleceń SQL w metodach pisanych w języku Java. API JDBC można użyć w sesyjnych ziarnach EJB, które muszą posiadać dostęp do bazy. Możesz skorzystać z niego także w kodzie serwletów i stron JSP, aby wywoływać z nich zapytania z pominięciem komponentów EJB. API JDBC składa się z dwóch części: „

„

46

interfejsu aplikacyjnego używanego przez komponenty aplikacji w celu uzyskania dostępu do bazy danych, interfejsu dostawcy usługi pozwalającego na podłączenie sterownika JDBC do platformy Javy EE.

Java EE 6. Zaawansowany przewodnik

API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7

Platforma Java SE 6 wymaga JDBC w wersji 4.0.

Java Naming and Directory Interface API API Java Naming and Directory Interface (JNDI) zapewnia dostęp do funkcjonalności usług nazewnictwa oraz katalogowych; daje aplikacji dostęp do wielu takich usług, włącznie z usługami już istniejącymi, na przykład LDAP, NDS, DNS i NIS. API to dostarcza aplikacji metody wykonujące standardowe operacje katalogowe, takie jak łączenie atrybutów z obiektami i wyszukiwanie obiektów przy użyciu ich atrybutów. Zastosowanie JNDI sprawia, że aplikacja JEE może przechowywać i wyszukiwać nazwane obiekty Javy dowolnego typu, a to pozwala Javie EE współdziałać z wieloma istniejącymi już aplikacjami. Usługi nazewnictwa Javy EE zapewniają dostęp do środowiska nazewnictwa JNDI aplikacjom klienckim, ziarnom EJB oraz komponentom webowym. Środowisko nazewnictwa pozwala dostosowywać komponenty bez wykonywania zmian w ich kodzie źródłowym. Kontener implementuje środowisko komponentu i dostarcza je w postaci kontekstu nazewnictwa JNDI (ang. naming context JNDI). Komponent Javy EE może zlokalizować kontekst nazewnictwa swojego środowiska przy użyciu interfejsów JNDI: tworzy obiekt javax.naming.InitialContext i przy jego użyciu wyszukuje kontekst nazewnictwa swojego środowiska pod nazwą java:comp/env. Przestrzeń nazewnictwa komponentu przechowywana jest bezpośrednio w kontekście nazewnictwa środowiska lub w którymkolwiek z jego bezpośrednich i pośrednich subkontekstów. Komponenty Javy EE mają dostęp do nazwanych obiektów dostarczonych przez system lub zdefiniowanych przez użytkownika. Obiekty dostarczone przez system, takie jak obiekty UserTransaction należące do JTA, przechowywane są w opcji kontekstu nazewnictwa środowiska java:comp/env. Platforma Javy EE pozwala komponentom na nazywanie obiektów zdefiniowanych przez użytkownika, takich jak ziarna EJB, elementy środowiska, obiekty DataSource należące do JDBC oraz połączenia do systemów komunikatów. Obiekt powinien być nazwany wewnątrz subkontekstu przestrzeni nazewnictwa, zgodnie ze swoim typem. Przykładowo ziarna EJB nazywane są wewnątrz subkontekstu java:comp/env/ejb, a referencje do obiektów JDBC DataSource — wewnątrz subkontekstu java:comp/env/jdbc.

JavaBeans Activation Framework JavaBeans Activation Framework (JAF) jest stosowany w API JavaMail. JAF dostarcza standardowe usługi pozwalające określić typ dowolnego fragmentu danych, enkapsulować dostęp do nich, odkryć możliwe do wykonania na nim operacje i utworzyć odpowiedni komponent JavaBeans, który ułatwi ich wykonanie.

Rozdział 1 y Przegląd technologii

47

API Javy EE 6 wchodzące w skład platformy Java Platform, Standard Edition 6 i 7

Java API for XML Processing Java API for XML Processing (JAXP), będące częścią platformy Java SE, obsługuje przetwarzanie dokumentów XML przy użyciu DOM (ang. Document Object Model), SAX (ang. Simple API for XML) i XSLT (ang. Extensible Stylesheet Language Transformation). JAXP pozwala aplikacjom analizować i transformować dokumenty XML niezależnie od konkretnej implementacji przetwarzania języka XML. W JAXP włączono również obsługę przestrzeni nazw (ang. namespace), co pozwala na pracę ze schematami, które mogłyby wywoływać konflikty nazw. JAXP powstało w celu zwiększenia elastyczności; pozwala na użycie różnych analizatorów zgodnych z językiem XML lub procesora XSL z kodu Twojej aplikacji, obsługuje schemat W3C (ang. Worldwide Web Consortium). Informacje o schemacie W3C znajdziesz pod adresem http://www.w3.org/XML/Schema.

Java Architecture for XML Binding Java Architecture for XML Binding (JAXB) zawiera wygodną metodę wiązania schematów XML z jego reprezentacją w programach w języku Java. JAXB może być wykorzystywany samodzielnie lub w połączeniu z JAX-WS, a wtedy dostarcza standardowe wiązania danych dla komunikatów usług sieciowych. API JAXB obsługiwane jest przez kontenery aplikacji klienckich Javy EE, kontenery webowe oraz kontenery EJB. Platforma Java EE 6 wymaga JAXB w wersji 2.2.

SOAP with Attachments API for Java SOAP with Attachments API for Java (SAAJ) jest niskopoziomowym API, na którym oparto JAX-WS. Pozwala na tworzenie i odczyt komunikatów zgodnych z specyfikacją protokołu SOAP 1.1 i 1.2 oraz z dokumentem SOAP with Attachments. Większość twórców aplikacji rezygnuje z użycia API SAAJ na rzecz wysokopoziomowego API oferowanego przez JAX-WS.

Java API for XML Web Services W specyfikacji Java API for XML Web Services (JAX-WS) zawarto obsługę usług sieciowych korzystających z API JAXB, by wiązać dane XML z obiektami Javy. Definiuje ona klienckie API dostępu do usług sieciowych oraz sposobów implementacji punktów dostępowych do usługi. Specyfikacje Implementing Enterprise Web Services, EJB oraz Java Servlet opisują wdrażanie opartych o JAX-WS usług i klientów. Wymagane jest, aby było możliwe wdrożenie aplikacji JAX-WS w oparciu o ten model. Specyfikacja JAX-WS opisuje obsługę handlerów przetwarzających komunikaty żądań i odpowiedzi. Handlery te wykonywane są w tym samym kontenerze, z tymi

48

Java EE 6. Zaawansowany przewodnik

Narzędzia serwera GlassFish

samymi uprawnieniami i tym samym kontekstem wykonywania, co klient lub komponent punktu dostępowego JAX-WS, z którymi są skojarzone. Handlery komunikatów mają dostęp do tej samej przestrzeni nazw JNDI (java:comp/env), co skojarzone z nimi komponenty. Niestandardowe serializery i deserializery, jeśli są obsługiwane, traktowane są tak samo jak handlery komunikatów. Platforma Java EE 6 wymaga JAX-WS w wersji 2.2.

Java Authentication And Authorization Service Java Authentication And Authorization Service (JAAS) wyposaża aplikacje JEE w metody do uwierzytelniania i autoryzacji określonych użytkowników i grup użytkowników, co umożliwi im wykonywanie operacji. JAAS jest wersją dla Javy standardowego frameworku Pluggable Authentication Module (PAM), który rozszerza architekturę zabezpieczeń platformy Javy i dodaje obsługę uwierzytelniania użytkowników.

Narzędzia serwera GlassFish Serwer GlassFish jest zgodną ze specyfikacją implementacją platformy Java EE 6. Poza obsługą wszystkich opisanych w poprzednich punktach API, serwer GlassFish zawiera wiele narzędzi Javy EE niebędących częścią specyfikacji platformy Java EE 6, które jednak są znacznym udogodnieniem dla twórców aplikacji. W tym podrozdziale podsumowujemy pokrótce narzędzia, które wchodzą w skład serwera GlassFish. Instrukcje dotyczące uruchamiania i zatrzymywania serwera GlassFish, uruchamiania konsoli administracyjnej oraz uruchamiania i zatrzymywania serwera Java DB znajdują się w rozdziale 2. W tabeli 1.1 zawarto spis narzędzi serwera GlassFish. Podstawowe informacje dotyczące użytkowania wielu z nich pojawiać się będą w dalszych częściach książki. Aby uzyskać szczegółowe informacje, sięgnij do pomocy online dostępnej przy użyciu graficznej konsoli administracyjnej. Tabela 1.1. Narzędzia serwera GlassFish Narzędzie

Opis

konsola administracyjna

Graficzne, przeglądarkowe narzędzie do administrowania serwerem GlassFish. Używane do zatrzymywania serwera, zarządzania użytkownikami, zasobami oraz aplikacjami.

asadmin

Narzędzie do administrowania serwerem GlassFish z wiersza poleceń. Używane do uruchamiania i zatrzymywania serwera, zarządzania użytkownikami, zasobami oraz aplikacjami.

appclient

Narzędzie wiersza poleceń uruchamiające kontener aplikacji klienckich oraz uruchamiające aplikację kliencką spakowaną w archiwum JAR.

Rozdział 1 y Przegląd technologii

49

Narzędzia serwera GlassFish

Tabela 1.1. Narzędzia serwera GlassFish — ciąg dalszy

50

Narzędzie

Opis

capture-schema

Narzędzie wiersza poleceń pozwalające na ekstrakcję informacji o schemacie z bazy danych, tworzące plik ze schematem, którego serwer GlassFish może użyć do zarządzania trwałością danych z poziomu kontenera.

package-appclient

Narzędzie pozwalające na spakowanie bibliotek kontenera aplikacji klienckich do archiwum JAR.

baza danych Java DB

Kopia serwera Java DB.

xjc

Narzędzie wiersza poleceń służące do przekształcania lub wiązania źródłowych schematów XML do zbioru klas JAXB języka Java.

schemagen

Narzędzie wiersza poleceń służące do generowania schematów XML dla każdej przestrzeni nazw, do których odnoszą się klasy napisanej aplikacji.

wsimport

Narzędzie wiersza poleceń służące do generowania przenośnych artefaktów JAX-WS z zadanego pliku WSDL. Artefakty te można następnie spakować do archiwum WAR wraz z plikiem WSDL, schematami oraz implementacją punktów dostępowych, a następnie wdrożyć.

wsgen

Narzędzie wiersza poleceń analizujące punkt dostępowy usługi i generujące wszystkie wymagane przenośne artefakty JAX-WS konieczne do wdrożenia i wywołania usługi sieciowej.

Java EE 6. Zaawansowany przewodnik

‹

‹

‹

2

ROZDZIAŁ 2

Używanie przykładowych aplikacji z samouczka

Tutaj zawarte zostały wszystkie informacje, jakie będą potrzebne, aby zainstalować, zbudować i uruchomić przykładowe aplikacje. W rozdziale: „ „ „ „ „ „ „ „

Wymagane oprogramowanie, Uruchamianie i zatrzymywanie serwera GlassFish, Uruchamianie konsoli administracyjnej, Uruchamianie i zatrzymywanie serwera Java DB, Budowanie przykładowych aplikacji, Struktura katalogów z przykładami samouczka, Pobieranie najnowszych aktualizacji samouczka, Debugowanie aplikacji Javy EE.

Wymagane oprogramowanie Uruchomienie przykładowych aplikacji, dostarczonych wraz z samouczkiem, wymaga posiadania oprogramowania opisanego w kolejnych punktach: „ „ „ „ „

Java Platform, Standard Edition, Java EE 6 Software Development Kit, Komponent samouczka Javy EE 6, NetBeans IDE, Apache Ant.

Java Platform, Standard Edition Do zbudowania, wdrożenia oraz uruchomienia przykładowych aplikacji niezbędne jest oprogramowanie Java Platform, Standard Edition 6.0 Development Kit (JDK 6) lub Java Platform, Standard Edition 7.0 Development Kit (JDK 7). Możesz je pobrać ze strony http://www.oracle.com/technetwork/java/javase/downloads/index.html.

Wymagane oprogramowanie

Pobierz aktualną wersję JDK, która nie zawiera żadnego oprogramowania dodatkowego, na przykład NetBeans IDE lub Java EE SDK.

Java EE 6 Software Development Kit Serwer GlassFish Server Open Source Edition 3.1.2 jest docelowym środowiskiem budowania i uruchamiania przykładów z tej książki. Aby zbudować, wdrożyć i uruchomić przykładowe aplikacje, musisz zainstalować serwer GlassFish i — opcjonalnie — środowisko programistyczne NetBeans IDE. Serwer GlassFish instalowany jest razem z oprogramowaniem Java EE Software Development Kit (SDK), które możesz pobrać ze strony http://www.oracle.com/technetwork/java/javaee/downloads/index.html. Upewnij się, że wybrałeś oprogramowanie Java EE 6 SDK, a nie Java EE 6 SDK Web Profile.

Instalacja SDK — porady Podczas instalacji SDK wykonaj następujące czynności: „

„

„

„

pozwól instalatorowi na pobranie i skonfigurowanie narzędzia aktualizacji Update Tool, jeśli uzyskujesz dostęp do internetu poprzez zaporę sieciową (ang. firewall), podaj serwer proxy i port; skonfiguruj nazwę użytkownika administracyjnego serwera GlassFish jako admin i nie podawaj dla niego hasła — są to wartości domyślne; zaakceptuj domyślnie ustawione wartości portu administracyjnego (ang. Admin Port, wartość 4848) i portu HTTP (ang. HTTP Port, wartość 8080); nie zaznaczaj opcji utworzenia usługi systemowej dla domeny.

Opcję uruchomienia domeny po jej utworzeniu można pozostawić włączoną, ale nie jest to wymagane. Samouczek odnosi się do lokalizacji as-install-parent, czyli katalogu, w którym został zainstalowany serwer GlassFish. Przykładowo w systemie Microsoft Windows domyślnym katalogiem instalacji jest C:\glassfish3, dlatego też domyślnie as-install-parent odwoływać się będzie do tego właśnie katalogu. Sam serwer GlassFish zainstalowany jest w katalogu o nazwie as-install, czyli podkatalogu glassfish w katalogu as-install-parent. Tak więc domyślnie w systemie Microsoft Windows as-install odnosi się do katalogu C:\glassfish3\glassfish. Po zainstalowaniu serwera GlassFish dodaj poniższe katalogi do zmiennej środowiskowej PATH w celu uniknięcia podawania za każdym razem pełnej ścieżki w linii poleceń: as-install-parent/bin as-install/bin

52

Java EE 6. Zaawansowany przewodnik

Wymagane oprogramowanie

Komponent samouczka Javy EE 6 Pliki źródłowe przykładowych aplikacji opisanych w tym samouczku zawarte są w komponencie samouczka Javy EE 6, który można pobrać za pomocą narzędzia aktualizacji Update Tool1.

T Pozyskiwanie komponentu samouczka

przy użyciu narzędzia Update Tool 1

Uruchom narzędzie Update Tool: „ „

w linii poleceń uruchom narzędzie updatetool, w systemie Windows uruchom Start/Wszystkie programy/Java EE 6 SDK/Start Update Tool.

2

Rozwiń węzeł Java EE 6 SDK.

3

Kliknij węzeł Available Updates.

4

Z listy wybierz element Java EE 6 Tutorial, zaznaczając jego pole wyboru.

5

Kliknij przycisk Install.

6

Zaakceptuj postanowienia licencyjne.

Po zakończeniu instalacji samouczek Javy EE 6 pojawi się na liście zainstalowanych komponentów. Został zainstalowany w katalogu as-install/docs/javaee-tutorial i zawiera dwa podkatalogi: docs oraz examples. W katalogu examples znajdują się podkatalogi dotyczące każdej technologii opisywanej w tym samouczku. Kolejne kroki

Aktualizacje samouczka Javy EE 6 są publikowane okresowo. Więcej informacji na temat aktualizacji samouczka znajdziesz w tym rozdziale, w podrozdziale „Pobieranie najnowszych aktualizacji samouczka”.

NetBeans IDE Zintegrowane środowisko programistyczne NetBeans IDE (ang. Integrated Development Environment) jest darmowym, otwartym IDE służącym do tworzenia aplikacji w Javie, w tym także aplikacji typu enterprise. NetBeans IDE obsługuje platformę Javy EE. Z jego pomocą możesz budować, pakować, wdrażać oraz uruchamiać przykładowe aplikacje tego samouczka. Do uruchomienia przykładów samouczka potrzebować będziesz najnowszej wersji NetBeans IDE, którą pobrać możesz ze strony http://netbeans.org/downloads/ index.html. Pamiętaj, by wybrać wersję przygotowaną pod kątem Javy EE.

1

Spolonizowanych dla wygody czytelnika kodów dostępnych na stronie internetowej książki (www.helion.pl/...) nie można pobrać w ten sposób — przyp. red.

Rozdział 2 y Używanie przykładowych aplikacji z samouczka

53

Wymagane oprogramowanie

T Instalacja NetBeans IDE bez serwera GlassFish Instalując środowisko programistyczne NetBeans IDE, nie instaluj wersji serwera GlassFish dystrybuowanej wraz z nim. Aby pominąć instalację serwera, wykonaj następujące czynności. 1

Na pierwszym ekranie usuń zaznaczenie opcji instalacji serwera GlassFish Server i kliknij przycisk OK.

Zaakceptuj standardowe postanowienia licencyjne i postanowienia dotyczące biblioteki Junit. 2

Kilka ćwiczeń wykorzystuje bibliotekę Junit, więc powinieneś ją zainstalować.

3

Kontynuuj instalację środowiska NetBeans IDE.

T Dodanie serwera GlassFish

do serwerów środowiska NetBeans IDE Gdy chcesz uruchomić przykłady samouczka w środowisku NetBeans IDE, musisz dodać do jego listy serwerów zainstalowany uprzednio serwer GlassFish. Wykonaj zatem zamieszczone poniżej instrukcje. 1

W uruchomionym środowisku NetBeans IDE wybierz Tools/Servers.

Otworzy się kreator Servers. 2

Kliknij przycisk dodawania serwera (Add Server).

3

Z listy Choose Server wybierz GlassFish Server 3+ i kliknij przycisk Next.

4

W polu Installation Location podaj lokalizację Java EE 6 SDK i kliknij przycisk Next.

5

Na ekranie Domain Location wybierz opcję Register Local Domain, aby zarejestrować lokalną domenę.

6

Kliknij przycisk Finish.

Apache Ant Rozwijany przez Apache Software Foundation (http://ant.apache.org/) Ant jest opartym na technologii Java narzędziem do tworzenia kodu źródłowego używanym do budowania, pakowania i wdrażania przykładów w tym samouczku. Do uruchomienia przykładów potrzebować będziesz narzędzia Ant w wersji 1.7.1. Jeśli jeszcze nie posiadasz tego narzędzia, możesz zainstalować je przy użyciu narzędzia Update Tool będącego częścią serwera GlassFish.

T Pozyskiwanie narzędzia Apache Ant 1

Uruchom narzędzie Update Tool: „

54

w linii poleceń uruchom narzędzie updatetool,

Java EE 6. Zaawansowany przewodnik

Uruchamianie i zatrzymywanie serwera GlassFish

„

w systemie Windows uruchom Start/Wszystkie programy/Java EE 6 SDK/Start Update Tool.

2

Rozwiń węzeł Java EE 6 SDK.

3

Wejdź w węzeł Available Add-ons.

4

Z listy wybierz element Apache Ant Build Tool, zaznaczając jego pole wyboru.

5

Kliknij przycisk Install.

6

Zaakceptuj postanowienia licencyjne.

Po zakończeniu instalacji Apache Ant pojawi się na liście zainstalowanych komponentów. Narzędzie zostało zainstalowane w katalogu o nazwie as-install-parent/ant. Kolejne kroki

Aby użyć polecenia ant z linii poleceń, dodaj ścieżkę do katalogu as-install-path/ ant/bin do zmiennej środowiskowej PATH.

Uruchamianie i zatrzymywanie serwera GlassFish Gdy chcesz uruchomić serwer GlassFish, otwórz okno terminalu lub wiersza poleceń i wykonaj polecenie: asadmin start-domain --verbose

Domena to jedna lub więcej instancji serwera GlassFish zarządzanych przez jeden serwer administracyjny. Z domeną związane są: „ „ „

numer portu serwera GlassFish; domyślnie jest to port 8080, numer portu konsoli administracyjnej serwera; domyślnie jest to port 4848, nazwa i hasło użytkownika administracyjnego; domyślna nazwa użytkownika to admin i domyślnie hasło nie jest wymagane.

Wartości te podaje się podczas instalacji serwera GlassFish. W przykładach opisanych w tym samouczku założono, że pozostawiono domyślne porty. Opcja start-domain wywołana bez argumentów uruchomi domyślną domenę, którą jest domena domain1. Flaga --verbose powoduje, że wszystkie logi oraz wyjście debugowania pojawiać się będą w oknie terminalu bądź linii poleceń. Wyjście jest również zapisywane w logach serwera, które znajdują się w pliku domain-dir/logs/server.log. Alternatywnie, w systemie Windows wybierz Start/Wszystkie Programy/Java EE 6 SDK/Start Application Server. Aby zatrzymać serwer GlassFish, otwórz okno terminalu lub wiersza poleceń i wykonaj polecenie: asadmin stop-domain domain1

Rozdział 2 y Używanie przykładowych aplikacji z samouczka

55

Uruchamianie konsoli administracyjnej

Alternatywnie, w systemie Windows wybierz Start/Wszystkie Programy/ Java EE 6 SDK/Stop Application Server.

T Uruchamianie serwera GlassFish

z poziomu środowiska NetBeans IDE 1

Kliknij zakładkę Services.

2

Rozwiń węzeł Servers.

3

Prawym przyciskiem myszy kliknij GlassFish Server i wybierz z menu polecenie Start.

Następne kroki Aby zatrzymać serwer GlassFish z poziomu środowiska NetBeans IDE, kliknij prawym przyciskiem myszy GlassFish Server i wybierz polecenie Stop.

Uruchamianie konsoli administracyjnej Narzędzie konsoli administracyjnej używane jest do administrowania serwerem GlassFish oraz zarządzania użytkownikami, zasobami i aplikacjami Javy EE. Konsolę administracyjną można wywołać tylko na działającym serwerze GlassFish. Gdy chcesz ją uruchomić, otwórz przeglądarkę internetową i wpisz adres http://localhost:4848/. Alternatywnie, w systemie Windows wybierz Start/Wszystkie Programy/ Java EE 6 SDK/Administration Console.

T Uruchamianie konsoli administracyjnej

w środowisku NetBeans IDE 1

Kliknij zakładkę Services.

2

Rozwiń węzeł Servers.

3

Kliknij prawym przyciskiem myszy instancję serwera GlassFish i wybierz z menu polecenie View Domain Admin Console. UWAGA Środowisko NetBeans IDE użyje do otwarcia konsoli administracyjnej

Twojej domyślnej przeglądarki.

Uruchamianie i zatrzymywanie serwera Java DB Serwer GlassFish zawiera serwer bazy danych Java DB. Aby uruchomić serwer Java DB, otwórz okno terminalu lub wiersza poleceń i wykonaj polecenie: asadmin start-database

56

Java EE 6. Zaawansowany przewodnik

Budowanie przykładowych aplikacji

Aby zatrzymać serwer Java DB, otwórz okno terminalu lub wiersza poleceń i wykonaj polecenie: asadmin stop-database

Więcej informacji dotyczących serwera Java DB wbudowanego serwer GlassFish znajdziesz na stronie http://www.oracle.com/technetwork/java/javadb/overview/ index.html.

T Uruchamianie serwera bazy danych

przy użyciu środowiska NetBeans IDE Uruchomienie serwera GlassFish z poziomu środowiska NetBeans IDE powoduje automatyczne uruchomienie bazy danych. Jeśli jednak chcesz ją uruchomić ręcznie, wykonaj poniższe kroki. 1

Kliknij zakładkę Services.

2

Rozwiń węzeł Databases.

3

Kliknij prawym przyciskiem myszy węzeł Java DB i wybierz z menu polecenie Start Server.

Kolejne kroki

Aby zatrzymać serwer bazy danych przy użyciu środowiska NetBeans IDE, kliknij prawym przyciskiem myszy węzeł Java DB i wybierz z menu opcję Stop Server.

Budowanie przykładowych aplikacji Przykładowe aplikacje tego samouczka dystrybuowane są razem z plikami konfiguracyjnymi środowiska NetBeans IDE i narzędzia Ant. Do budowania, pakowania, wdrażania i uruchamiania przykładów można użyć dowolnego z tych narzędzi. Instrukcje dotyczące budowania przykładów zawarte zostały w poszczególnych rozdziałach.

Struktura katalogów z przykładami samouczka Aby ułatwić iteracyjny rozwój aplikacji i trzymać ich źródła oraz skompilowane pliki oddzielnie, w przykładowych aplikacjach samouczka zastosowano strukturę katalogów Java BluePrints. Każdy moduł aplikacji ma następującą strukturę: „ „ „

„

build.xml — plik budowania Ant, src/java — katalog zawierający kody źródłowe modułu aplikacji języka Java, src/conf — katalog zawierający pliki konfiguracyjne modułu, z wyłączeniem aplikacji internetowych, web — katalog zawierający strony internetowe, arkusze stylów, znaczniki i obrazy (tylko aplikacje internetowe),

Rozdział 2 y Używanie przykładowych aplikacji z samouczka

57

Pobieranie najnowszych aktualizacji samouczka

„

„

web/WEB-INF — katalog zawierający pliki konfiguracyjne aplikacji internetowych (tylko aplikacje internetowe), nbproject — katalog zawierający pliki projektu środowiska NetBeans IDE.

Przykłady składające się z wielu modułów pakowanych w archiwum EAR zawierają podkatalogi dla każdego modułu nazywane zgodnie z poniższą konwencją: „

nazwa-przykładu-app — aplikacje klienckie,

„

nazwa-przykładu-ejb — moduły EJB pakowane do archiwów EJB JAR,

„

nazwa-przykładu-war — aplikacje internetowe.

Pliki budowania narzędzia Ant (build.xml) dystrybuowane razem z przykładami zawierają cele (ang. targets) pozwalające na tworzenie podkatalogów: „ „ „

build oraz skopiowanie i zbudowanie w nim plików, dist, który zawiera spakowany plik modułu, client-jar, który zawiera spakowaną w archiwum JAR aplikację kliencką.

Folder tut-install/examples/bp-project/ zawiera dodatkowe cele wykorzystywane przez cele zawarte w pliku build.xml. W niektórych przykładach cel Ant otworzy przykładowy adres URL w domyślnej przeglądarce internetowej (o ile jest dostępna). W systemie Windows stanie się to automatycznie. W systemach typu UNIX najprawdopodobniej konieczna będzie modyfikacja pliku tut-install/examples/bp-project/build.properties. Usuń znak komentarza z wiersza zawierającego właściwość default.browser i określ ścieżkę do pliku wykonywalnego przeglądarki internetowej. Bez tego dodatkowego kroku konieczne będzie samodzielne otwarcie adresu URL w przeglądarce internetowej.

Pobieranie najnowszych aktualizacji samouczka Aby sprawdzić dostępne aktualizacje samouczka, użyj narzędzia aktualizacji Update Tool będącego częścią Java EE 6 SDK.

T Aktualizacja samouczka za pomocą centrum aktualizacji

58

1

W środowisku NetBeans IDE kliknij zakładkę Services i rozwiń w niej węzeł Servers.

2

Kliknij prawym przyciskiem myszy węzeł GlassFish Server 3+ i wybierz z menu polecenie View Update Center, aby wyświetlić narzędzie aktualizacji Update Tool.

3

Z drzewa wybierz węzeł Available Updates, aby wyświetlić listę zaktualizowanych pakietów.

4

Poszukaj aktualizacji dla pakietu samouczka Java EE 6 Tutorial (javaee-tutorial).

5

Jeśli pojawiła się nowa aktualizacja samouczka, wybierz ją i kliknij przycisk Install.

Java EE 6. Zaawansowany przewodnik

Debugowanie aplikacji Javy EE

Debugowanie aplikacji Javy EE W tym podrozdziale wyjaśniono, w jaki sposób odkryć źródło błędu występującego podczas wdrożenia lub działania aplikacji.

Używanie logów serwera Jednym ze sposobów debugowania aplikacji jest przejrzenie logów serwera zawartych w katalogu o nazwie domain-dir/logs/server.log. Znajdziesz tam wiadomości zgłaszane przez serwer GlassFish i Twoje aplikacje. W swojej aplikacji możesz logować wiadomości z dowolnej klasy Javy, przy użyciu polecenia System.out. ´println lub Java Logging API (dokumentacja na stronie http://docs.oracle.com/ javase/6/docs/technotes/guides/logging/index.html), oraz komponentów webowych za pomocą metody ServerContext.log. Jeśli korzystasz z środowiska NetBeans IDE, komunikaty będą pojawiły się w logach serwera i w oknie Output. Uruchomienie serwera GlassFish z flagą --verbose skutkować będzie pojawieniem się wszystkich komunikatów logowania i debugowania zarówno w oknie terminalu lub wiersza poleceń, jak i w logach serwera. Jeśli uruchomisz serwer GlassFish w tle, komunikaty debugowania pojawiać się będą tylko w logach serwera. Zawartość logów serwera możesz przeglądać za pomocą edytora tekstu lub przeglądarki logów dostępnej w konsoli administracyjnej serwera.

T Używanie przeglądarki logów 1

Wybierz węzeł GlassFish Server.

2

Kliknij przycisk View Log Files.

3

Otwarte zostaną logi serwera; zobaczysz 40 ostatnich wpisów.

4

Aby zobaczyć pozostałe wpisy, wykonaj poniższe instrukcje. a. Kliknij łącze Modify Search. b. Podaj dowolne kryteria, które spełniać mają wyszukiwane wiadomości. c. Wciśnij przycisk Search znajdujący się na górze przeglądarki logów.

Używanie debuggera Serwer GlassFish obsługuje architekturę debuggera platformy Java (ang. Java Platform Debugger Architecture, w skrócie JPDA). Za pomocą JPDA możesz skonfigurować serwer GlassFish do wystawiania informacji o debugowaniu przy użyciu gniazdka sieciowego (ang. socket).

Rozdział 2 y Używanie przykładowych aplikacji z samouczka

59

Debugowanie aplikacji Javy EE

T Debugowanie aplikacji przy użyciu debuggera 1

Z wykorzystaniem konsoli administracyjnej włącz debugowanie w serwerze GlassFish. a. W węźle Configurations wybierz węzeł server-config. b. Wybierz opcję JVM Settings. Domyślne ustawienia debugowania wyglądają następująco: -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9009

Jak widzisz, domyślny port debuggera to 9009. Możesz zmienić tę wartość na wolny port, niezajęty przez serwer GlassFish czy inne usługi. c. Zaznacz pole wyboru Debug Enabled. d. Kliknij przycisk Save. 2

60

Zatrzymaj i uruchom ponownie serwer GlassFish.

Java EE 6. Zaawansowany przewodnik

CZĘŚĆ II

Warstwa webowa Część II dotyczy zaawansowanej tematyki warstwy webowej. Składa się z następujących rozdziałów: „ „

„ „ „ „ „

Rozdział 3., „Technologia JavaServer Faces — tematy zaawansowane” Rozdział 4., „Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces” Rozdział 5., „Komponenty złożone — tematy zaawansowane i przykłady” Rozdział 6., „Tworzenie własnych komponentów UI i innych obiektów” Rozdział 7., „Konfiguracja aplikacji JavaServer Faces” Rozdział 8., „Przesył plików do serwera w technologii Java Servlet” Rozdział 9., „Umiędzynarodowienie i lokalizacja aplikacji webowych”

‹

‹

‹

3

ROZDZIAŁ 3

Technologia JavaServer Faces — tematy zaawansowane

W książce Java EE 6. Przewodnik. Wydanie IV przedstawione zostały podstawy technologii JavaServer Faces oraz faceletów, czyli zalecanej warstwy prezentacji dla platformy Javy EE. W tym i kolejnych rozdziałach opisujemy zaawansowane zagadnienia wspomnianej technologii. „

„

„

„

„

W tym rozdziale w szczegółowy sposób omawiamy cykl życia elementów technologii JavaServer Faces. W niektórych bardziej zaawansowanych aplikacjach zastosowano dobrze zdefiniowane fazy cyklu życia, by dostosować ich zachowanie do ściśle określonych wymagań. W rozdziale 4., „Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces”, wprowadzamy pojęcie technologii Ajax, a także opisujemy sposoby jej wykorzystania w aplikacjach korzystających z JavaServer Faces. W rozdziale 5., „Komponenty złożone — tematy zaawansowane i przykłady”, omawiamy zaawansowane funkcje komponentów złożonych. W rozdziale 6., „Tworzenie własnych komponentów UI i innych obiektów”, opisujemy sposoby tworzenia od podstaw nowych komponentów, rendererów konwerterów, elementów nasłuchujących i walidatorów. W rozdziale 7., „Konfiguracja aplikacji JavaServer Faces”, objaśniamy proces tworzenia i wdrażania aplikacji JavaServer Faces, wykorzystanie różnych plików konfiguracyjnych, a także strukturę wdrożeń.

W rozdziale: „ „ „ „

Cykl życia aplikacji JavaServer Faces, Częściowe przetwarzanie i rendering, Cykl życia aplikacji faceletów, Model komponentów interfejsu użytkownika.

Cykl życia aplikacji JavaServer Faces Cykl życia aplikacji odnosi się do różnych stanów przetwarzania tej konkretnej aplikacji, od momentu inicjalizacji aż po jej zakończenie. Cykle życia związane są z każdą aplikacją. W trakcie cyklu życia aplikacji internetowej wyróżnić można kilka typowych zadań:

Cykl życia aplikacji JavaServer Faces

„ „ „ „

obsługę nadchodzących żądań, dekodowanie parametrów, modyfikację i zapis stanu, przekazanie kodu, który posłuży przeglądarce do zrenderowania strony WWW.

Framework aplikacji JavaServer Faces automatycznie zarządza fazami cyklu życia prostych aplikacji, ale dopuszcza zarządzanie nimi przez programistę złożonej aplikacji, gdy zajdzie taka konieczność. Aplikacje JavaServer Faces wykorzystujące zaawansowane funkcje systemu mogą wymagać interakcji z cyklem życia w ściśle określonych fazach. Przykładem mogą być aplikacje wykorzystujące technologię Ajax, w których użyto funkcji przetwarzania częściowego cyklu życia. Lepsze zrozumienie poszczególnych faz cyklu życia to klucz do tworzenia dobrze zaprojektowanych komponentów. Uproszczony widok cyklu życia JavaServer Faces, składający się z dwóch głównych faz aplikacji internetowej JavaServer Faces, został przedstawiony w podrozdziale „Cykl życia aplikacji hello”, w książce Java EE 6. Przewodnik. Wydanie IV. W tym podrozdziale przyjrzymy się cyklowi życia JavaServer Faces nieco dokładniej.

Omówienie cyklu życia JavaServer Faces Cykl życia aplikacji JavaServer Faces rozpoczyna się wraz z wykonaniem przez klienta żądania HTTP strony WWW, a kończy się, gdy serwer odpowie, wysyłając stronę przetłumaczoną na język HTML. Cykl życia można podzielić na dwie główne fazy: wykonanie i rendering. Fazę wykonania można dodatkowo podzielić na podfazy dotyczące obsługi złożonego drzewa komponentów. Struktura wymaga konwersji i weryfikacji danych komponentów, obsługi zdarzeń komponentów i przekazania danych komponentów do ziaren w odpowiedniej kolejności. Stronę JavaServer Faces reprezentuje drzewo komponentów nazywane widokiem. W trakcie cyklu życia implementacja JavaServer Faces musi utworzyć widok, biorąc pod uwagę stan zapamiętany przez poprzednie odpowiedzi dotyczące strony. Gdy klient zażąda strony, implementacja JavaServer Faces wykonuje kilka zadań, na przykład sprawdza dane wejściowe komponentów widoku i konwertuje te dane do typów wskazanych po stronie serwerowej. Implementacja JavaServer Faces przeprowadza wszystkie zadania jako serię kroków w trakcie cyklu życia żądanie-odpowiedź. Na rysunku 3.1 przedstawiamy omawiane kroki. Cykl życia żądanie-odpowiedź obsługuje dwa rodzaje żądań, czyli żądanie początkowe i zwrotne. Żądanie początkowe występuje, gdy użytkownik wykonuje żądanie dotyczące danej strony po raz pierwszy. Żądanie zwrotne ma miejsce, gdy użytkownik przesyła z powrotem do serwera dane dotyczące formularza znajdującego się na stronie pobranej przez przeglądarkę w trakcie żądania początkowego.

64

Java EE 6. Zaawansowany przewodnik

Cykl życia aplikacji JavaServer Faces

Rysunek 3.1. Standardowy cykl życia żądanie-odpowiedź dla JavaServer Faces

Gdy cykl życia obsługuje żądania początkowe, wykonuje jedynie fazy przywrócenia widoku i renderingu odpowiedzi, ponieważ użytkownik nie przekazał żadnych dodatkowych danych ani akcji do przetworzenia. Z drugiej strony, w przypadku żądania zwrotnego cykl życia wykonuje wszystkie zaprezentowane fazy. Najczęściej pierwsze żądanie strony JavaServer Faces jest efektem akcji wykonanej przez klienta, na przykład wynika z kliknięcia łącza lub komponentu przycisku na innej stronie JavaServer Faces. Aby zrenderować odpowiedź, która stanowi inną stronę JavaServer Faces, aplikacja tworzy nowy widok i zapamiętuje go

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

65

Cykl życia aplikacji JavaServer Faces

w instancji javax.faces.context.FacesContext, która reprezentuje wszystkie informacje związane z przetwarzaniem nadchodzącego żądania i utworzeniem odpowiedzi. Następnie aplikacja pobiera referencje do obiektów niezbędnych dla widoku i wywołuje metodę FacesContext.renderResponse, która wymusza natychmiastowy rendering widoku poprzez przeskoczenie do fazy renderowania odpowiedzi cyklu życia, co doskonale obrazują strzałki z napisem „Rendering odpowiedzi”. Czasem aplikacja musi przekierować użytkownika do zasobu innej aplikacji internetowej (na przykład usługi sieciowej) lub wygenerować odpowiedź, która nie zawiera komponentów JavaServer Faces. W takiej sytuacji programista musi pominąć fazę renderowania odpowiedzi, wywołując metodę FacesContext. ´responseComplete. Na diagramie zobrazowano również tę sytuację, stosując strzałki z napisem „Odpowiedź zakończona”. Najczęściej dochodzi do sytuacji, w których komponent JavaServer Faces wysyła żądanie pobrania innej strony JavaServer Faces. W takiej sytuacji implementacja JavaServer Faces obsługuje żądanie i automatycznie realizuje fazy cyklu życia, by przeprowadzić niezbędne konwersje, walidacje i aktualizacje modelu, a także wygenerować odpowiedź. Istnieje jeden wyjątek dotyczący cyklu życia opisanego w tym podrozdziale. Gdy atrybut immediate komponentu ma wartość prawda (true), walidacja, konwersja i zdarzenia powiązane z tym komponentem są przetwarzane w trakcie fazy zastosowania wartości zapytania, a nie w trakcie dalszych faz. Szczegóły cyklu życia wyjaśniane w kolejnych punktach będą interesowały przede wszystkim programistów, który muszą dowiedzieć się, kiedy standardowo obsługiwane są walidacje, konwersje i zdarzenia, a także w jaki sposób wykonać zmiany w przetwarzaniu. Więcej informacji na temat poszczególnych faz cyklu życia uzyskasz, pobierając najnowszą dokumentację specyfikacji JavaServer Faces dostępną pod adresem http://jcp.org/en/jsr/detail?id=314. Faza wykonania cyklu życia aplikacji JavaServer Faces składa się z podfaz (są to także tytuły kolejnych punktów). Oto one. „ „ „ „ „ „

Faza przywrócenia widoku, Faza zastosowania wartości zapytania, Faza przetwarzania walidacji, Faza aktualizacji wartości modelu, Faza wywołania aplikacji, Faza renderowania odpowiedzi.

Faza przywrócenia widoku Kiedy wykonane zostaje żądanie strony JavaServer Faces — najczęściej z powodu kliknięcia łącza lub komponentu przycisku — implementacja JavaServer Faces rozpoczyna fazę przywracania widoku.

66

Java EE 6. Zaawansowany przewodnik

Cykl życia aplikacji JavaServer Faces

W trakcie tej fazy implementacja tworzy widok strony, podłącza procedury obsługi zdarzeń oraz walidatory do komponentów i zapisuje widok w instancji FacesContext, która zawiera wszystkie informacje niezbędne do przetworzenia pojedynczego żądania. Wszystkie komponenty aplikacji, procedury obsługi zdarzeń, konwertery i walidatory mają dostęp do instancji FacesContext. Jeśli żądanie strony jest żądaniem początkowym, implementacja JavaServer Faces w trakcie tej fazy tworzy pusty widok i cykl życia przechodzi do fazy renderowania odpowiedzi, w jakiej pusty widok wypełniają komponenty, do których odnoszą się znaczniki umieszczone na stronie. Jeśli żądanie jest typu zwrotnego, widok dotyczący strony istnieje już wewnątrz instancji FacesContext. W trakcie tej fazy implementacja JavaServer Faces przywraca widok, wykorzystując informacje zapisane u klienta lub po stronie serwera.

Faza zastosowania wartości zapytania Po przywróceniu drzewa komponentów w trakcie żądania zwrotnego każdy z komponentów znajdujących się w drzewie wydobywa nowe wartości z parametrów żądania przy użyciu odpowiedniej metody dekodującej (processDecodes()). Wartość zostaje zapamiętana lokalnie wewnątrz każdego z komponentów. Jeśli którakolwiek z metod dekodujących lub procedur obsługi zdarzeń wywołała metodę renderResponse dla aktualnej instancji FacesContext, implementacja JavaServer Faces przechodzi od razu do fazy renderowania odpowiedzi. Jeżeli w trakcie tej fazy zakolejkowano zdarzenia, implementacja przekazuje je zainteresowanym procedurom nasłuchującym. Jeśli niektóre komponenty na stronie zawierają atrybuty immediate (patrz „Wspólne atrybuty znaczników komponentów” w książce Java EE 6. Przewodnik. Wydanie IV) ustawione na wartość true, walidatory, konwersje i zdarzenia powiązane z tymi komponentami zostaną wykonane w trakcie tej fazy. Jeżeli którakolwiek z konwersji nie powiedzie się, zostanie wygenerowany komunikat błędu powiązany z komponentem, który trafi do kolejki w obiekcie FacesContext. Faza renderingu odpowiedzi wyświetli go użytkownikowi wraz z innymi błędami walidacji wynikającymi z przeprowadzenia fazy walidacyjnej. W tym momencie, jeśli aplikacja musi przekierować użytkownika do zasobu innej aplikacji internetowej lub wygenerować odpowiedź, która nie zawiera komponentów JavaServer Faces, wywołuje metodę FacesContext.responseComplete. Po zakończeniu fazy komponenty zawierają nowe wartości, a komunikaty i zdarzenia są zakolejkowane. Jeśli aktualne żądanie zostanie zidentyfikowane jako żądanie częściowe, implementacja pobierze kontekst częściowy z FacesContext i użyje metody przetwarzania fragmentów.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

67

Cykl życia aplikacji JavaServer Faces

Faza przetwarzania walidacji W trakcie tej fazy implementacja JavaServer Faces, wykorzystując metody validate (processValidators), przetwarza wszystkie walidatory zarejestrowane dla komponentów umieszczonych w drzewie. Sprawdza atrybuty komponentów określające reguły walidacji i porównuje je z lokalnymi wartościami zapisanymi w poszczególnych komponentach. Implementacja wykonuje również konwersję komponentów z danymi wejściowymi, które nie posiadały atrybutu immediate ustawionego na wartość true. Jeżeli lokalna wartość jest nieprawidłowa lub gdy jakakolwiek konwersja nie powiedzie się, implementacja JavaServer Faces dodaje komunikat błędu do instancji FacesContext i cykl życia przechodzi od razu do fazy renderowania odpowiedzi. W ten sposób strona zostaje zrenderowana ponownie wraz z informacjami o błędach. Co istotne, na stronie pojawią się również błędy konwersji wykryte w fazie zastosowania wartości zapytania. Jeśli którakolwiek z metod walidujących lub procedur obsługi zdarzeń wywołała metodę renderResponse dla aktualnej instancji FacesContext, implementacja JavaServer Faces przechodzi od razu do fazy renderowania odpowiedzi. Jeśli w tym momencie aplikacja musi przekierować użytkownika do zasobu innej aplikacji internetowej lub wygenerować odpowiedź, która nie zawiera komponentów JavaServer Faces, wywołuje metodę FacesContext.responseComplete. Jeżeli w trakcie wykonywania tej fazy zostaną zakolejkowane zdarzenia, implementacja JavaServer Faces wywoła zainteresowane nimi procedury obsługi. Jeśli aktualne żądanie zostanie zidentyfikowane jako żądanie częściowe, implementacja pobierze kontekst częściowy z FacesContext i użyje metody przetwarzania fragmentów.

Faza aktualizacji wartości modelu Gdy implementacja JavaServer Faces stwierdzi, że dane są poprawne, przechodzi przez drzewo komponentów i ustawia właściwości odpowiednich obiektów po stronie serwera na lokalne wartości komponentów. Implementacja aktualizuje jedynie właściwości ziaren wskazane przez atrybuty komponentów wejściowych. Jeżeli lokalne dane nie mogą zostać skonwertowane do typów wskazanych we właściwościach ziaren, cykl życia przechodzi automatycznie do fazy renderowania odpowiedzi, by użytkownik od razu otrzymał ponownie zrenderowaną stronę wraz z informacją o błędach. Przypomina to sytuację, która zachodzi w przypadku błędów walidacji. Jeśli którakolwiek z metod updateModels lub procedur obsługi zdarzeń wywołała metodę renderResponse dla aktualnej instancji FacesContext, implementacja JavaServer Faces przechodzi od razu do fazy renderowania odpowiedzi.

68

Java EE 6. Zaawansowany przewodnik

Cykl życia aplikacji JavaServer Faces

Jeśli w tym momencie aplikacja musi przekierować użytkownika do zasobu innej aplikacji internetowej lub wygenerować odpowiedź, która nie zawiera komponentów JavaServer Faces, wywołuje metodę FacesContext.responseComplete. Jeżeli w trakcie wykonywania tej fazy zostaną zakolejkowane zdarzenia, implementacja JavaServer Faces wywoła zainteresowane nimi procedury obsługi. Jeśli aktualne żądanie zostanie zidentyfikowane jako żądanie częściowe, implementacja pobierze kontekst częściowy z FacesContext i użyje metody przetwarzania fragmentów.

Faza wywołania aplikacji W trakcie tej fazy implementacja JavaServer Faces obsługuje wszystkie zdarzenia poziomu aplikacji, na przykład wysłanie formularza lub przejście do innej strony. Jeśli którakolwiek z metod updateModels lub procedur obsługi zdarzeń wywołała metodę renderResponse dla aktualnej instancji FacesContext, implementacja JavaServer Faces przechodzi od razu do fazy renderowania odpowiedzi. Jeżeli aktualnie przetwarzany widok powstał na podstawie informacji o stanie z poprzedniego żądania i komponent zgłosił zdarzenie, dla tych zdarzeń wywołane zostaną odpowiednie procedury obsługi. Na końcu implementacja JavaServer Faces przekaże sterowanie do fazy renderowania odpowiedzi.

Faza renderowania odpowiedzi W trakcie tej fazy implementacja JavaServer Faces tworzy widok i deleguje odpowiedzialność na odpowiednie zasoby, których zadaniem jest właściwe zrenderowanie strony. Jeśli mamy do czynienia z żądaniem początkowym, komponenty znajdujące się na stronie trafią do drzewa komponentów. Jeżeli nie jest to żądanie początkowe, komponenty znajdują się już w drzewie i nie trzeba ich ponownie dodawać. Jeżeli żądanie jest typu zwrotnego i natrafiono na błędy w trakcie wykonywania faz stosowania wartości zapytania, wykonywania walidacji lub aktualizacji wartości modeli, ponownie renderowana jest oryginalna strona. Jeśli strona zawiera znaczniki h:message lub h:messages, wyświetlone zostaną wszystkie zakolejkowane komunikaty o błędach. Po zrenderowaniu treści widoku stan odpowiedzi zostaje zapisany, by miały do niego dostęp kolejne żądania. Zapisany stan jest ponownie dostępny w fazie przywracania widoku.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

69

Częściowe przetwarzanie i rendering

Częściowe przetwarzanie i rendering Cykl życia JavaServer Faces dotyczy wszystkich procesów wykonania i renderingu aplikacji. Istnieje możliwość przetworzenia lub zrenderowania jedynie fragmentu aplikacji, na przykład pojedynczego komponentu. Przykładem jest framework Ajax dotyczący JavaServer Faces, potrafiący generować żądania zawierające informacje, dzięki którym wybrany komponent będzie przetwarzany, renderowany i przesyłany z powrotem do klienta. Gdy tego rodzaju żądanie częściowe trafi do cyklu życia JavaServer Faces, za wszystkie informacje i przetwarzanie odpowiada obiekt javax.faces.context. ´PartialViewContext. Cykl życia JavaServer Faces bierze pod uwagę istnienie żądań typu Ajax i odpowiednio modyfikuje drzewo komponentów. Atrybuty wykonania i renderingu znacznika f:ajax służą do określenia, które komponenty powinny zostać wykonane i zrenderowane. Aby uzyskać więcej informacji na temat tych atrybutów, zajrzyj do rozdziału 4., „Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces”.

Cykl życia aplikacji faceletów Specyfikacja JavaServer Faces definiuje cykl życia aplikacji JavaServer Faces. Więcej informacji na ten temat znajdziesz w podrozdziale „Cykl życia aplikacji JavaServer Faces”. Poniższe kroki dotyczą procesu stosowanego przez aplikację bazującą na faceletach. 1. Gdy klient, na przykład przeglądarka, wykona nowe żądanie strony utworzonej za pomocą faceletów, powstaje nowe drzewo komponentów lub obiekt javax.faces.component.UIViewRoot, który trafia do FacesContext. 2. Obiekt UIViewRoot jest stosowany dla faceletów, a widok zostaje wypełniony komponentami do zrenderowania. 3. Nowo utworzony widok zostaje zrenderowany jako odpowiedź przesłana do klienta. 4. W trakcie renderingu stan widoku zostaje zapamiętany, by mógł być użyty w następnych żądaniach. Zapamiętywane są komponenty wejściowe i dane formularzy. 5. Klient może wchodzić w interakcję z widokiem i zażądać innego widoku lub dokonania zmiany przez aplikację JavaServer Faces. W takiej sytuacji zapisany widok zostanie odtworzony. 6. Odtworzony widok ponownie przechodzi przez fazy cyklu życia JavaServer Faces, co w efekcie spowoduje albo wygenerowanie nowego widoku, albo ponowne zrendrowanie aktualnego widoku, jeśli nie wystąpiły problemy z walidacją i nie została wywołana żadna akcja. 7. Jeśli wystąpi żądanie tego samego widoku, zapamiętany widok zostanie zrenderowany ponownie.

70

Java EE 6. Zaawansowany przewodnik

Model komponentów interfejsu użytkownika

8. Jeżeli żądanie dotyczy nowego widoku, ma miejsce proces opisany w kroku 2. 9. Nowy widok zostaje zrenderowany jako odpowiedź i przesłany do klienta.

Model komponentów interfejsu użytkownika Poza opisem cyklu życia, omówienie architektury JavaServer Faces spowoduje lepsze poznanie wykorzystywanych technologii. Komponenty JavaServer Faces to klocki, z których powstaje widok JavaServer Faces. Komponent może, ale nie musi, dotyczyć interfejsu użytkownika. Komponenty interfejsu użytkownika to konfigurowalne elementy wielokrotnego użytku, które składają się na interfejs użytkownika aplikacji JavaServer Faces. Niektóre komponenty są bardzo proste, na przykład przycisk, a inne znacznie bardziej złożone; przykładem może być tabela, która składa się z wielu innych komponentów. Technologia JavaServer Faces zapewnia bogatą i elastyczną architekturę komponentów, która składa się z elementów. Oto one: „

„ „

„

„ „

zestaw klas javax.faces.component.UIComponent określających stan i zachowanie komponentów interfejsu użytkownika, model renderowania określający różne sposoby renderowania komponentów, model konwersji definiujący sposób rejestracji konwerterów danych w komponentach, model zdarzeń i procedur ich obsługi, który określa sposoby obsługi zdarzeń komponentów, model walidacji definiujący sposób rejestracji walidatorów w komponentach, model nawigacji, który określa sposób poruszania po stronie i kolejność wczytywania stron.

W następnym podrozdziale pokrótce omówimy wszystkie wspomniane elementy architektury komponentów.

Klasy komponentów interfejsu użytkownika Technologia JavaServer Faces zapewnia zestaw klas komponentów interfejsu użytkownika i powiązane z nimi interfejsy zachowań, które w pełni definiują funkcjonalność komponentów, na przykład przechowywanie stanu, utrzymywanie referencji do innych obiektów, obsługę zdarzeń i sposoby renderowania zestawów standardowych komponentów. Klasy komponentów są w pełni rozszerzalne, co umożliwia programistom tworzenie własnych komponentów. Więcej informacji na ten temat podajemy w rozdziale 6., „Tworzenie własnych komponentów UI i innych obiektów”.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

71

Model komponentów interfejsu użytkownika

Abstrakcyjną klasą bazową wszystkich komponentów jest javax.faces.component. ´UIComponent. Klasy komponentów interfejsu użytkownika zapewniane przez JavaServer Faces dziedziczą po klasie UIComponentBase (stanowiącej podklasę klasy UIComponent), która definiuje domyślny stan i zachowanie komponentu. Wraz z technologią JavaServer Faces dostarczane są następujące klasy komponentów: „

UIColumn — reprezentuje pojedynczą kolumnę danych komponentu UIData,

„

UICommand — reprezentuje kontrolkę, która wywołuje odpowiednie akcje w momencie aktywacji, UIData — reprezentuje dowiązanie danych do kolekcji danych reprezentowanych przez instancję javax.faces.model.DataModel, UIForm — reprezentuje formularz wejściowy przedstawiany do wypełnienia użytkownikowi; komponenty potomne reprezentują między innymi pola wejściowe, których dane zostaną przesłane do serwera po wypełnieniu formularza; odpowiednikiem tego komponentu w HTML jest znacznik form, UIGraphics — wyświetla obrazek, UIInput — pobiera dane wejściowe od użytkownika; jest podklasą klasy UIOutput, UIMessage — wyświetla komunikat błędu w odpowiednim dla użytkownika języku, UIMessages — wyświetla zestaw komunikatów o błędzie w odpowiednim dla użytkownika języku, UIOutcomeTarget — wyświetla hiperłącze w postaci łącza lub przycisku, UIOutput — wyświetla dane wyjściowe na stronie, UIPanel — zarządza układem graficznym komponentów potomnych, UIParameter — określa parametry zastąpienia, UISelectBoolean — umożliwia użytkownikowi wskazanie wartości logicznej w kontrolce przez jej zaznaczenie lub usunięcie zaznaczenia; stanowi podklasę klasy UIInput, UISelectItem — reprezentuje pojedynczy element w zestawie elementów, UISelectItems — reprezentuje cały zestaw elementów, UISelectMany — umożliwia użytkownikowi wybór wielu elementów z pewnego zestawu; stanowi podklasę klasy UIInput, UISelectOne — umożliwia użytkownikowi wybór jednego elementu z pewnego zestawu; stanowi podklasę klasy UIInput, UIViewParameter — reprezentuje parametry zapytania w żądaniu; stanowi podklasę klasy UIInput, UIViewRoot — stanowi korzeń drzewa komponentów.

„

„

„ „

„

„

„ „ „ „ „

„ „ „

„

„

„

Klasy komponentów, poza rozszerzaniem klasy UIComponentBase, implementują jeden lub kilka interfejsów zachowań. Każdy z interfejsów definiuje określone zachowanie dla zestawu komponentów, których klasy implementują tenże interfejs. Oto interfejsy zachowań — wszystkie zdefiniowane w pakiecie javax.faces. ´component (chyba że wskazano inaczej).

72

Java EE 6. Zaawansowany przewodnik

Model komponentów interfejsu użytkownika

„

„

„

„

„

„

„

„

ActionSource — wskazuje, że komponent może zgłosić zdarzenie akcji. Interfejs ten przewidziany został do współpracy z komponentami bazującymi na technologii JavaServer Faces w wersji 1.1_01 lub starszej. Interfejs ten wycofano z JavaServer Faces 2. ActionSource2 — rozszerza ActionSource, więc zapewnia tę samą funkcjonalność. Dodatkowo umożliwia komponentom użycie EL (ang. Expression Language) w momencie tworzenia referencji do metod obsługujących zdarzenia akcji. EditableValueHolder — rozszerza ValueHolder i określa dodatkowe funkcjonalności dotyczące edytowalnych komponentów, na przykład walidację lub zgłaszanie zdarzeń zmiany wartości. NamingContainer — wskazuje, że każdy komponent, którego korzeniem jest ten komponent, posiada unikatowy identyfikator. StateHolder — wskazuje, iż komponent zawiera informacje o stanie, które należy zapisać między żądaniami. ValueHolder — wskazuje, że komponent przechowuje lokalną wartość, a także może mieć dostęp do danych z warstwy modelu. javax.faces.event.SystemEventListenerHolder — przechowuje listę instancji javax.faces.event.SystemEventListener dla każdego typu javax.faces.event.SystemEvent zdefiniowanego przez tę klasę. javax.faces.component.behavior.ClientBehaviorHolder — dodaje możliwość dołączenia instancji javax.faces.component.behavior. ´ClientBehavior, na przykład skryptów wielokrotnego użycia.

Klasa UICommand implementuje interfejsy ActionSource2 i StateHolder. Klasa UIOutput i klasy po niej dziedziczące implementują interfejsy StateHolder i ValueHolder. Klasa UIInput i klasy po niej dziedziczące implementują interfejsy EditableValueHolder, StateHolder i ValueHolder. Klasa UIComponentBase implementuje interfejs StateHolder. Jedynie osoby piszące komponenty muszą korzystać z klas komponentów i interfejsów zachowań w sposób bezpośredni. Autorzy stron i programiści aplikacji wykorzystują standardowe komponenty przez dołączenie znacznika reprezentującego komponent na stronie. Większość komponentów może być na stronie renderowana w różny sposób. Przykładem jest komponent UICommand, który może być zrenderowany jako przycisk lub łącze. W następnym punkcie omawiamy sposób działania modelu renderingu, a także wyjaśniamy, jak autorzy stron wybierają rodzaj renderingu przez wskazanie odpowiednich znaczników.

Model renderingu komponentów Architekturę komponentów JavaServer Faces zaprojektowano w taki sposób, że funkcjonalność komponentu definiuje klasa komponentu, ale za rendering komponentu odpowiada osobna klasa renderująca. Taki sposób zaprojektowania systemu ma kilka zalet. Niżej wymieniamy niektóre.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

73

Model komponentów interfejsu użytkownika

„

„

Twórcy komponentów mogą zdefiniować zachowanie komponentu tylko raz, ale utworzyć kilka klas renderujących, z których każda w nieco innych sposób renderuje komponent dla tego samego klienta lub różnych klientów. Autorzy stron i programiści aplikacji mogą zmienić wygląd komponentu na stronie przez wybór znaczników reprezentujących odpowiednie połączenie klasy komponentu i klasy renderującej.

Zestaw renderujący (ang. render kit) definiuje, w jaki sposób klasy komponentów zostają odwzorowane na znaczniki komponentów odpowiednie dla konkretnego klienta. Implementacja JavaServer Faces zawiera standardowo zestaw renderujący HTML dotyczący renderowania dla klientów wykorzystujących strony HTML. Zestaw renderujący definiuje zbiór klas javax.faces.render.Renderer dla każdego obsługiwanego komponentu. Każda klasa Renderer określa inny sposób renderowania konkretnego komponentu na wyjście zdefiniowane przez zestaw renderujący. Przykładowo w komponencie UISelectOne zastosowano trzy różne renderery. Pierwszy z nich wyświetla komponent jako przycisk opcji. Drugi wyświetla go jako listę rozwijaną, a trzeci jako listę wyboru. W bardzo podobny sposób komponent UICommand można wyświetlić jako przycisk lub hiperłącze, wykorzystując odpowiednio znaczniki h:commandButton i h:commandLink. Część command znacznika dotyczy klasy UICommand, która określa funkcjonalność, czyli w tym przypadku uruchomienie akcji. Część Button lub Link dotyczy osobnych klas Renderer, które określają sposób wyświetlenia komponentu na stronie. Każdy znacznik zdefiniowany w standardowym zestawie renderującym HTML składa się z funkcjonalności komponentu (zdefiniowanej w klasie UIComponent) oraz atrybutów renderingu (zdefiniowanych przez klasę Renderer). W rozdziale 7. książki Java EE 6. Przewodnik. Wydanie IV zawarta została lista wszystkich obsługiwanych znaczników komponentów, a także przedstawiony sposób ich użycia. Implementacja JavaServer Faces zapewnia osobną bibliotekę znaczników dotyczącą renderowania komponentów na potrzeby HTML.

Model konwersji Aplikacja JavaServer Faces może opcjonalnie powiązać komponent z danymi obiektu znajdującego się po stronie serwera. Obiektem tym jest komponent JavaBeans, na przykład zarządzane ziarno. Aplikacja pobiera i ustawia dane obiektu dla wybranego komponentu, wywołując odpowiednie właściwości obiektu. Gdy komponent jest powiązany z obiektem, aplikacja ma dostęp do dwóch widoków danych komponentu: „

74

widoku modelu, w którym dane reprezentują odpowiednie typy, na przykład int lub long;

Java EE 6. Zaawansowany przewodnik

Model komponentów interfejsu użytkownika

„

widoku reprezentacji, w którym dane są reprezentowane w sposób odpowiedni do odczytu lub modyfikacji przez użytkownika. Przykładowo obiekt typu java.util.Date można przedstawić jako tekst w formacie dd/mm/yy lub jako zestaw trzech osobnych tekstów.

Implementacja JavaServer Faces automatycznie konwertuje dane komponentu między dwoma wymienionymi widokami, gdy właściwość ziarna powiązanego z komponentem jest jednym z typów obsługiwanych przez dane komponentu. Jeśli komponent UISelectBoolean jest powiązany z właściwością ziarna typu java.lang.Boolean, implementacja JavaServer Faces spowoduje automatyczną konwersję danych komponentu z typu String na Boolean. Co istotne, niektóre dane komponentu muszą być powiązane z właściwościami konkretnego typu. Przykładem jest wspomniany komponent UISelectBoolean, który musi być powiązany z właściwości typu boolean lub java.lang.Boolean. Czasem zachodzi konieczność konwersji danych komponentu do typu innego niż standardowy lub konieczność zapewnienia innego formatu samych danych. By obsłużyć tego rodzaju sytuacje, technologia JavaServer Faces umożliwia zgłoszenie dla komponentów UIOutput (lub komponentów będących potomkami tej klasy) implementacji javax.faces.convert.Converter. Po zgłoszeniu implementacji Converter komponentowi to ona będzie odpowiadała za przeprowadzanie konwersji danych między dwoma widokami. Można albo zastosować standardowe konwertery dostarczane wraz z JavaServer Faces, albo utworzyć własne. Tworzenie własnych konwerterów zostało opisane w rozdziale 6., „Tworzenie własnych komponentów UI i innych obiektów”.

Model zdarzeń i procesów ich obsługi Model zdarzeń i procesów ich obsługi w JavaServer Faces przypomina model zdarzeń JavaBeans, bo również stosuje klasy zdarzeń o ściśle określonych typach, a także interfejsy dla kodu nasłuchującego, których aplikacja może użyć do obsługi zdarzeń generowanych przez komponenty. Specyfikacja JavaServer Faces definiuje trzy typy zdarzeń: zdarzenia aplikacji, zdarzenia systemowe i zdarzenia modelu danych. Zdarzenia aplikacji są ściśle powiązane z konkretną aplikacją. Generuje je komponent UIComponent. Reprezentują standardowe zdarzenia dostępne we wcześniejszych wersjach technologii JavaServer Faces. Obiekt zdarzenia zawiera informację o komponencie, który to zdarzenie zgłosił, ale także inne parametry określające zdarzenie. Aby otrzymać powiadomienie o zdarzeniu, aplikacja musi zapewnić implementację klasy elementu nasłuchującego i zgłosić ją (zarejestrować) komponentowi, który generuje zdarzenia. Gdy użytkownik wykona aktywację komponentu, na przykład kliknie przycisk, zostanie zgłoszone zdarzenie. Spowoduje to wywołanie przez implementację JavaServer Faces metody zgłoszonej jako procedura obsługi zdarzenia.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

75

Model komponentów interfejsu użytkownika

JavaServer Faces obsługuje dwa rodzaje zdarzeń związanych z aplikacją: zdarzenia akcji i zdarzenia zmiany wartości. Zdarzenie akcji (klasa javax.faces.event.ActionEvent) zachodzi, gdy użytkownik aktywuje komponent implementujący interfejs javax.faces.component. ´ActionSource. Dotyczy to przycisków i hiperłączy. Zdarzenie zmiany wartości (klasa javax.faces.event.ValueChangeEvent) zachodzi, gdy użytkownik zmieni wartość komponentu reprezentowanego przez klasę UIInput lub jedną z jej podklas. Przykładem może być włączenie opcji, co powoduje zmianę wartości komponentu na true. Komponentami, które mogą wygenerować tego rodzaju zdarzenie, są UIInput, UISelectOne, UISelectMany i UISelectBoolean. Zdarzenie zmiany wartości zachodzi tylko wtedy, gdy nie pojawiły się błędy walidacji. W zależności od wartości atrybutu immediate (patrz „Wspólne atrybuty znaczników komponentów” w książce Java EE 6. Przewodnik. Wydanie IV) komponentu zgłaszającego zdarzenie, zdarzenia akcji mogą zostać wykonane albo w trakcie fazy wywołania aplikacji, albo w fazie stosowania wartości żądania. Zdarzenia zmiany wartości mogą zostać przetworzone w trakcie fazy walidacji lub fazy stosowania wartości żądania. Zdarzenia systemowe są generowane przez Object, a nie UIComponent. Są generowane w trakcie wykonywania aplikacji w ściśle określonych momentach. Mają zastosowanie dla całej aplikacji, a nie jej poszczególnych komponentów. Zdarzenia modelu danych zachodzą, gdy zostanie wybrany nowy wiersz komponentu UIData. Istnieją dwa sposoby zapewnienia reakcji aplikacji na zdarzenia akcji lub zmiany wartości emitowane przez standardowe komponenty: „

„

implementacja klasy nasłuchiwania zdarzenia i jego obsługi, a następnie rejestracja jej dla komponentu poprzez zagnieżdżenie wewnątrz znacznika komponentu albo znacznika f:valueChangeListener, albo f:actionListener, implementacja metody zarządzanego ziarna, która obsłuży zdarzenie, a następnie wskazanie tej metody za pomocą odpowiedniego wyrażenia znajdującego się w atrybucie znacznika komponentu.

Więcej informacji na temat implementacji procedur obsługi zdarzeń znajdziesz w rozdziale 6., w podrozdziale „Implementacja klasy nasłuchiwania zdarzeń”. Więcej informacji na temat rejestracji procedur obsługi (listenerów) znajdziesz w podrozdziale „Rejestrowanie listenerów na komponentach”, w książce Java EE 6. Przewodnik. Wydanie IV. Więcej informacji na temat tworzenia metod zarządzanych ziaren obsługujących tego rodzaju zdarzenia znajdziesz w podrozdziałach „Tworzenie metody obsługującej zdarzenie akcji” i „Tworzenie metody obsługującej zdarzenie zmiany wartości”, książki Java EE 6. Przewodnik. Wydanie IV.

76

Java EE 6. Zaawansowany przewodnik

Model komponentów interfejsu użytkownika

W jaki sposób odnieść się do metody zarządzanego ziarna z poziomu znacznika komponentu, dowiesz się z podrozdziału „Odwoływanie się do metod backing beana”, w książce Java EE 6. Przewodnik. Wydanie IV. Zgłaszając zdarzenia z poziomu własnych komponentów, należy zaimplementować odpowiednie klasy zdarzeń i ręcznie kolejkować zdarzenie dotyczące komponentu. To dodatkowa praca, poza wspominaną już implementacją klasy procedury obsługi zdarzenia lub metody zarządzanego ziarenka, które obsłuży zdarzenie. Więcej informacji na ten temat zawiera podrozdział „Obsługa zdarzeń dla samodzielnie wykonanych komponentów” rozdziału 6. tej książki.

Model walidacji Technologia JavaServer Faces obsługuje mechanizm sprawdzania danych lokalnych komponentów z możliwością edycji (na przykład pól tekstowych). Sprawdzenie wartości odbywa się za pomocą aktualizacji odpowiednich danych modelu w celu ich dopasowania do lokalnej wartości. Podobnie jak w modelu konwersji, także w modelu walidacji zdefiniowano zestaw standardowych klas do przeprowadzania typowych sprawdzeń. Co więcej, standardowa biblioteka znaczników JavaServer Faces definiuje zbiór znaczników odpowiadających standardowym implementacjom javax.faces.validator. ´Validator. Listę wszystkich standardowych klas walidatorów i odpowiadających im znaczników znajdziesz w podrozdziale „Używanie standardowych walidatorów”, w książce Java EE 6. Przewodnik. Wydanie IV. Większość znaczników stosuje zestawy atrybutów konfigurujących właściwości walidatora, na przykład minimalną i maksymalną wartość danych komponentu. Autor strony rejestruje walidator dla komponentu, zagnieżdżając jego znacznik wewnątrz znacznika komponentu. Poza walidatorami rejestrowanymi dla komponentów, można również zadeklarować domyślny walidator stosowany dla wszystkich komponentów UIInput aplikacji. Więcej informacji na temat walidatorów domyślnych znajdziesz w rozdziale 7., w podrozdziale „Korzystanie z walidatorów domyślnych”. Model walidacji dopuszcza tworzenie własnych walidatorów i odpowiadających im znaczników w celu przeprowadzania weryfikacji specyficznych dla aplikacji. Model walidacji zapewnia dwa sposoby implementacji własnej walidacji: „

„

implementację interfejsu Validator przeprowadzającego odpowiednie sprawdzenia, implementację metody zarządzanego ziarna przeprowadzającej odpowiednie sprawdzenia.

Implementując interfejs Validator, trzeba również: „ „

zarejestrować implementację w aplikacji, utworzyć własne znaczniki lub znacznik f:validator w celu rejestracji walidatora w komponencie.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

77

Model komponentów interfejsu użytkownika

W opisanym wcześniej standardowym modelu walidacji walidatory definiuje się dla każdego komponentu wejściowego na stronie. Model Bean Validation umożliwia użycie wybranego walidatora dla wszystkich pól na stronie. W celu uzyskania dodatkowych informacji zajrzyj do podrozdziału „Używanie mechanizmu Bean Validation” książki Java EE 6. Przewodnik. Wydanie IV lub do rozdziału 22., „Mechanizm Bean Validation — tematy zaawansowane” tej książki.

Model nawigacji Model nawigacji JavaServer Faces ułatwia zdefiniowanie nawigacji stron i obsługę dowolnego dodatkowego przetwarzania niezbędnego do wybrania sekwencji, w których wczytywane są strony. W technologii JavaServer Faces nawigacja to zbiór reguł wyboru następnej strony lub widoku do wyświetlenia po wykonaniu akcji aplikacji, na przykład po kliknięciu przycisku lub hiperłącza. Nawigacja może być niejawna lub zdefiniowana przez programistę. Nawigacja niejawna włącza się, gdy nie są dostępne reguły zdefiniowane przez programistę. Więcej informacji na temat nawigacji niejawnej znajduje się w podrozdziale „Niejawne reguły nawigacyjne” rozdziału 7. tej książki Reguły nawigacji zdefiniowanej przez programistę mogą znajdować się w plikach zasobów z konfiguracją aplikacji, na przykład faces-config.xml. Wykorzystują zbiór elementów XML. Domyślna struktura reguły nawigacyjnej ma postać:







Obsługa nawigacji zdefiniowanej przez programistę polega na: „ „

zdefiniowaniu reguły w pliku zasobów konfiguracyjnych aplikacji, odniesieniu się do wynikowego obiektu String z atrybutu action komponentu przycisku lub hiperłącza; wynikowy String służy implementacji JavaServer Faces do wyboru reguły nawigacyjnej.

Oto przykład reguły nawigacyjnej:

/welcome.xhtml

sukces /response.xhtml

78

Java EE 6. Zaawansowany przewodnik

Model komponentów interfejsu użytkownika

Reguła informuje, że jeśli komponent polecenia (na przykład h:commandButton lub h:commandLink) ze strony welcome.xhtml zostanie uaktywniony, aplikacja przejdzie ze strony welcome.xhtml do strony response.xhtml, kiedy wynikiem związanym ze znacznikiem komponentu będzie success. Poniżej znajduje się przykład znacznika h:commandButton z pliku welcome.xhtnl, który zapewnia zgłoszenie odpowiedniego wyniku:

Jak pokazujemy na przykładzie, każdy element navigation-rule definiuje sposób przejścia z jednej strony (określonej w elemencie from-view-id) aplikacji do innej. Elementy navigation-rule mogą zawierać dowolną liczbę elementów navigation-case. Każdy z nich określa następną stronę do otwarcia (element to-view-id) na podstawie uzyskanego wyniku (element from-outcome). W bardziej złożonych aplikacjach wynik logiczny może również pochodzić z wartości zwracanej przez metodę akcji zarządzanego ziarna. Metoda wykona pewne operacje, by określić zwracany wynik. Przykładowo może sprawdzić, czy hasło podane przez użytkownika na stronie odpowiada hasłu znajdującemu się w pliku. Jeśli tak, metoda zwróci wartość sukces. W przeciwnym razie zwróci wartość błąd, która może oznaczać ponowne przejście do strony logowania. Wartość sukces może prowadzić do wyświetlenia strony z historią transakcji na karcie kredytowej. Jeżeli wynik operacji ma zostać zwrócony przez metodę ziarna, trzeba odnieść się do metody przy użyciu odpowiedniego wyrażenia wewnątrz atrybutu action:

Gdy użytkownik kliknie przycisk reprezentowany przez znacznik, komponent wygeneruje zdarzenie akcji. Zdarzenie zostanie obsłużone przez domyślną instancję javax.faces.event.ActionListener, która wywołuje metodę akcji, do jakiej odnosi się komponent zgłaszający zdarzenie. Metoda akcji zwraca odpowiedni wynik do metody nasłuchującej akcji. Metoda nasłuchująca przekazuje uzyskany wynik oraz referencję do metody akcji, która ją zwróciła, do domyślnego javax.faces.application.NavigationHandler. Implementacja NavigationHandler wybiera następną stronę do wyświetlenia, porównując wynik i metodę akcji z regułami nawigacji znajdującymi się w pliku zasobów konfiguracyjnych. Stosuje przy tym następujący algorytm. 1. Kod z NavigationHandler wybiera regułę nawigacyjną, która pasuje do aktualnie wyświetlanej strony. 2. Dopasowuje wynik lub metodę akcji otrzymaną z domyślnej instancji javax.faces.event.ActionListener do wartości występujących w regule. 3. Stara się dopasować zarówno metodę, jak i wynik w tym samym przypadku nawigacyjnym. 4. Jeśli poprzednik krok nie powiedzie się, implementacja stara się dopasować wynik. 5. Jeśli oba wcześniejsze kroki zawiodły, stara się dopasować metodę akcji.

Rozdział 3 y Technologia JavaServer Faces — tematy zaawansowane

79

Model komponentów interfejsu użytkownika

6. Jeżeli żadne reguły nawigacyjne nie zostały dopasowane, ponownie wyświetla ten sam widok. Gdy kod NavigationHandler znajdzie dopasowanie, rozpoczyna się faza wysyłki odpowiedzi. W jej trakcie serwer wykona rendering strony wybranej przez NavigationHandler. Przykładowa aplikacja Duke’s Tutoring (ćwiczenie Duka’a) korzysta z reguł nawigacyjnych w metodach biznesowych obsługujących tworzenie, edycję i usuwanie użytkowników aplikacji. Przykładowy formularz dodawania nowego studenta wykorzystuje znacznik h:commandButton w następujący sposób:

Przedstawione zdarzenie akcji wywołuje metodę dukestutoring.ejb.AdminBean.createStudent: public String createStudent(Student student) { em.persist(student); return "createdStudent"; }

Zwracana wartość createdStudent posiada odpowiedni przypadek nawigacyjny ujęty w pliku konfiguracyjnym faces-config.xml:

/admin/student/createStudent.xhtml

createdStudent /admin/index.xhtml

Po dodaniu studenta użytkownik zostaje przekierowany do strony administracyjnej. Więcej informacji na temat definiowania reguł nawigacyjnych zawiera podrozdział „Konfiguracja reguł nawigacyjnych” rozdziału 7. tej książki. Więcej informacji na temat implementacji metod akcji do obsługi nawigacji zawiera podrozdział „Tworzenie metody obsługującej zdarzenie akcji” książki Java EE 6. Przewodnik. Wydanie IV. Dodatkowe informacje na temat odnoszenia się do wyników lub metod akcji z poziomu znaczników komponentów zawiera podrozdział „Odwoływanie się do metody wykonującej nawigację” książki Java EE 6. Przewodnik. Wydanie IV.

80

Java EE 6. Zaawansowany przewodnik

‹

‹

‹

4

ROZDZIAŁ 4

Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

W pierwszych aplikacjach internetowych korzystano głównie ze statycznych stron WWW. Statyczna strona po aktualizacji przez klienta musi być w całości pobrana z serwera, by odzwierciedlić wprowadzone poprawki. Oznacza to, że po każdej zmianie wprowadzonej przez klienta serwer przygotowuje nową wersję całej strony WWW z naniesionymi poprawkami. Częste wczytywanie całych stron WWW znacząco obciąża połączenie sieciowe i obniża wydajność aplikacji. Technologie, takie jak Ajax, pomagają rozwiązać wspomniane problemy. Ajax, skrót od Asynchronous JavaScript and XML, dotyczy zestawu technologii internetowych, które umożliwiają tworzenie dynamicznych i wysoce szybkich w reakcji aplikacji internetowych. Wykorzystując technologię Ajax, aplikacje internetowe mogą pobierać z serwera treści nawet bez jakichkolwiek zmian w wyglądzie strony lub bez jakiejkolwiek akcji użytkownika. JavaServer Faces dostępna na platformie Javy EE 6 zawiera wbudowaną obsługę technologii Ajax. W tym rozdziale skupimy się na korzystaniu z technologii Ajax w aplikacjach internetowych JavaServer Faces. W rozdziale: „ „ „ „ „ „ „ „ „ „ „ „

Technologia Ajax — wprowadzenie, Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces, Wykorzystanie technologii Ajax wraz z faceletami, Wysłanie żądania Ajax, Monitorowanie zdarzeń po stronie klienta, Obsługa błędów, Otrzymywanie odpowiedzi Ajax, Cykl życia żądania Ajax, Grupowanie komponentów, Wczytywanie kodu JavaScript jako zasobu, Przykładowa aplikacja ajaxguessnumber, Dodatkowe informacje na temat użycia technologii Ajax wraz z technologią JavaServer Faces.

Technologia Ajax — wprowadzenie

Technologia Ajax — wprowadzenie Ajax to skrót, który odnosi się do języka JavaScript i formatu XML, czyli rozwiązań szeroko stosowanych w dynamicznych witrynach i asynchronicznie doczytywanych materiałach. Choć technologia Ajax nie ogranicza się tylko i wyłącznie do tych dwóch elementów, w praktyce najczęściej to właśnie ich połączenie stosuje się w aplikacjach internetowych. W tym rozdziale skupimy się przede wszystkim na dodaniu funkcjonalności technologii Ajax z użyciem języka JavaScript w aplikacjach JavaServer Faces. JavaScript jest dynamicznym językiem skryptowym dla aplikacji internetowych. Umożliwia programistom zapewnienie rozszerzonej funkcjonalności w interfejsach użytkownika oraz komunikowanie się z stron z serwerem w sposób asynchroniczny. JavaScript jest językiem stosowanym przede wszystkim po stronie klienta (w przeglądarce internetowej) i tym samym zmniejsza potrzebę komunikacji klienta z serwerem. Gdy funkcja JavaScript wysyła asynchroniczne żądanie od klienta do serwera, serwer odpowiada danymi, które posłużą do aktualizacji DOM-u (ang. Document Object Model, czyli modelu obiektowego dokumentu). Odpowiedź w wielu sytuacjach ma formę dokumentu XML. Termin Ajax odnosi się przede wszystkim do wspomnianej interakcji między klientem i serwerem. Odpowiedź serwera nie musi być w formacie XML. Obecnie coraz częściej stosuje się również inne formaty, przede wszystkim format JSON. W tym rozdziale nie będziemy skupiać się na formatach odpowiedzi. Ajax umożliwia asynchroniczną aktualizację fragmentu strony WWW. Dzięki temu strony WWW mogą szybciej reagować na akcje użytkownika i zapewniać odpowiedź w czasie niemalże rzeczywistym. Aplikacje internetowe wykorzystujące technologię Ajax mogą komunikować się z serwerem, przetwarzać informacje i pobierać dane bez wpływania na wygląd i sposób działania strony wyświetlanej użytkownikowi w danym momencie. Oto kilka zalet stosowania technologii Ajax: „

„

„

82

sprawdzanie danych formularza w czasie rzeczywistym, co eliminuje potrzebę przesłania formularza do weryfikacji, rozszerzona funkcjonalność stron internetowych, na przykład zapytania o nazwę użytkownika i hasło, częściowa aktualizacja treści strony WWW, co pozwala uniknąć ponownego wczytywania całej strony.

Java EE 6. Zaawansowany przewodnik

Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces Funkcjonalność Ajax do aplikacji JavaServer Faces można wprowadzić przez: „ „

dodanie do aplikacji odpowiedniego kodu JavaScript, użycie wbudowanej biblioteki zasobów Ajax.

We wcześniejszych wydaniach platformy Javy EE aplikacje JavaServer Pages zapewniały funkcjonalność Ajax przez dodawanie do aplikacji odpowiedniego kodu JavaScript. Platforma Javy EE 6 obsługuje technologię Ajax przez zapewnienie wbudowanej biblioteki zasobów Ajax. Wykorzystując wspomnianą bibliotekę zasobów, standardowe dla JavaServer Faces komponenty interfejsu użytkownika, na przykład przyciski, etykiety lub pola tekstowe, mogą zostać wzbogacone o obsługę technologii Ajax. Można również wczytać bibliotekę zasobów i używać jej metod bezpośrednio z poziomu kodu zarządzanych ziaren. W kolejnych podrozdziałach opisujemy sposoby korzystania z wbudowanej biblioteki zasobów Ajax. Co więcej, ponieważ model komponentowy technologii JavaServer Faces można rozszerzać, własne komponenty również mogą korzystać z funkcjonalności Ajax. Wersja Ajax aplikacji guessnumber nazwana ajaxguessnumber jest dostępna w materiałach dodatkowych do tej książki. Więcej informacji na ten temat znajdziesz w tym rozdziale, w podrozdziale „Przykładowa aplikacja ajaxguessnumber”. W następnych podrozdziałach pojawi się opis znacznika f:ajax i jego atrybutów.

Wykorzystanie technologii Ajax wraz z faceletami Jak wcześniej wspomniano, technologia JavaServer Faces obsługuje technologię Ajax, zapewniając wbudowaną bibliotekę zasobów Ajax jako część głównych bibliotek JavaServerFaces. Zbudowane zasoby Ajax można zastosować w aplikacjach JavaServer Faces na jeden z następujących sposobów: „

„

wykorzystując znacznik f:ajax wraz z innymi standardowymi komponentami w aplikacji typu Facelet; to rozwiązanie dodaje funkcjonalność Ajax do dowolnego komponentu interfejsu użytkownika bez potrzeby dodatkowej konfiguracji lub kodu; poprzez użycie metody API JavaScript jsf.ajax.request() bezpośrednio w aplikacji faceletowej; to rozwiązanie zapewnia bezpośredni dostęp do metod Ajax i zapewnia pełną kontrolę nad zachowaniem komponentu.

Rozdział 4 y Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

83

Wykorzystanie technologii Ajax wraz z faceletami

Użycie znacznika f:ajax Znacznik f:ajax jest jednym z podstawowych znaczników JavaServer Faces i zapewnia funkcjonalność Ajax każdemu standardowemu komponentowi interfejsu użytkownika, gdy jest stosowany w połączeniu z tym komponentem. W poniższym przykładzie dodano obsługę technologii Ajax do komponentu wejściowego przez dołączenie znacznika f:ajax:



W przedstawionym przykładzie włączono, co prawda, obsługę technologii Ajax, ale nie zdefiniowano żadnego atrybutu znacznika f:ajax. Brak wskazania zdarzenia spowoduje wykonanie domyślnej akcji komponentu. W przypadku komponentu inputText domyślną akcją przy braku atrybutu event jest zdarzenie valueChange. W tabeli 4.1 przedstawiamy listę atrybutów znacznika f:ajax wraz z ich akcjami domyślnymi. Tabela 4.1. Atrybuty znacznika f:ajax Nazwa

Typ

Opis

disabled

javax.el.ValueExpression,

Wartość logiczna (Boolean) określająca stan znacznika. Wartość true oznacza, że zachowanie dotyczące Ajax nie powinno być realizowane. Wartość false wskazuje, że zachowanie Ajax należy dołączyć. Wartością domyślną jest false.

którego wynik jest typu Boolean

84

event

javax.el.ValueExpression, którego wynik jest typu String

Wartość typu String wskazująca rodzaj zdarzenia, dla którego ma być zastosowane zachowanie Ajax. Jeżeli jest podana, musi stanowić jedno ze zdarzeń obsługiwanych przez komponent. Jeżeli została pominięta, system określa zdarzenie domyślne (zdarzenie, które wywoła żądanie Ajax) komponentu. Dla komponentów implementujących javax.faces. ´component.ActionSource jest to zdarzenie action, a dla komponentów implementujących javax.faces. ´component.EditableValueHolder jest to zdarzenie valueChange.

execute

javax.el.ValueExpression, którego wynik jest typu Object

Element Collection, który określa listę komponentów do wykonania po stronie serwera. W przypadku literału musi to być lista identyfikatorów komponentów oddzielona znakami spacji. Jeżeli wskazano ValueExpression, musi odnosić się do właściwości zwracającej Collection z obiektami String. Jeżeli nie jest określony, przyjmuje wartość @this.

Java EE 6. Zaawansowany przewodnik

Wykorzystanie technologii Ajax wraz z faceletami

Tabela 4.1. Atrybuty znacznika f:ajax — ciąg dalszy Nazwa

Typ

Opis

immediate

javax.el.ValueExpression,

Wartość logiczna wskazująca, czy pola wejściowe powinny być przetwarzane na wcześniejszym etapie cyklu życia. Wartość true oznacza, że wygenerowane zdarzenia zachowań są zgłaszane w fazie stosowania wartości żądania. W przeciwnym razie są zgłaszane w fazie wywołania aplikacji.

którego wynik jest typu Boolean

listener

javax.el.MethodExpression

Nazwa metody nasłuchującej wywoływanej w momencie rozesłania javax.faces. ´event.AjaxBehaviorEvent do klasy obsługi zdarzeń.

onevent

javax.el.ValueExpression, którego wynik jest typu String

Nazwa funkcji JavaScript odpowiedzialnej za zdarzenia interfejsu użytkownika.

onerror

javax.el.ValueExpression, którego wynik jest typu String

Nazwa funkcji JavaScript odpowiedzialnej za obsługę błędów.

render

javax.el.ValueExpression, którego wynik jest typu Object

Element Collection, który określa listę komponentów do zrenderowania po stronie klienta. W przypadku literału musi to być lista identyfikatorów komponentów oddzielona znakami spacji lub (i) jedno ze słów kluczowych. Jeżeli wskazano ValueExpression, musi odnosić się do właściwości zwracającej Collection z obiektami String. Jeżeli nie jest określony, przyjmuje wartość @none.

Słowa kluczowe wymienione w tabeli 4.2 mogą być stosowane w atrybutach execute i render znacznika f:ajax. Tabela 4.2. Słowa kluczowe atrybutów execute i render Słowo kluczowe

Opis

@all

wszystkie identyfikatory komponentów

@form

formularz, w którym znajduje się komponent

@none

żadne identyfikatory komponentów

@this

element, który wywołał żądanie

Pamiętaj, że w przypadku użycia znacznika f:ajax na stronie faceletu biblioteka zasobów JavaScript zostanie wczytana w sposób niejawny. Bibliotekę można również wczytać w sposób jawny, stosując rozwiązanie opisane w tym rozdziale, w podrozdziale „Wczytywanie kodu JavaScript jako zasobu”.

Rozdział 4 y Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

85

Wysłanie żądania Ajax

Wysłanie żądania Ajax Aby aktywować funkcjonalność Ajax, aplikacja internetowa musi utworzyć żądanie Ajax i wysłać je do serwera. Serwer odpowiada za jego przetworzenie. Do utworzenia żądania Ajax aplikacja wykorzystuje atrybuty znacznika f:ajax wskazane w tabeli 4.1. W podrozdziale wyjaśnimy proces tworzenia i wysyłania żądań Ajax z wykorzystaniem niektórych przedstawionych w tabeli atrybutów. UWAGA W rzeczywistości to metoda jsf.ajax.request() z biblioteki zasobów

w tle pobiera dane dostarczone przez znacznik f:ajax i wysyła odpowiednie żądanie do cyklu życia JavaServer Faces.

Użycie atrybutu event Atrybut event określa zdarzenie, które wywołuje akcję Ajax. Kilkoma możliwymi wartościami tego atrybutu są click, keyup, mouseover, focus i blur. Jeżeli atrybut nie zostanie wskazany, system użyje domyślnego zdarzenia bazującego na komponencie nadrzędnym. Dla komponentów implementujących javax.faces.component.ActionSource (na przykład commandButton) jest to zdarzenie action, a dla komponentów implementujących javax.faces. ´component.EditableValueHolder (na przykład inputText) — zdarzenie valueChange. W poniższym przykładzie znacznik f:ajax jest powiązany z komponentem przycisku, a zdarzeniem wywołującym akcję Ajax jest kliknięcie przycisku:



UWAGA Zapewne zauważyłeś, że wymienione zdarzenia przypominają zdarzenia

dostępne z poziomu języka JavaScript. Dostępne zdarzenia właśnie na nich bazują, ale nie zawierają przedrostka on. Dla przycisku domyślnym zdarzeniem jest click, więc nie trzeba było dodawać atrybutu event="click", by uzyskać pożądane zachowanie.

Użycie atrybutu execute Atrybut execute określa komponent lub komponenty do wykonania po stronie serwera. Komponent identyfikuje atrybut id. Można wskazać więcej niż jeden komponent do uruchomienia. W takiej sytuacji identyfikatory poszczególnych komponentów trzeba oddzielić znakami spacji.

86

Java EE 6. Zaawansowany przewodnik

Monitorowanie zdarzeń po stronie klienta

Wykonywany komponent uczestniczy we wszystkich fazach przetwarzania żądania w cyklu życia, poza fazą renderowania odpowiedzi. Atrybut execute może również zawierać słowa kluczowe, takie jak @all, @none, @this lub @form . Wartością domyślną jest @this , co oznacza, że ma zostać wykonany komponent, wewnątrz którego znajduje się znacznik f:ajax. Poniższy kod określa komponent h:inputText z wartością id równą userNo. Zostanie on wykonany po kliknięciu przycisku.

...



Użycie atrybutu immediate Atrybut immediate wskazuje, czy pola wejściowe powinny być przetwarzane na wcześniejszym etapie cyklu życia żądania, czy może nieco później. Wartość true oznacza, że zdarzenia wygenerowane przez komponent są rozgłaszane w fazie stosowania wartości żądania. W przeciwnym razie są rozgłaszane w fazie wywołania aplikacji. Jeżeli atrybut nie jest podany jawnie, przyjmuje wartość domyślną false.

Użycie atrybutu listener Atrybut listener dotyczy wyrażenia metody, które zostanie wykonane po stronie serwera w odpowiedzi na akcję Ajax ze strony klienta. Metoda javax.faces.event. ´AjaxBehaviorListener.processAjaxBehavior elementu nasłuchującego jest wywoływana jednokrotnie w trakcie fazy wywołania aplikacji cyklu życia. W poniższym przykładzie atrybut listener zdefiniowano na poziomie znacznika f:ajax i odnosi się do metody ziarna:

Poniższy kod reprezentuje metodę akcja z obiektu ziarno: public void akcja(AjaxBehaviorEvent event) { wykonaj zadania; }

Monitorowanie zdarzeń po stronie klienta Trwające żądania Ajax można monitorować przy użyciu atrybutu onevent znacznika f:ajax. Wartością atrybutu jest nazwa funkcji w języku JavaScript. JavaServer Faces wywoła funkcję onevent na każdym z etapów przetwarzania żądania Ajax, czyli na etapach rozpoczęcia, ukończenia i sukcesu.

Rozdział 4 y Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

87

Obsługa błędów

Wywołując funkcję JavaScript przypisaną właściwości onevent, JavaServer Faces przekazuje do niej obiekt z danymi. Obiekt zawiera właściwości wymienione w tabeli 4.3. Tabela 4.3. Właściwości obiektu danych funkcji onevent Właściwość

Opis

responseXML

odpowiedź żądania Ajax w formacie XML

responseText

odpowiedź żądania Ajax w formacie tekstowym

responseCode

odpowiedź żądania Ajax w formacie liczbowym

source

źródło aktualnego żądania Ajax — element DOM

status

status żądania Ajax: begin (rozpoczęcie), complete (ukończenie) lub success (sukces)

type

rodzaj żądania Ajax — event

Wykorzystując wartość właściwości status obiektu danych, można łatwo identyfikować aktualny stan żądania Ajax i monitorować jego postęp. W poniższym przykładzie funkcja JavaScript monitorowanieZadaniaAjax będzie wywoływana przy każdej zmianie stanu żądania Ajax:

Obsługa błędów Za obsługę błędów technologii Ajax w JavaServer Faces odpowiada atrybut onerror znacznika f:ajax. Zawiera on nazwę funkcję JavaScript. Gdy wystąpi błąd w trakcie przetwarzania żądania Ajax, JavaServer Faces wywoła wskazaną w onerror funkcję JavaScript i przekaże jej obiekt danych. Obiekt ten zawiera wszystkie właściwości dostępne dla atrybutu onevent oraz kilka dodatkowych, takich jak: „ description, „ errorName, „ errorMessage. Właściwość type zawiera wartość error. Właściwość status obiektu danych zawiera jedną z wartości błędów wymienionych w tabeli 4.4. W poniższym przykładzie wszystkie błędy występujące w trakcie przetwarzania żądania Ajax zostaną zgłoszone poprzez wywołanie funkcji JavaScript o nazwie bledyZadaniaAjax:

88

Java EE 6. Zaawansowany przewodnik

Otrzymywanie odpowiedzi Ajax

Tabela 4.4. Wartości właściwości status obiektu danych w przypadku błędu Wartość

Opis

emptyResponse

brak odpowiedzi Ajax z serwera

httpError

jeden z błędów zgodnych z HTTP: request.status==null lub request.status==undefined, lub request.status < 200, lub request.status >= 300

malformedXML

odpowiedź Ajax nie została przekazana we właściwym, dobrze skonstruowanym formacie

serverError

odpowiedź Ajax zawiera element error

Otrzymywanie odpowiedzi Ajax Żądanie Ajax po wysłaniu przez aplikację jest przetwarzane po stronie serwera, a odpowiedź trafia z powrotem do klienta. Jak wcześniej wspomniano, technologia Ajax umożliwia częściową aktualizację stron WWW. Aby zapewnić prawidłowe działanie aktualizacji częściowej, technologia JavaServer Faces dopuszcza częściowe przetworzenie widoku. Obsługa odpowiedzi zależy od zawartości atrybutu render znacznika f:ajax. Podobnie jak atrybut execute, także atrybut render określa fragmenty strony, które zostaną zaktualizowane. Wartościami atrybutu render mogą być identyfikatory jednego lub kilku komponentów, słowa kluczowe (@this, @all, @none lub @form) lub wyrażenie EL. W poniższym przykładzie atrybut render identyfikuje komponent wyjściowy, który zostanie wyświetlony po udanym zakończeniu akcji Ajax.



Jednak zdecydowanie częściej atrybut render jest powiązany z atrybutem event. W poniższym przykładzie komponent wyjściowy zostanie wyświetlony po kliknięciu komponentu przycisku.



UWAGA Pamiętaj, że w tle za obsługę odpowiedzi serwera odpowiada metoda jsf.ajax.request(). Rejestruje ona funkcję zwrotną obsługi odpowiedzi w momencie tworzenia żądania. Gdy klient otrzymuje odpowiedź z serwera, funkcja zwrotna zostaje wywołana. Jej zadaniem jest automatyczna aktualizacja DOM po stronie klienta na podstawie danych uzyskanych z serwera.

Rozdział 4 y Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

89

Cykl życia żądania Ajax

Cykl życia żądania Ajax Żądanie Ajax różni się od pozostałych żądań JavaServer Faces i jego obsługa przez cykl życia JavaServer Faces wygląda inaczej. Zgodnie z opisem z podrozdziału „Częściowe przetwarzanie i rendering” rozdziału 3. tej książki, gdy serwer otrzymuje żądanie Ajax, stan powiązany z żądaniem jest przechwytywany przez javax.faces.context. ´PartialViewContext. Obiekt ten zawiera między innymi informacje dotyczące tego, które komponenty należy przetworzyć lub zrenderować. Metoda processPartial z PartialViewContext wykorzystuje te informacje do przeprowadzenia częściowego przetwarzania i renderingu drzewa komponentów. Atrybut execute znacznika f:ajax wskazuje, którą część drzewa komponentów po stronie serwera należy przetworzyć. Ponieważ komponenty znajdujące się w drzewie komponentów mogą posiadać unikatowe identyfikatory, w łatwy sposób można przetworzyć pojedynczy komponent, ich grupę lub całe drzewo. Odpowiada za to metoda visitTree klasy javax.faces.component.UIComponent. Komponenty po określeniu są przetwarzane przez poszczególne fazy cyklu życia żądania JavaServer Faces. Atrybut render, podobny w działaniu do atrybutu execute, wskazuje segmenty drzewa komponentów, które powinny zostać zrenderowane w trakcie fazy renderowania odpowiedzi. Podczas fazy renderowania odpowiedzi sprawdzana jest zawartość atrybutu render. Wskazane tam komponenty są odnajdywane, a następnie muszą wykonać

renderowanie siebie i swoich potomków. Wynik renderingu jest łączony w całość i przesyłany do klienta jako odpowiedź.

Grupowanie komponentów We wcześniejszych podrozdziałach opisywaliśmy dołączanie funkcjonalności Ajax do pojedynczych komponentów interfejsu użytkownika. Możliwe jest również powiązanie akcji Ajax z więcej niż jednym komponentem poprzez operację grupowania. Poniższy przykład jest ilustracją grupowania komponentów przy użyciu znacznika f:ajax.





W przedstawionym przykładzie żaden z komponentów nie jest jeszcze powiązany z atrybutami event i render. Z tego powodu w trakcie wpisywania danych przez użytkownika nie zostanie wykonana żadna akcja. Powiązanie komponentów z atrybutami event i render może przyjąć następującą postać:

90

Java EE 6. Zaawansowany przewodnik

Wczytywanie kodu JavaScript jako zasobu





Gdy w zaktualizowanym przykładzie użytkownik kliknie którykolwiek z komponentów, uaktualniony wynik zostanie wyświetlony dla wszystkich komponentów. Akcję Ajax można dostosować do konkretnej sytuacji, dodając odpowiednie zdarzenia do każdego z komponentów. W ten sposób funkcjonalność Ajax zostanie skumulowana. Rozważmy następujący przypadek:

...

...

W przedstawionej sytuacji komponent przycisku wywoła akcję Ajax w przypadku zdarzenia mouseover oraz w przypadku zdarzenia kliknięcia.

Wczytywanie kodu JavaScript jako zasobu Plik zasobów JavaScript dostarczany wraz z technologią JavaServer Faces nosi nazwę jsf.js i jest dostępny w bibliotece javax.faces. Biblioteka odpowiada za obsługę funkcjonalności Ajax w aplikacjach JavaServer Faces. Gdy chcesz bezpośrednio skorzystać z zasobu w komponencie lub klasie ziarna, należy jawnie wczytać bibliotekę zasobu. Zasób można wczytać na jeden z następujących sposobów: „ stosując API zasobów w sposób bezpośredni na stronie faceletu, „ wykorzystując adnotację javax.faces.application.ResourceDependency i API zasobów w klasie ziarna.

Użycie API dla kodu JavaScript w aplikacji z faceletami Aby skorzystać z biblioteki JavaScript bezpośrednio w aplikacji internetowej, na przykład na stronie faceletu, należy przede wszystkim za pomocą znacznika h:outputScript określić domyślny zasób JavaScript dla strony. Rozważmy zaistnienie na stronie faceletu następującego fragmentu:



Wskazanie jako celu (atrybut target) znacznika head spowoduje, że zasób skryptu zostanie zrenderowany wewnątrz znacznika head strony HTML.

Rozdział 4 y Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

91

Wczytywanie kodu JavaScript jako zasobu

W następnym kroku należy określić komponent, do którego chciałbyś dołączyć funkcjonalność Ajax. Dodaj zatem funkcjonalność do komponentu, wykorzystując API JavaScript. Spójrz na następujący przykład:





Metoda jsf.ajax.request przyjmuje maksymalnie trzy parametry, które określają odpowiednio źródło, zdarzenie i opcje. Parametr źródła określa element DOM, który wywołał żądanie Ajax (najczęściej przyjmuje wartość this). Opcjonalny parametr zdarzenia określa zdarzenie DOM, które spowodowało zgłoszenie zdarzenia. Opcjonalny parametr opcji składa się z par nazwa-wartość wymienionych w tabeli 4.5. Tabela 4.5. Możliwe elementy parametru opcji Nazwa

Wartość

execute

Oddzielona znakami spacji lista identyfikatorów lub jedno ze słów kluczowych z tabeli 4.2. Identyfikatory odnoszą się do komponentów, które mają zostać wykonane w fazie przetwarzania cyklu życia żądania.

render

Oddzielona znakami spacji lista identyfikatorów lub jedno ze słów kluczowych z tabeli 4.2. Identyfikatory odnoszą się do komponentów, które mają zostać przetworzone w fazie renderowania cyklu życia żądania.

onevent

Tekst zawierający nazwę funkcji JavaScript do wykonania w momencie zajścia zdarzenia.

onerror

Tekst zawierający nazwę funkcji JavaScript do wykonania w momencie wystąpienia błędu.

params

Obiekt umożliwiający przekazanie wraz z żądaniem dodatkowych parametrów.

Jeżeli identyfikatory nie zostaną określone, wartością domyślną atrybutu execute stanie się @this, a atrybutu render — @none. W pliku można umieścić metodę JavaScript i dołączyć ją jako zasób.

Użycie adnotacji @ResourceDependency w klasie ziarna Aby klasa ziarna wczytała domyślną bibliotekę jsf.js, użyj adnotacji javax.faces.application.ResourceDependency. Aby wczytać zasób Ajax po stronie serwerowej, użyj metody jsf.ajax.request wewnątrz klasy ziarna. Rozwiązanie to stosuje się najczęściej przy tworzeniu własnych komponentów lub też przy dodawaniu własnego renderera do komponentu.

92

Java EE 6. Zaawansowany przewodnik

Przykładowa aplikacja ajaxguessnumber

Poniższy przykład jest ilustracją wczytywania zasobu z poziomu klasy ziarna: @ResourceDependency(name="jsf.js" library="javax.faces" target="head")

Przykładowa aplikacja ajaxguessnumber Aby zrozumieć zalety oferowane przez technologię Ajax, zajrzyj wcześniej do przykładu guessnumber z rozdziału 5. książki Java EE 6. Przewodnik. Wydanie IV. Jeżeli zmodyfikujesz przykład tak, by korzystał z technologii Ajax, pamiętaj, że odpowiedź nie może być wyświetlona na stronie response.xhtml. Dochodzi wtedy do asynchronicznego wywołania ziarna (ang. bean) po stronie serwera, a odpowiedź jest wyświetlana na oryginalnej stronie tuż po wykonaniu komponentu wejściowego (nie jest potrzebne ponowne wczytanie całej strony WWW). Kod źródłowy aplikacji znajduje się w folderze tut-install/examples/web/ ajaxguessnumber.

Pliki źródłowe Zmiany w aplikacji guessnumber dotyczą dwóch plików źródłowych, a także wprowadzenia pliku JavaScript.

Strona faceletu ajaxgreeting.xhtml Strona faceletu aplikacji ajaxguessnumber (plik web/ajaxgreeting.xhtml) jest niemalże kopią strony greeting.xhtml z aplikacji guessnumber.

Aplikacja faceletowa zgadywania liczby z użyciem technologii ´Ajax



Witaj, mam na imię Duke. Myślę o liczbie w przedziale od #{userNumberBean.minimum} do #{userNumberBean.maximum}. Czy potrafisz ją odgadnąć?





Rozdział 4 y Wykorzystanie technologii Ajax wraz z technologią JavaServer Faces

93

Przykładowa aplikacja ajaxguessnumber



Po wdrożeniu zmodyfikowanej wersji aplikacji zauważysz, że komunikat dotyczący prawidłowej odpowiedzi nadal pojawia się na ekranie nawet po przekazaniu wartości poza zakresem.

Dodatkowe informacje na temat użycia technologii Ajax wraz z technologią JavaServer Faces Dodatkowe informacje na temat użycia technologii Ajax wraz z technologią JavaServer Faces znajdziesz na następujących stronach WWW: „ „

96

witryna projektu JavaServer Faces — http://javaserverfaces.java.net/, strona API biblioteki JavaScript dołączonej do JavaServer Faces — http://javaserverfaces.java.net/nonav/docs/2.1/jsdocs/symbols/jsf.ajax.html.

Java EE 6. Zaawansowany przewodnik

‹

‹

‹

5

ROZDZIAŁ 5

Komponenty złożone — tematy zaawansowane i przykłady

W tym rozdziale omawiamy zaawansowane funkcjonalności złożonych komponentów technologii JavaServer Faces. Komponent złożony to specjalny rodzaj szablonu JavaServer Faces, który działa na zasadach podobnych do zasad działania komponentu. Jeżeli dopiero rozpoczynasz przygodę z komponentami złożonymi, przed rozpoczęciem lektury tego rozdziału przeczytaj podrozdział „Złożone komponenty” książki Java EE 6. Przewodnik. Wydanie IV. W rozdziale: „ Atrybuty komponentu złożonego, „ Wywoływanie zarządzanego ziarna, „ Walidacja wartości komponentu złożonego, „ Przykładowa aplikacja compositecomponentlogin”.

Atrybuty komponentu złożonego Atrybuty komponentu złożonego tworzy się przy użyciu znacznika composite: ´attribute. W tabeli 5.1 zawarliśmy listę najczęściej stosowanych atrybutów tego znacznika. W poniższym fragmencie kodu zdefiniowano atrybut komponentu złożonego i przypisano mu wartość domyślną:

W poniższym fragmencie skorzystano z elementu method-signature:

A tu z elementu type:

Wywoływanie zarządzanego ziarna

Tabela 5.1. Najczęściej stosowane atrybuty znacznika composite:attribute Atrybut

Opis

name

Określa nazwę atrybutu komponentu złożonego stosowaną na stronach, które go wykorzystują. Ewentualnie atrybut name może określać standardowe procedury obsługi zdarzeń, na przykład action, actionListener, a także zarządzane ziarno.

default

Zawiera domyślną wartość atrybutu komponentu złożonego.

required

Wskazuje, czy podanie wartości atrybutu jest wymagane.

method-signature

Określa podklasę klasy java.lang.Object jako typ atrybutu komponentu złożonego. Element method-signature wskazuje, że atrybut komponentu złożonego jest wyrażeniem dotyczącym metody. Atrybuty method-signature i type wykluczają się nawzajem. W przypadku podania obu atrybut method-signature zostanie pominięty. Domyślnym typem atrybutu jest java.lang.Object. Uwaga — wyrażenia metod przypominają wyrażenia wartości, ale zamiast obsługiwać dynamiczne pobieranie i ustawianie właściwości wyrażenia metod obsługują wywoływanie metod dowolnych obiektów i przekazywanie im parametrów, a także przekazanie wyniku wykonania metody (jeśli występuje).

type

Określa w pełni kwalifikowaną nazwę klasy jako typ atrybutu. Atrybuty method-signature i type wykluczają się nawzajem. W przypadku podania obu atrybut method-signature zostanie pominięty. Domyślnym typem atrybutu jest java.lang.Object.

Wywoływanie zarządzanego ziarna Aby umożliwić komponentowi złożonemu obsługę danych po stronie serwera, można wywołać zarządzane ziarno na jeden ze sposobów: „ „

przekazać referencję zarządzanego ziarna do komponentu złożonego, w sposób bezpośredni wykorzystać właściwości zarządzanego ziarna.

Aplikacja omawiana w tym rozdziale, w podrozdziale „Przykładowa aplikacja compositecomponentlogin”, jest ilustracją sposobu użycia zarządzanego ziarna w połączeniu z komponentem złożonym przez przekazanie do komponentu referencji do ziarna.

Walidacja wartości komponentu złożonego JavaServer Faces zapewnia następujące znaczniki dotyczące walidacji wartości komponentów wejściowych. Znaczniki te można wykorzystać w połączeniu ze znacznikami composite:valueHolder i composite:editableValueHolder. W tabeli 5.2 wymieniamy najczęściej używane znaczniki walidatorów.

98

Java EE 6. Zaawansowany przewodnik

Przykładowa aplikacja compositecomponentlogin

Tabela 5.2. Znaczniki walidatorów Nazwa znacznika

Opis

f:validateBean

Przekazuje proces walidacji wartości lokalnej API Bean Validation.

f:validateRegex

Używa atrybutu pattern, by sprawdzić poprawność otaczającego komponentu. Cały wzorzec jest przyrównywany do wartości typu String komponentu. Jeśli pasuje, wartość jest prawidłowa.

f:validateRequired

Wymusza przekazanie wartości. Ma taki sam efekt jak ustawienie elementu required atrybutu komponentu złożonego na wartość true.

Przykładowa aplikacja compositecomponentlogin Aplikacja compositecomponentlogin tworzy komponent złożony, który przyjmuje nazwę użytkownika oraz hasło. Komponent współpracuje z zarządzanym ziarnem, zapamiętuje nazwę użytkownika i hasło w zarządzanym ziarnie, pobiera wartości z ziarna i wyświetla je na stronie logowania. Aplikacja składa się z pliku komponentu złożonego, strony WWW i zarządzanego ziarna. Kod źródłowy aplikacji znajduje się w folderze tut-install/examples/web/ compositecomponentlogin/.

Plik komponentu złożonego Plik komponentu złożonego to plik XHTML umieszczony w lokalizacji /web/resources/ezcomp/LoginPanel.xhtml. Zawiera część composite:interface, która deklaruje etykiety dla nazwy użytkownika, hasła i przycisku logowania. Deklaruje również zarządzane ziarno definiujące właściwości dla nazwy użytkownika i hasła.







Implementacja komponentu złożonego przyjmuje wartości wejściowe dla właściwości nazwy użytkownika i hasła z zarządzanego ziarna:

Rozdział 5 y Komponenty złożone — tematy zaawansowane i przykłady

99

Przykładowa aplikacja compositecomponentlogin





...

Strona wykorzystująca komponent W tym przykładzie stroną WWW wykorzystującą komponent jest plik XHTML (web/index.xhtml) wywołujący komponent złożony logowania wraz z zarządzanym ziarnem. Odpowiada za walidację danych wejściowych.





Znacznik f:validateLength wymaga, by nazwa użytkownika miała od 4 do 10 znaków. Znacznik f:validateRegex wymaga, by hasło miało od 4 do 10 znaków i dodatkowo zawierało przynajmniej jedną cyfrę, jedną małą literę i jedną dużą literę.

Zarządzane ziarno Zarządzane ziarno, src/java/compositecomponentlogin/MyLoginBean.java, definiuje metodę o nazwie login, która pobiera wartości nazwy użytkownika i hasła.

100

Java EE 6. Zaawansowany przewodnik

Przykładowa aplikacja compositecomponentlogin

@ManagedBean @RequestScoped public class MyLoginBean { private String name; private String password; public MyLoginBean() { } public MyLoginBean(String name, String password) { this.name = name; this.password = password; } public String getPassword() { return password; } public void setPassword(String newValue) { password = newValue; } public String getName() { return name; } public void setName(String newValue) { name = newValue; }

}

public String login() { if (getName().equals("javaee")) { String msg = "Sukces. Twoja nazwa użytkownika to " + getName() + ", a Twoje hasło to " + getPassword(); FacesMessage facesMsg = new FacesMessage(msg, msg); FacesContext.getCurrentInstance().addMessage(null, facesMsg); return "index"; } else { String msg = "Porażka. Twoja nazwa użytkownika to " + getName() + ", a Twoje hasło to " + getPassword(); FacesMessage facesMsg = new ´FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg); FacesContext.getCurrentInstance().addMessage(null, facesMsg); return "index"; } }

Uruchomienie przykładu compositecomponentlogin Do zbudowania, spakowania, wdrożenia i uruchomienia przykładu compositecomponentlogin można wykorzystać środowisko NetBeans IDE lub narzędzie Ant.

Rozdział 5 y Komponenty złożone — tematy zaawansowane i przykłady

101

Przykładowa aplikacja compositecomponentlogin

T Budowanie, pakowanie i wdrażanie przykładu

compositecomponentlogin w środowisku NetBeans IDE 1

Z menu File wybierz polecenie Open Project.

2

Po otwarciu okna dialogowego Open Project przejdź do folderu tut-install/ examples/web.

3

Zaznacz folder compositecomponentlogin.

4

Kliknij przycisk Open Project.

5

Przejdź do zakładki Projects. Kliknij prawym przyciskiem myszy compositecomponentlogin i z menu wybierz polecenie Deploy.

T Budowanie, pakowanie i wdrażanie przykładu

compositecomponentlogin za pomocą narzędzia Ant 1

W oknie terminalu przejdź do poniższej lokalizacji:

tut-install/examples/web/compositecomponentlogin/ 2

Wpisz następujące polecenie: ant

3

Wpisz następujące polecenie: ant deploy

T Uruchomienie przykładu compositecomponentlogin 1

W przeglądarce internetowej wpisz adres URL: http://localhost:8080/compositecomponentlogin/

Pojawi się strona z komponentem logowania. 2

Wpisz wartości w pola tekstowe nazwy użytkownika oraz hasła, a następnie kliknij przycisk Zaloguj się.

Kod metody login został napisany w ten sposób, że logowanie powiedzie się, jeśli jako nazwę użytkownika podasz nazwę javaee. Jeśli nazwa użytkownika ma mniej niż 4 znaki lub więcej niż 10 znaków, z powodu użycia znacznika f:validateLength pojawi się komunikat o błędzie. Jeśli hasło ma mniej niż 4 znaki lub więcej niż 10 znaków albo nie zawiera przynajmniej jednej cyfry, jednej dużej liter i jednej małej litery, z powodu użycia znacznika f:validateRegex pojawi się komunikat Regex Pattern not matched.

102

Java EE 6. Zaawansowany przewodnik

‹

‹

‹

6

ROZDZIAŁ 6

Tworzenie własnych komponentów UI i innych obiektów

Technologia JavaServer Faces zapewnia podstawowy zestaw komponentów interfejsu użytkownika do wielokrotnego użytku, dzięki którym można szybko i łatwo tworzyć interfejsy użytkownika dla aplikacji internetowych. Większość komponentów to odwzorowania jeden-do-jednego elementów HTML 4. Często zdarza się, że w aplikacji wymagany jest komponent posiadający dodatkową funkcjonalność lub też potrzebny całkowicie nowy komponent. Technologia JavaServer Faces dopuszcza rozszerzanie standardowych komponentów w celu dodania do nich nowych funkcjonalności. Możliwe jest również tworzenie całkowicie nowych komponentów. Bogaty ekosystem bibliotek komponentów zewnętrznych firm bazuje na wspomnianej możliwości tworzenia własnych komponentów, ale jego dokładny opis wykracza poza ramy tej książki. Dobrym punktem początkowym będzie wyszukanie w wyszukiwarce internetowej frazy „JSF Component Libraries” i poznanie tego istotnego aspektu technologii JavaServer Faces. Twórca komponentu, poza rozszerzaniem funkcjonalności standardowych komponentów, może także ułatwić autorowi strony zmianę wyglądu lub zachowania komponentu na stronie WWW. Ewentualnie twórca komponentu może zechcieć renderować komponent w inny sposób dla różnego rodzaju urządzeń, na przykład wyświetlać komponent inaczej dla smartfonów i tabletów, a inaczej dla tradycyjnych komputerów. Korzystając z elastycznej architektury JavaServer Faces, twórca ma możliwość oddzielenia definicji zachowania komponentu od jego wyglądu przez oddelegowanie renderingu komponentu do osobnej klasy renderującej. W ten sposób twórca komponentu definiuje jego zachowanie tylko jeden raz, ale tworzy wiele rendererów, które odpowiadają za renderowanie komponentu w sposób najlepiej dostosowany do konkretnego urządzenia. Klasa javax.faces.component.UIComponent odpowiada za reprezentację pojedynczego, niezależnego elementu interfejsu użytkownika w trakcie cyklu życia przetwarzania żądania. Jej celem istnienia jest reprezentacja znaczenia komponentu — za wizualną stronę komponentu odpowiada klasa javax.faces. ´render.Renderer. Pojedynczy widok JavaServer Faces może zawierać wiele instancji tej samej klasy UIComponent, podobnie jak dowolny program Javy zawiera wiele instancji dowolnych klas.

Określanie, czy potrzebny jest własny komponent lub renderer

Technologia JavaServer Faces dopuszcza tworzenie własnych komponentów przez rozszerzanie klasy UIComponent, która stanowi klasę bazową dla wszystkich standardowych komponentów interfejsu użytkownika. Własny komponent może pojawić się we wszystkich miejscach, w których dopuszcza się wystąpienie komponentu standardowego (również jako składnika komponentu złożonego). Klasę UIComponent identyfikują dwie nazwy: component-family określa ogólny cel istnienia komponentu (na przykład, czy jest to komponent wejściowy, czy wyjściowy), a component-type określa szczegółowy cel istnienia, na przykład wejściowe pole tekstowe lub przycisk polecenia. Klasa Renderer to element pomocniczy klasy UIComponent, której zadaniem jest określanie, w jaki sposób konkretna klasa UIComponent będzie wyglądała na danym urządzeniu. Podobnie jak komponenty, także renderery identyfikują dwie nazwy: render-kit-id i renderer-type. Zestaw rendererów (ang. render kit) to po prostu zestaw, do którego przynależy konkretna grupa rendererów; reprezentuje ją identyfikator render-kit-id. Większość bibliotek komponentów JavaServer Faces udostępnia własne zestawy rendererów. Obiekt znacznika javax.faces.view.facelets.Tag to pomocnik klas UIComponent i Renderer, który umożliwia twórcy strony dołączenie instancji UIComponent do widoku JavaServer Faces. Znacznik reprezentuje konkretną kombinację component-type i renderer-type. Więcej informacji na temat współdziałania komponentów, rendererów i znaczników podajemy w tym rozdziale, w punkcie „Kombinacje komponentów, rendererów i znaczników”. W tym rozdziale wykorzystamy komponent mapy obrazu z przypadku użycia nazwanego księgarnią Duke’a, by wyjaśnić zasady tworzenia własnych komponentów, rendererów i powiązanych z nimi własnych znaczników, a także omówić wszystkie kwestie dotyczące wykorzystania takich komponentów i rendererów w aplikacji. Więcej informacji na temat przykładu można znaleźć w rozdziale 25., „Przykładowy scenariusz użycia — księgarnia Duke’a”. W rozdziale zawarliśmy również wyjaśnienia dotyczące tworzenia innych obiektów własnego typu: konwerterów, klas nasłuchujących i walidatorów. Omawiamy także sposoby powiązania wartości komponentów i instancji z obiektów danych, a także sposoby powiązania własnych obiektów z właściwościami zarządzanych ziaren. W rozdziale: „ „ „ „ „ „ „

104

Określanie, czy potrzebny jest własny komponent lub renderer, Analiza przykładu z mapą obrazu, Kroki niezbędne do utworzenia własnego komponentu, Tworzenie własnych klas komponentów, Przekazanie renderowania do renderera, Implementacja klasy nasłuchiwania zdarzeń, Obsługa zdarzeń dla samodzielnie wykonanych komponentów,

Java EE 6. Zaawansowany przewodnik

Określanie, czy potrzebny jest własny komponent lub renderer

„ „ „ „ „

„

Definicja znacznika komponentu własnego w deskryptorze biblioteki znaczników, Użycie własnego komponentu, Utworzenie i użycie własnego konwertera, Utworzenie i użycie własnego walidatora, Wiązanie wartości i instancji komponentów z właściwościami zarządzanego ziarna, Wiązanie konwerterów, walidatorów i obsługi zdarzeń z właściwościami zarządzanego ziarna.

Określanie, czy potrzebny jest własny komponent lub renderer Implementacja JavaServer Faces obsługuje bardzo prosty zestaw komponentów i powiązanych z nim rendererów. W tym podrozdziale wyjaśnimy, w jaki sposób zdecydować, czy zastosować standardowy komponent i renderer, czy raczej tworzyć własny komponent bądź też renderer.

Kiedy użyć własnego komponentu? Klasa komponentu definiuje stan i zachowanie komponentu interfejsu użytkownika. Zachowanie dotyczy takich aspektów jak konwersja wartości komponentu do odpowiednich znaczników, zakolejkowanie zdarzeń w komponentach, przeprowadzenie walidacji i dowolnego innego zachowania powiązanego ze sposobem interakcji komponentu z przeglądarką i cyklem życia przetwarzanego żądania. Tworzenie własnych komponentów jest zalecane w następujących sytuacjach. „

„

„

Konieczne jest dodanie do standardowego komponentu nowego zachowania, takiego jak generowanie nowego rodzaju zdarzenia (na przykład konieczność poinformowania pozostałej części strony, że komponent uległ zmianie z powodu pewnej interakcji użytkownika). Konieczne jest w trakcie przetwarzania żądania dotyczącego wartości komponentu podjęcie akcji innej niż ta, która jest zdefiniowana w istniejących już komponentach. Chcesz skorzystać ze specyficznych możliwości HTML oferowanych przez docelową przeglądarkę, ale żaden ze standardowych komponentów JavaServer Faces nie zapewnia obsługi w sposób odpowiedni dla danego zadania. Aktualne wydanie nie zawiera standardowych komponentów powiązanych z zaawansowanymi elementami HTML, na przykład ramkami. Dzięki elastycznej architekturze komponentów nic nie stoi na przeszkodzie, by samodzielnie wykonać niezbędne komponenty. W przykładzie użycia zwanym księgarnią Duke’a tworzone są własne komponenty, które odpowiadają znacznikom HTML map i area.

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

105

Określanie, czy potrzebny jest własny komponent lub renderer

„

Rendering odbywa się dla klienta niezwiązanego z HTML, który wymaga użycia nietypowych komponentów. Za jakiś czas standardowy zestaw rendererów HTML będzie obsługiwał wszystkie standardowe komponenty HTML. Jeśli jednak rendering dotyczy specyficznego klienta, na przykład telefonu, konieczne może okazać się wykonanie nietypowych komponentów zawierających elementy specyficzne dla tego klienta. Przykładem mogą być tutaj komponenty architektury bezprzewodowej zawierające obsługę pasków postępu i znakowania, które nie są dostępne w standardowych klientach HTML. W takiej sytuacji do komponentu trzeba będzie dołączyć własny renderer. Czasem nawet wystarczy jedynie zmiana domyślnego renderera na własny.

Oto przypadki, kiedy nie jest konieczne tworzenie własnego komponentu. „

„

„

„

„

106

Trzeba połączyć komponenty w celu utworzenia nowego komponentu posiadającego własne, unikatowe zachowanie. W takiej sytuacji wystarczające okazuje się użycie komponentu złożonego, który łączy kilka komponentów standardowych. Więcej informacji na ten temat zawarto w podrozdziale „Złożone komponenty”, w książce Java EE 6. Przewodnik. Wydanie IV i w tej książce, w rozdziale 5., „Komponenty złożone — tematy zaawansowane i przykłady”. Wystarczy modyfikacja danych komponentu lub dodanie funkcjonalności specyficznej dla komponentu. W takiej sytuacji należy utworzyć zarządzane ziarno i dołączyć je do standardowego komponentu, zamiast tworzyć własny komponent. Więcej informacji na temat zarządzanych ziaren podano w podrozdziale „Backing beany”, w książce Java EE 6. Przewodnik. Wydanie IV. Trzeba wykonać konwersję danych komponentu do typu nieobsługiwanego przez jego renderer. Więcej informacji na temat konwersji danych komponentu zawiera podrozdział „Używanie standardowych konwerterów” książki Java EE 6. Przewodnik. Wydanie IV. Dane komponentu wymagają walidacji. Zarówno standardowe, jak i własne walidatory można dodać do komponentu, wykorzystując na stronie znaczniki walidatora. Więcej informacji na ten temat podano w podrozdziale „Używanie standardowych konwerterów”, w książce Java EE 6. Przewodnik. Wydanie IV, a także w tym rozdziale, w podrozdziale „Utworzenie i użycie własnego konwertera”. Trzeba zarejestrować nasłuchiwanie zdarzeń dla komponentu. Można to zadanie zrealizować, wykorzystując znaczniki f:valueChangeListenerand i f:actionListener, lub wskazać metodę obsługującą zdarzenie w zarządzanym ziarnie z wykorzystaniem atrybutów actionListener lub valueChangeListener komponentu. Więcej informacji na ten temat znajdziesz w tym rozdziale, w podrozdziale „Implementacja klasy nasłuchiwania zdarzeń” i w podrozdziale „Tworzenie metod backing beana”, w książce Java EE 6. Przewodnik. Wydanie IV.

Java EE 6. Zaawansowany przewodnik

Określanie, czy potrzebny jest własny komponent lub renderer

Kiedy zastosować własny renderer? Renderer, czyli kod odpowiedzialny za wygenerowanie znaczników zapewniających wyświetlenie komponentu na stronie internetowej, umożliwia oddzielenie semantyki komponentu od jego wyglądu. Stosując to rozdzielenie, łatwiej obsłużyć różne rodzaje urządzeń przy zachowaniu tego samego sposobu tworzenia i używania komponentów. Renderer można traktować jak „adapter klienta”. Tworzy wynik odpowiedni do użycia i wyświetlenia przez klienta, a także w odpowiedni sposób przyjmuje dane od klienta, gdy ten wchodzi z komponentem w interakcję. Tworząc własny komponent, trzeba między innymi upewnić się, że klasa komponentu realizuje operacje niezbędne do prawidłowego renderingu, takie jak: „

„

dekodowanie — w czasie którego konwertowane są nadchodzące parametry żądania do lokalnej wartości komponentu, kodowanie — kiedy konwertowana jest wartość lokalna z komponentu na kod umieszczany w odpowiedzi.

Specyfikacja JavaServer Faces obsługuje dwa modele programowania dotyczące kodowania i dekodowania: „

„

implementacja bezpośrednia — klasa komponentu implementuje kodowanie i dekodowanie, implementacja delegowana — klasa komponentu deleguje implementację kodowania i dekodowania do osobnego renderera.

Delegowanie operacji do renderera ułatwia powiązanie własnego komponentu z różnymi rendererami, a tym samym znacznie upraszcza obsługę różnych klientów. Jeżeli nie jest planowane renderowanie konkretnego komponentu dla różnych klientów, renderowanie wyniku bezpośrednio przez komponent będzie prostsze w realizacji. Oczywiście, osobny renderer ułatwia odseparowanie semantyki od wyglądu. W przykładzie o nazwie księgarnia Duke’a renderery oddzielane są od komponentów, choć wynikowy kod dotyczy tylko przeglądarek obsługujących HTML 4. Jeżeli nie jesteś pewien, czy będziesz potrzebował elastyczności zapewnianej przez osobne renderery i chcesz użyć prostszego rozwiązania z implementacją bezpośrednią, nic nie stoi na przeszkodzie, by skorzystać z obu modeli. Klasa komponentu może zawierać domyślny kod renderujący i jednocześnie obsługiwać delegację, jeśli twórca strony wskaże zewnętrzny renderer.

Kombinacje komponentów, rendererów i znaczników Tworząc własny komponent, można jednocześnie zbudować powiązany z nim renderer. Aby powiązać komponent z rendererem i umożliwić utworzenie odnośnika do komponentu na stronie, potrzebny będzie własny znacznik.

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

107

Analiza przykładu z mapą obrazu

Choć należy napisać kod własnego komponentu i renderera, nie trzeba pisać kodu dla własnego znacznika (nazywanego procedurą obsługi znacznika). Podczas określania odpowiedniej kombinacji komponentu i renderera implementacja faceletów automatycznie utworzy odpowiednią procedurę obsługi znacznika. W rzadkich sytuacjach może zajść konieczność użycia własnego renderera w połączeniu z komponentem standardowym (zamiast własnego autorstwa). W tym punkcie przedstawimy przykłady takich sytuacji i omówimy elementy niezbędne do utworzenia własnego komponentu, własnego renderera i własnego znacznika. Przykład użycia własnego renderera w połączeniu ze standardowym komponentem dotyczy sytuacji, takich jak chęć wprowadzenia własnej walidacji po stronie klienta. Kod walidujący zostanie zaimplementowany w języku skryptowym JavaScript, a następnie zrenderowany przy użyciu własnego renderera. W takiej sytuacji niezbędny będzie własny znacznik dla renderera, by jego procedura obsługi mogła zarejestrować renderer dla standardowego komponentu. Własne komponenty, jak i własne renderery wymagają powiązanych z nimi własnych znaczników. Można jednak utworzyć własny znacznik bez własnego komponentu lub renderera. Przypuśćmy, że trzeba wykonać własny walidator wymagający dodatkowych atrybutów w swoim znaczniku. W takiej sytuacji własny znacznik dotyczy własnego walidatora i nie ma związku z komponentem lub rendererem. W każdej sytuacji niezbędne jest powiązanie własnego znacznika z obiektem po stronie serwera. W tabeli 6.1 podsumowujemy to, co trzeba, i to, co można powiązać z własnymi komponentem, rendererem lub znacznikiem. Tabela 6.1. Wymagania własnych znaczników, rendererów i komponentów Własny element

Musi mieć

Może mieć

własny komponent

własny znacznik

własny lub standardowy renderer

własny renderer

własny znacznik

własny lub standardowy komponent

własny znacznik JavaServer Faces

obiekt po stronie serwera, na przykład komponent, własny renderer lub walidator twórcy aplikacji

własny lub standardowy komponent powiązany z własnym rendererem

Analiza przykładu z mapą obrazu Księgarnia Duke’a zawiera niestandardowy komponent mapy obrazu na stronie index.xhtml. Mapa obrazu umożliwia wybór jednego z sześciu tytułów książek. Gdy użytkownik kliknie jeden z tytułów na mapie obrazu, aplikacja wyświetla stronę ze szczegółami wybranego tytułu oraz informacje o polecanej pozycji książkowej. Strona umożliwia użytkownikowi dodanie którejkolwiek książki do koszyka.

108

Java EE 6. Zaawansowany przewodnik

Analiza przykładu z mapą obrazu

Dlaczego mam korzystać z technologii JavaServer Faces do implementacji mapy obrazu? Technologia JavaServer Faces to idealny framework do wykorzystania przy implementacji mapy obrazu, ponieważ może wykonać niezbędne zadania po stronie serwera bez potrzeby korzystania z serwerowej wersji mapy obrazu. Z kilku powodów mapy obrazu po stronie klienta są bardziej preferowane od map obrazu po stronie serwera. Jednym z nich jest natychmiastowa informacja zwrotna, gdy użytkownik umieści kursor myszy nad fragmentem z przypisaną akcją. Innym powodem jest fakt, że mapy obrazu po stronie klienta są wydajniejsze, bo w odróżnieniu od map obrazu po stronie serwera nie wymagają kontaktu z serwerem. Czasem zdarzają się jednak sytuacje, w których mapa obrazu musi skorzystać z serwera, by pobrać dane lub zmienić kontrolki niezwiązane z formularzem (zadania te są niedostępne dla mapy obrazu po stronie klienta). Ponieważ własny komponent mapy obrazu korzysta z technologii JavaServer Faces, ma dostęp do zalet obu typów map obrazu — potrafi obsłużyć część aplikacji, która musi zostać wykonana po stronie serwera, a jednocześnie dopuszcza realizację innych części aplikacji po stronie klienta.

Działanie zrenderowanego kodu HTML Oto nieco skrócona wersja formularza ze strony HTML, który aplikacja musi zrenderować:

...

...

...

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

109

Analiza przykładu z mapą obrazu

...

Znacznik img łączy obraz (book_all.jpg) z mapą obrazu wskazaną w atrybucie usemap. Znacznik map definiuje mapę obrazu i zawiera zestaw znaczników area. Każdy ze znaczników area określa obszar na mapie obrazu. Atrybuty onmouseover, i onclick wskazują kod JavaScript, który należy wykonać w momencie zajścia odpowiedniego zdarzenia. Gdy kursor myszy znajdzie się nad obszarem, wykonana zostanie funkcja wskazana przez onmouseover, a wskazany obszar podświetlony. Gdy użytkownik przesunie kursor myszy poza aktualny region, funkcja onmouseout ponownie wyświetli oryginalny obraz. Jeżeli użytkownik kliknie konkretny region, funkcja onclick ustawi wartość znacznika input na identyfikator wybranego obszaru i wyśle ukryty formularz do serwera.

onmouseout

Znacznik input to ukryta kontrolka, która przechowuje wartość aktualnie zaznaczonego obszaru podczas wymianami danych pomiędzy serwerem i klientem. Dzięki temu klasy komponentów po stronie serwera mogą pobrać identyfikator wybranego przez użytkownika regionu. Obiekty po stronie serwera pobierają wartość bookMap_current i ustawiają ją w instancji javax.faces.context.FacesContext zgodnie z wyborem użytkownika.

Omówienie strony faceletu Poniżej znajduje się skrócona treść strony faceletu, którą komponent mapy obrazu wykorzystuje do wygenerowania strony HTML omawianej w poprzednim punkcie. Do uruchomienia niestandardowych komponentów wykorzystuje własne znaczniki bookstore:map i bookstore:area.

...



Atrybut alt znacznika h:graphicImage dotyczy odpowiedniej wersji językowej tekstu "Wybierz książkę z katalogu". Znacznik f:actionListener wewnątrz znacznika bookstore:map wskazuje klasę nasłuchiwania dla zdarzenia akcji. Metoda processAction klasy umieszcza identyfikator książki dla wybranego obszaru mapy w danych sesji. Wyjaśnienie szczegółów obsługi zdarzenia znajduje się w tym rozdziale, w podrozdziale „Obsługa zdarzeń dla samodzielnie wykonanych komponentów”. Atrybut action znacznika bookstore:map wskazuje na wynik typu String — "bookstore", który dzięki domyślnym regułom nawigacji przeniesie użytkownika do strony bookstore.xhtml. Więcej informacji na ten temat zawiera podrozdział „Konfiguracja reguł nawigacyjnych” z rozdziału 7. Atrybut immediate znacznika bookstore:map zawiera wartość true, co oznacza, że domyślna implementacja javax.faces.event.ActionListener powinna zostać wykonana w trakcie fazy stosowania wartości żądania cyklu życia, a nie w fazie wywołania aplikacji. Ponieważ żądanie wynikające z kliknięcia mapy nie wymaga żadnej walidacji, konwersji danych lub aktualizacji obiektów po stronie serwera, sensowne wydaje się natychmiastowe przejście do fazy wywołania aplikacji. Atrybut current znacznika map:bookstore jest ustawiony na obszar domyślny, czyli map1 (patrz książka My Early Years: Growing Up on Star7 autorstwa Duke’a). Zauważ, że znaczniki bookstore:area nie zawierają żadnego kodu JavaScript, współrzędnych i rodzaju kształtu, który pojawił się w kodzie HTML. Kod JavaScript generuje klasa dukesbookstore.renderers.AreaRenderer. Atrybuty onmouseover i onmouseout wskazują obrazy, które należy wczytać w momencie zajścia wskazanego zdarzenia. Sposób generowania kodu JavaScript wyjaśniamy w tym rozdziale, w punkcie „Przeprowadzenie kodowania”. Dane dotyczące współrzędnych, kształtu i tekstu alternatywnego pochodzą z atrybutu value, którego wartość odnosi się do atrybutu w zasięgu aplikacji. Wartością atrybutu jest ziarno przechowujące dane coords, shape i alt. Sposób przechowywania ziaren w zasięgu aplikacji wyjaśniamy nieco dokładniej w następnym punkcie.

Konfiguracja danych modelu W aplikacji JavaServer Faces dane, takie jak współrzędne istotnych punktów mapy obrazu, pobiera się z atrybutu value za pomocą ziarna. Kształt i współrzędne fragmentu obrazu powinno się definiować razem, ponieważ współrzędne są interpretowane w różny sposób w zależności od rodzaju kształtu. Ponieważ wartość komponentu można powiązać tylko z jedną właściwością, atrybut value nie może odnosić się jednocześnie do kształtu i współrzędnych.

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

111

Analiza przykładu z mapą obrazu

By rozwiązać przedstawiony problem, aplikacja przechowuje wszystkie informacje wewnątrz zestawu obiektów ImageArea. Inicjalizacja obiektów przebiega w zasięgu aplikacji dzięki mechanizmowi tworzenia zarządzanych ziaren (patrz podrozdział „Backing beany”, w książce Java EE 6. Przewodnik. Wydanie IV). Poniżej znajduje się deklaracja zarządzanego ziarna dla ImageArea odpowiadająca obszarowi Ameryki Południowej:

... Book201 dukesbookstore.model.ImageArea / ´managed-bean-class> application

... shape rect

... alt Duke

... coords 67,23,212,268

Więcej informacji na temat inicjalizacji zarządzanych ziaren przy użyciu mechanizmu tworzenia zarządzanych ziaren zawiera podrozdział „Plik zasobów konfiguracyjnych aplikacji” z rozdziału 7. Atrybuty value znaczników bookstore:area odnoszą się do ziaren w zasięgu aplikacji, co obrazuje znacznik umieszczony w pliku index.xhtml.

Aby odnieść się do wartości obiektu ziarna ImageArea z klasy komponentu, trzeba zaimplementować w klasie komponentu metodę getValue. Metoda wywołuje metodę super.getValue. Klasa nadrzędna dla tut-install/examples/case-studies/ dukes-bookstore/src/java/dukesbookstore/components/AreaComponent.java — UIOutput — zawiera metodę getValue, która odpowiada za odnalezienie obiektu ImageArea powiązanego z AreaComponent. Klasa AreaRenderer, która ma za zadanie zrenderować wartości alt, shape i coords z obiektu ImageArea, wywołuje metodę getValue klasy AreaComponent, by uzyskać obiekt ImageArea. ImageArea iarea = (ImageArea) area.getValue();

Klasa ImageArea to proste ziarno, więc dostęp do danych kształtu, współrzędnych i tekstu alternatywnego odbywa się przez wywołanie odpowiedniej metody dostępowej. W tym rozdziale, w punkcie „Tworzenie klasy renderera” wyjaśniamy, jak wykonać to zadanie dla klasy AreaRenderer.

112

Java EE 6. Zaawansowany przewodnik

Kroki niezbędne do utworzenia własnego komponentu

Podsumowanie klas mapy obrazu W tabeli 6.2 podsumowujemy wszystkie klasy niezbędne do implementacji komponentu mapy obrazu. Tabela 6.2. Klasy mapy obrazu Klasa

Funkcja

AreaSelectedEvent

Zdarzenie javax.faces.event.ActionEvent wskazujące, że wybrano AreaComponent z MapComponent.

AreaComponent

Klasa definiująca komponent obszaru, który odpowiada własnemu znacznikowi bookstore:area.

MapComponent

Klasa definiująca komponent mapy, który odpowiada własnemu znacznikowi bookstore:map.

AreaRenderer

Klasa bazująca na javax.faces.render.Renderer. Przeprowadza delegowany rendering komponentu dla AreaComponent.

ImageArea

Ziarno przechowujące kształt i współrzędne obszaru.

MapBookChangeListener

Klasa nasłuchiwania zdarzenia akcji dla MapComponent.

Załóżmy, że bookstore-dir oznacza folder źródłowy aplikacji księgarni Duke’a, który jest dostępny w lokalizacji tut-install/examples/case-studies/dukes-bookstore/ src/java/dukesbookstore/. Klasy zdarzeń i nasłuchiwania znajdują się w folderze bookstore-dir/listeners/. Klasy komponentów umieszczone są w folderze bookstore-dir/components/, klasy rendererów — w folderze bookstore-dir/ renderers/. Klasa ImageArea znajduje się w folderze bookstore-dir/model/.

Kroki niezbędne do utworzenia własnego komponentu Tworząc własny komponent, korzystaj z następujących kroków. 1. Utwórz klasę własnego komponentu, która wykonuje następujące zadania. a. Przesłania metodę getFamily, by zwracać odpowiednią rodzinę komponentu służącą do wyszukiwania rendererów, które mogą posłużyć do wyświetlenia komponentu. b. Zawiera kod renderujący lub deleguje renderowanie do renderera (patrz krok 2.). c. Umożliwia atrybutom komponentu przyjmowanie wyrażeń. d. Kolejkuje zdarzenie komponentu, jeśli komponent generuje zdarzenia. e. Zapisuje i przywraca stan komponentu. 2. Deleguj rendering do odpowiedniej klasy renderera, jeśli komponent nie obsługuje renderowania samodzielnie. W tym celu wykonaj dodatkowe kroki.

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

113

Tworzenie własnych klas komponentów

a. Utwórz klasę własnego renderera dziedziczącą po javax.faces.render. ´Renderer. b. Zarejestruj renderer w zestawie renderującym. 3. Zarejestruj komponent. 4. Utwórz system obsługi zdarzeń, jeśli komponent generuje zdarzenia. 5. Utwórz deskryptor biblioteki znaczników (TLD) definiujący własny znacznik. Więcej informacji na temat rejestracji własnych komponentów i rendererów znajdziesz w podrozdziałach „Rejestracja własnego komponentu” i „Rejestracja własnego renderera w zestawie rendererów” z rozdziału 7. Opis użycia własnego komponentu na stronie JavaServer Faces znajduje się w tym rozdziale, w podrozdziale „Użycie własnego komponentu”.

Tworzenie własnych klas komponentów Zgodnie z opisem w punkcie „Kiedy użyć własnego komponentu?”, który znajduje się w tym rozdziale, klasa komponentu definiuje stan i zachowanie komponentu UI. Informacje o stanie dotyczą typu komponentu, jego identyfikatora i wartości lokalnej. Zachowanie definiowane przez klasę komponentu dotyczy następujących aspektów: „ „

„ „ „ „

dekodowania (konwersji parametru żądania do wartości lokalnej komponentu), kodowania (konwersji wartości lokalnej na odpowiednie znaczniki lub wartości HTML), zapisu stanu komponentu, aktualizacji wartości ziarna na podstawie wartości lokalnej, przeprowadzenia walidacji wartości lokalnej, kolejkowania zdarzeń.

Klasa javax.faces.component.UIComponentBase definiuje domyślne zachowanie klasy komponentu. Wszystkie klasy związane ze standardowymi komponentami dziedziczą po klasie UIComponentBase. Klasy te, podobnie jak własna klasa, dodają własne definicje zachowań. Klasa własnego komponentu musi albo bezpośrednio dziedziczyć po klasie albo rozszerzać jedną z klas standardowych komponentów. Klasy te znajdują się w pakiecie javax.faces.component, a ich nazwy rozpoczynają się od UI.

UIComponentBase,

Jeżeli własny komponent wykonuje zadania podobne do standardowych komponentów, lepiej rozszerzyć jeden z już istniejących komponentów, zamiast bezpośrednio dziedziczyć po UIComponentBase. Przypuśćmy, że chcemy wykonać komponent edytowalnego menu. W takiej sytuacji większy sens ma dziedziczenie po UISelectOne, a nie po UIComponentBase, ponieważ najprawdopodobniej będzie można ponownie użyć części zachowań zdefiniowanych w UISelectOne. By menu stało się edytowalne, trzeba zmienić jedynie kilka funkcjonalności.

114

Java EE 6. Zaawansowany przewodnik

Tworzenie własnych klas komponentów

Niezależnie od tego, czy UIComponentBase rozszerza własny komponent, czy któryś z komponentów standardowych, warto zastanowić się, czy nie powinien on również implementować jednego lub kilku interfejsów zachowań zdefiniowanych w pakiecie javax.faces.component. Oto one. „

„

„

„

„

„

ActionSource — wskazuje, że komponent może zgłosić zdarzenie akcji (javax.faces.event.ActionEvent). ActionSource2 — rozszerza ActionSource i umożliwia właściwościom komponentów użycie EL w momencie tworzenia referencji do metod obsługujących zdarzenia akcji. EditableValueHolder — rozszerza ValueHolder i określa dodatkowe funkcjonalności dotyczące edytowalnych komponentów, na przykład walidację lub zgłaszanie zdarzeń zmiany wartości. NamingContainer — wskazuje, że każdy komponent, którego korzeniem jest ten komponent, posiada unikatowy identyfikator. StateHolder — wskazuje, iż komponent zawiera informacje o stanie, które należy zapisać między żądaniami. ValueHolder — wskazuje, że komponent przechowuje lokalną wartość, a także może mieć dostęp do danych z warstwy modelu.

Jeżeli własny komponent dziedziczy bezpośrednio po UIComponentBase, automatycznie implementuje jedynie StateHolder. Ponieważ wszystkie komponenty bezpośrednio lub pośrednio dziedziczą po UIComponentBase, wszystkie implementują StateHolder. Wszystkie komponenty implementujące StateHolder implementują również interfejs StateHelper, który rozszerza StateHolder i definiuje rozwiązanie przypominające odwzorowanie, które ułatwia komponentom zapis i odtworzenie części stanu widoku. Jeśli własny komponent rozszerza jeden z innych komponentów standardowych, może automatycznie implementować inne interfejsy zachowań poza standardowym StateHolder. Jeśli komponent rozszerza UICommand, automatycznie implementuje ActionSource2. Jeśli rozszerza UIOutput lub jedną z klas komponentów bazujących na UIOutput, automatycznie implementuje ValueHolder. Jeśli komponent rozszerza UIInput, automatycznie implementuje EditableValueHolder i ValueHolder. Zajrzyj do dokumentacji API JavaServer Faces, by dowiedzieć się, co implementują inne klasy komponentów. Nic nie stoi na przeszkodzie, by we własnym komponencie jawnie wskazać dodatkowy interfejs zachowań, który nie wynika z samego łańcucha dziedziczeń. Kiedy tworzony komponent rozszerza UIInput, a zamierzasz zgłaszać zdarzenia akcji, musisz jawnie zaimplementować interfejs ActionSource2, ponieważ komponent UIInput nie implementuje go domyślnie. Mapa obrazu z przykładu księgarni Duke’a wykorzystuje dwie klasy komponentów: AreaComponent i MapComponent. Klasa MapComponent rozszerza klasę UICommand, więc implementuje ActionSource2. Oznacza to, że może zgłaszać zdarzenia akcji, gdy użytkownik kliknie mapę obrazu. Klasa AreaComponent rozszerza standardowy komponent UIOutput. Adnotacja @FacesComponent rejestruje komponenty w implementacji JavaServer Faces:

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

115

Tworzenie własnych klas komponentów

@FacesComponent("DemoMap") public class MapComponent extends UICommand {...} @FacesComponent("DemoArea") public class AreaComponent extends UIOutput {...}

Klasa MapComponent dotyczy komponentu wskazywanego przez znacznik bookstore:map:

...

Klasa AreaComponent dotyczy komponentu wskazywanego przez znacznik bookstore:area:

Obiekt MapComponent zawiera jeden lub więcej obiektów AreaComponent. Jego zachowanie składa się z elementów, takich jak: „ „ „ „ „ „

pobranie wartości aktualnie wybranego obszaru, zdefiniowanie właściwości związanych z wartościami komponentu, generowanie zdarzenia, gdy użytkownik kliknie mapę obrazu, kolejkowanie zdarzeń, zapisanie stanu, zrenderowanie znaczników map i input w HTML.

Klasa MapComponent deleguje rendering znaczników map i input do klasy MapRenderer. Klasa AreaComponent jest powiązana z ziarnem przechowującym kształt i współrzędne regionu mapy. Sposób dostępu do wszystkich danych zostanie omówiony w tym rozdziale, w punkcie „Tworzenie klasy renderera”. Działanie AreaComponent składa się z następujących elementów: „ „ „

pobrania danych kształtu i współrzędnych z obiektu ziarna, ustawienia wartości ukrytego znacznika na wartość id komponentu, renderingu znacznika area, włącznie z funkcjami JavaScript onmouseover, onmouseout i onclick.

Choć te zadania są wykonywane przez klasę AreaRenderer, klasa AreaComponent musi je w odpowiedni sposób delegować. Szczegóły zostały opisane w tym rozdziale, w podrozdziale „Przekazanie renderowania do renderera”. W pozostałej części podrozdziału opisujemy zadania wykonywane przez MapComponent, a także kodowanie i dekodowanie delegowane do klasy MapRenderer.

116

Java EE 6. Zaawansowany przewodnik

Tworzenie własnych klas komponentów

W tym rozdziale, w podrozdziale „Obsługa zdarzeń dla samodzielnie wykonanych komponentów” opisujemy sposób obsługi zdarzeń przez MapComponent.

Określenie rodziny komponentu Jeśli klasa własnego komponentu deleguje rendering, musi zapewnić własną wersję metody getFamily, zdefiniowaną oryginalnie w klasie UIComponent, by zwrócić identyfikator rodziny komponentu. Wykorzystuje się go jako odnośnik do komponentu (lub ich zbioru), który można zrenderować przy użyciu konkretnego renderera (lub ich grupy). Rodzina komponentu wraz z rodzajem renderera służy do wyszukania odpowiedniego renderera dla komponentu: public String getFamily() { return ("Map"); }

Identyfikator rodziny komponentów — Map — musi odpowiadać elementom component-family umieszczonym w konfiguracjach komponentów i rendererów pliku zasobu konfiguracji aplikacji. W podrozdziale „Rejestracja własnego renderera w zestawie rendererów” z rozdziału 7. wyjaśniamy, w jaki sposób zdefiniować rodzinę komponentu w konfiguracji renderera. Podrozdział „Rejestracja własnego komponentu” z rozdziału 7. opisuje sposób definicji rodziny komponentu w konfiguracji komponentu.

Przeprowadzenie kodowania W trakcie fazy renderowania odpowiedzi implementacja JavaServer Faces uruchamia w widoku metody kodujące wszystkich komponentów i powiązanych z nimi rendererów. Metody dekodujące konwertują aktualne wartości lokalne komponentów na odpowiednie znaczniki lub wartości przesyłane do klienta jako odpowiedź. Klasa UIComponentBase definiuje zbiór metod dotyczących renderowania znaczników: encodeBegin, encodeChildren i encodeEnd. Jeśli komponent zawiera komponenty podrzędne, do prawidłowego renderingu komponentu niezbędne jest użycie więcej niż jednej ze wspomnianych metod. Przy braku komponentów podrzędnych całą pracę należy wykonać w metodzie encodeEnd. Ewentualnie można skorzystać z metody encodeAll obejmującej wszystkie wcześniej wspomniane metody. Ponieważ MapComponent stanowi komponent nadrzędny dla AreaComponent, znaczniki area muszą zostać zrenderowane po znaczniku otwierającym map, ale przed znacznikiem zamykającym map. Aby uzyskać odpowiedni efekt, klasa MapRenderer renderuje znacznik otwierający map w metodzie encodeBegin, a pozostałą część znacznika map w metodzie encodeEnd. Implementacja JavaServer Faces automatycznie wywołuje metodę encodeEnd renderera dotyczącego AreaComponent po wywołaniu metody encodeBegin Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

117

Tworzenie własnych klas komponentów

z klasy MapRenderer, ale przed wywołaniem metody encodeEnd klasy MapRenderer. Jeśli komponent musi przeprowadzić rendering własnych potomków, wykonuje to zadanie w metodzie encodeChildren. Oto metody encodeBegin i encodeEnd klasy MapRenderer: @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { if ((context == null)|| (component == null)){ throw new NullPointerException(); } MapComponent map = (MapComponent) component; ResponseWriter writer = context.getResponseWriter(); writer.startElement("map", map); writer.writeAttribute("name", map.getId(), "id"); } @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { if ((context == null) || (component == null)){ throw new NullPointerException(); } MapComponent map = (MapComponent) component; ResponseWriter writer = context.getResponseWriter(); writer.startElement("input", map); writer.writeAttribute("type","hidden", null); writer.writeAttribute("name", getName(context,map), "clientId");( writer.endElement("input"); writer.endElement("map"); }

Zauważ, że metoda encodeBegin renderuje jedynie znacznik otwierający map. Metoda encodeEnd renderuje znacznik input oraz znacznik zamykający map. Metody kodujące przyjmują jako argument obiekt typu UIComponent, a także argument typu javax.faces.context.FacesContext. Instancja FacesContext zawiera wszystkie informacje związane z aktualnym żądaniem. Argument UIComponent zawiera komponent, który należy zrenderować. Metody renderują znaczniki, wykorzystując instancję klasy javax.faces.context. ´ResponseWriter, która odpowiada za przekazanie danych do aktualnej odpowiedzi. W dużym skrócie mówiąc, rendering polega na przekazaniu nazw znaczników HTML i ich atrybutów do instancji ResponseWriter jako tekstu, pobraniu wartości atrybutów komponentu i przekazaniu ich jako wartości do ResponseWriter. Metoda startElement przyjmuje jako parametr obiekt String (nazwę znacznika) i komponent, do którego przynależy znacznik (w tym przypadku map). (Przekazanie tego rodzaju informacji do instancji ResponseWriter ułatwia zadanie narzędziom dla projektantów, bo wtedy łatwo ustalić, z których komponentów pochodzą poszczególne części wygenerowanych znaczników. Po wywołaniu startElement można wywoływać metodę writeAttribute, by dodać do znacznika atrybuty. Metoda writeAttribute przyjmuje nazwę atrybutu,

118

Java EE 6. Zaawansowany przewodnik

Tworzenie własnych klas komponentów

jego wartość, a także nazwę właściwości lub atrybutu komponentu powiązanego z generowanym atrybutem znacznika. Ostatni parametr może przyjąć wartość null; nie jest renderowany. Wartość atrybutu name znacznika map jest pobierana przy użyciu metody getId klasy UIComponent, która zwraca unikatowy identyfikator komponentu. Wartość atrybutu name znacznika input pochodzi z metody getName(FacesContext, UIComponent) klasy MapRenderer. Jeżeli chcesz zawrzeć w komponencie własny system renderujący, a jednocześnie dopuścić stosowanie zewnętrznego renderera, jeśli zostanie zdefiniowany, umieść poniższy kod w metodzie kodującej (sprawdza on, czy z komponentem został powiązany renderer): if (getRendererType() != null) { super.encodeEnd(context); return; }

Jeśli renderer jest dostępny, metoda wywołuje metodę encodeEnd klasy nadrzędnej, która zajmie się odszukaniem odpowiedniego renderera. Klasa MapComponent deleguje cały rendering do klasy MapRenderer, więc nie musi sprawdzać istnienia renderera. W niektórych klasach własnych komponentów, które rozszerzają komponenty standardowe, konieczna może okazać się implementacja innych metod, nie tylko encodeEnd. Jeśli przykładowo trzeba pobrać wartości komponentu z parametrów żądania, konieczne będzie dodanie metody decode.

Przeprowadzenie dekodowania W trakcie fazy stosowania wartości żądania implementacja JavaServer Faces wywołuje metody decode wszystkich komponentów drzewa. Metoda decode wydobywa wartość lokalną komponentu z parametrów żądania i wykorzystuje implementację javax.faces.convert.Converter do zamiany uzyskanej wartości na typ odpowiedni dla klasy komponentu. Klasa własnego komponentu lub jej renderera musi implementować metodę decode tylko wtedy, gdy powinna pobrać wartość lokalną lub kolejkuje zdarzenia. Komponent kolejkuje zdarzenie, wywołując metodę queueEvent. Oto metoda decode zastosowana w klasie MapRenderer: @Override public void decode(FacesContext context, UIComponent component) { if ((context == null) || (component == null)) { throw new NullPointerException(); } MapComponent map = (MapComponent) component; String key = getName(context, map); String value = (String) context.getExternalContext(). getRequestParameterMap().get(key); if (value != null)

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

119

Tworzenie własnych klas komponentów

}

}

map.setCurrent(value);

Metoda decode najpierw pobiera nazwę ukrytego pola input, wywołując w tym celu metodę getName(FacesContext, UIComponent). Wykorzystuje nazwę jako klucz w odwzorowaniu parametrów żądania, by pobrać aktualną wartość pola. Wartość odpowiada obszarowi wybranemu przez użytkownika. Na końcu ustawia wartość atrybutu current klasy MapComponent na wartość pola input.

Umożliwienie właściwościom komponentu przyjmowania wyrażeń W zasadzie prawie wszystkie atrybuty standardowych znaczników JavaServer Faces mogą przyjmować wyrażenia, czy to wyrażenia dotyczące wartości, czy wyrażenia dotyczące metod. Zaleca się, by tworzone komponenty również obsługiwały w swych atrybutach wyrażenia, które znacząco zwiększają elastyczność komponentu w trakcie pisania stron faceletów. Aby atrybuty mogły przyjmować wyrażenia, klasa komponentu musi implementować metody ustawiania i pobierania właściwości komponentu. Metody te mogą wykorzystywać rozwiązania oferowane przez interfejs StateHelper do zapisu i przywracania nie tylko tych właściwości, ale również stanu komponentu między poszczególnymi żądaniami. Ponieważ MapComponent rozszerza UICommand, klasa UICommand zajęła się już pobraniem instancji ValueExpression i MethodExpression powiązanych ze wszystkimi obsługiwanymi przez nią atrybutami. Podobnie, klasa UIOutput, którą rozszerza klasa AreaComponent, także pobiera instancje ValueExpression dla obsługiwanych atrybutów. W przypadku obu komponentów proste metody ustawiające i pobierające zapamiętują i pobierają kluczowe wartości i stan atrybutów, co pokazujemy w poniższym fragmencie klasy AreaComponent: enum PropertyKeys { alt, coords, shape, targetImage; } public String getAlt() { return (String) getStateHelper().eval(PropertyKeys.alt, null); } public void setAlt(String alt) { getStateHelper().put(PropertyKeys.alt, alt); } ...

Jeśli jednak klasa własnego komponentu dziedziczy bezpośrednio po UIComponentBase, trzeba samodzielnie zaimplementować metody pobierające instancje ValueExpression i MethodExpression powiązane z atrybutami, które mogą przyjmować wyrażenia. Przykładowo można dodać metodę, która pobierze instancję ValueExpression dla atrybutu immediate:

120

Java EE 6. Zaawansowany przewodnik

Tworzenie własnych klas komponentów

public boolean isImmediate() { if (this.immediateSet) { return (this.immediate); } ValueExpression ve = getValueExpression("immediate"); if (ve != null) { Boolean value = (Boolean) ´ve.getValue(getFacesContext().getELContext()); return (value.booleanValue()); } else { return (this.immediate); } }

Właściwości odpowiadające atrybutom komponentu przyjmującym wyrażenia metod muszą przyjmować i zwracać obiekt MethodExpression. Gdyby klasa MapComponent dziedziczyła po UIComponentBase, a nie po UICommand, trzeba by zapewnić właściwość action, która zwraca i przyjmuje obiekt MethodExpression: public MethodExpression getAction() { return (this.action); } public void setAction(MethodExpression action) { this.action = action; }

Zapis i przywracanie stanu Zgodnie z opisem z punktu „Umożliwienie właściwościom komponentu przyjmowania wyrażeń”, z tego rozdziału, użycie interfejsu StateHelper umożliwia zapis stanu komponentu w tym samym czasie, w którym ustawia się lub pobiera wartości właściwości. Implementacja StateHelper dopuszcza zapis stanu częściowego, czyli zapisuje jedynie zmiany w stanie po żądaniu inicjującym, a nie cały stan, ponieważ ten można łatwo odtworzyć w fazie przywracania widoku. Klasy komponentów implementujące StateHolder mogą preferować implementację metod saveState(FacesContext) i restoreState(FacesContext, Object), by wspomóc implementację JavaServer Faces podczas zapisu i przywracania pełnego stanu komponentów między żądaniami. Aby zapisać zbiór wartości, można zaimplementować metodę saveState ´(FacesContext). Metoda jest wywoływana w trakcie fazy renderowania odpowiedzi, w której stan odpowiedzi zostaje zapisany, by mógł zostać wykorzystany w kolejnych żądaniach. Oto hipotetyczna metoda klasy MapComponent, która zapisuje tylko jeden atrybut — current: @Override public Object saveState(FacesContext context) { Object values[] = new Object[2]; values[0] = super.saveState(context); values[1] = current; return (values); }

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

121

Przekazanie renderowania do renderera

Metoda inicjalizuje tablicę, która będzie przechowywała zapisany stan. Następnie zapisuje cały stan powiązany z komponentem. Komponent, który implementuje StateHolder, może również zapewnić implementację metody restoreState(FacesContext, Object), która przywraca stan komponentu zapisany wcześniej przy użyciu metody saveState(FacesContext). Metodę restoreState(FacesContext, Object) wywołuje faza przywracania widoku, w której implementacja JavaServer Faces sprawdza, czy istnieje stan zapisany przez poprzednią fazę renderowania odpowiedzi; stan ten musi zostać odtworzony jako element przygotowań do obsługi nadchodzącego żądania. Oto hipotetyczna metoda restoreState(FacesContext, MapComponent:

Object)

dla klasy

public void restoreState(FacesContext context, Object state) { Object values[] = (Object[]) state; super.restoreState(context, values[0]); current = (String) values[1]; }

Metoda przyjmuje FacesContext i obiekt typu Object reprezentujący tablicę przechowującą stan komponentu. Metoda ustawia właściwości komponentu na wartości zapisane w tablicy Object. Niezależnie od tego, czy w klasie komponentu pojawiła się implementacja wymienionych metod, można skorzystać z parametru kontekstu o nazwie javax.faces.STATE_SAVING_METHOD, by wskazać w deskryptorze wdrożenia, gdzie ma zostać zapisany stan: u klienta (client) lub na serwerze (server). Jeśli stan ma znaleźć się po stronie klienta, stan całego widoku jest umieszczany w ukrytym polu tekstowym strony. Domyślnie stan jest zapisywany po stronie serwera. Aplikacja internetowa przykładowego przypadku użycia nazwanego las Duke’a zapisuje stan po stronie klienta. Zapis stanu po stronie klienta wymaga większej przepustowości łącza, a także dodatkowych zasobów po stronie klienta. Zapis po stronie serwera wymaga dodatkowych zasobów serwerowych. Zapis stanu po stronie klienta warto rozważyć, jeśli klienci mogą w większości przypadków mieć wyłączoną obsługę cookies (tzw. ciasteczek).

Przekazanie renderowania do renderera Zarówno MapComponent, jak i AreaComponent delegują cały rendering do osobnego renderera. W tym rozdziale, w punkcie „Przeprowadzenie kodowania” wyjaśniamy sposób przeprowadzenia renderingu przez MapRenderer na potrzeby klasy MapComponent. W tym podrozdziale skupimy się na szczegółach przekazania renderingu do renderera AreaRenderer, który obsługuje wyświetlenie komponentu AreaComponent.

122

Java EE 6. Zaawansowany przewodnik

Przekazanie renderowania do renderera

Delegowanie renderingu wymaga realizacji następujących kroków: „ „

„

utworzenia klasy Renderer, rejestracji renderera w zestawie rendererów przy użyciu adnotacji @FacesRenderer (lub przy użyciu pliku zasobu konfiguracyjnego aplikacji w sposób wyjaśniony w podrozdziale „Rejestracja własnego renderera w zestawie rendererów” z rozdziału 7., wskazania typu renderera w adnotacji @FacesRenderer.

Tworzenie klasy renderera Delegując rendering do renderera, można przekazać mu również odpowiedzialność za całe kodowanie i dekodowanie, ale nic nie stoi na przeszkodzie, by część wspomnianych prac wykonać w klasie komponentu. Klasa AreaComponent deleguje całe kodowanie do klasy AreaRenderer. Klasa renderera rozpoczyna się od adnotacji @FacesRenderer: @FacesRenderer(componentFamily = "Area", rendererType = "dukesbookstore.renderers.AreaRenderer") public class AreaRenderer extends Renderer {

Adnotacja @facesRenderer rejestruje klasę renderera w implementacji JavaServer Faces. Adnotacja określa rodzinę komponentu oraz rodzaj renderera. Aby przeprowadzić rendering dla komponentu AreaComponent, klasa AreaRenderer musi zaimplementować metodę encodeEnd. Metoda ta pobiera wartości kształtu, współrzędnych i alternatywnego tekstu umieszczone w ziarnie ImageArea powiązanym z komponentem AreaComponent. Przypuśćmy, że aktualnie renderowany znacznik area ma wartość atrybutu value równą "book203". Poniższy wiersz kodu z metody encodeEnd pobiera wartość atrybutu z instancji FacesContext. ImageArea iarea = (ImageArea)area.getValue();

Wartością atrybutu jest instancja ziarna ImageArea, która zawiera wartości shape, coords i alt związane z komponentem AreaComponent o identyfikatorze book203. Więcej informacji na temat przechowywania tych wartości przez aplikację zawiera punkt tego rozdziału, „Konfiguracja danych modelu”. Po pobraniu obiektu ImageArea metoda renderuje wartości shape, coords i alt przez proste wywołanie metod dostępowych i przekazanie wartości do instancji javax.faces.context.ResponseWriter, co prezentujemy w poniższym fragmencie kodu, który generuje atrybuty kształtu i współrzędnych: writer.startElement("area", area); writer.writeAttribute("alt", iarea.getAlt(), "alt"); writer.writeAttribute("coords", iarea.getCoords(), "coords"); writer.writeAttribute("shape", iarea.getShape(), "shape");

Metoda encodeEnd renderuje również kod JavaScript dla atrybutów onmouseout, onmouseover i onclick. Strona faceletu musi jedynie przekazać ścieżki do obrazów do wczytania w trakcie akcji onmouseout i onmouseover: Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

123

Przekazanie renderowania do renderera

Klasa AreaRenderer zajmuje się wygenerowaniem kodu JavaScript dla tych akcji, co obrazuje umieszczony poniżej fragment kodu metody encodeEnd. Kod JavaScript generowany przez AreaRenderer dla akcji onclick ustawia wartość ukrytego pola na wartość identyfikatora klikniętego obszaru i wysyła stronę do serwera: sb = new StringBuffer("document.forms[0]['").append(targetImageId). append("'].src='"); sb.append( getURI(context, (String) area.getAttributes().get("onmouseout"))); sb.append("'"); writer.writeAttribute("onmouseout", sb.toString(), "onmouseout"); sb = new StringBuffer("document.forms[0]['").append(targetImageId). append("'].src='"); sb.append( getURI(context, (String) area.getAttributes().get("onmouseover"))); sb.append("'"); writer.writeAttribute("onmouseover", sb.toString(), "onmouseover"); sb = new StringBuffer("document.forms[0]['"); sb.append(getName(context, area)); sb.append("'].value='"); sb.append(iarea.getAlt()); sb.append("'; document.forms[0].submit()"); writer.writeAttribute("onclick", sb.toString(), "value"); writer.endElement("area");

Wysłanie strony powoduje powrót cyklu życia JavaServer Faces do fazy przywracania widoku. Faza pobiera z żądania wszystkie informacje o stanie — włącznie z wartościami ukrytych pól — i konstruuje nową wersję drzewa komponentów. Za pobranie wartości żądania odpowiada metoda decode klasy MapComponent. Zostaje ona wywołana w fazie stosowania wartości żądania, która następuje po fazie przywracania widoku. Poza metodą encodeEnd klasa AreaRenderer zawiera pusty konstruktor. Służy on do utworzenia instancji AreaRenderer, by można ją było dodać do zestawu rendererów. Adnotacja @FacesRenderer rejestruje w implementacji klasę renderera JavaServer Faces jako renderer. Adnotacja przyjmuje jako parametry rodzinę komponentu oraz rodzaj renderera.

Określenie rodzaju renderera W fazie renderowania odpowiedzi implementacja JavaServer Faces wywołuje metodę getRendererType procedury obsługi znacznika komponentu, by określić renderer do wywołania (jeśli istnieje). Typ renderera określa się w elemencie rendererType adnotacji @FacesRenderer klasy AreaRenderer, a także w elemencie renderer-type pliku deskryptora biblioteki znaczników.

124

Java EE 6. Zaawansowany przewodnik

Implementacja klasy nasłuchiwania zdarzeń

Implementacja klasy nasłuchiwania zdarzeń Technologia JavaServer Faces obsługuje dla komponentów zdarzenia akcji i zdarzenia zmiany wartości. Zdarzenia akcji zachodzą, gdy użytkownik aktywuje komponent implementujący interfejs javax.faces.component.ActionSource. Zdarzenia reprezentuje klasa javax.faces.event.ActionEvent. Zdarzenia zmiany wartości zachodzą, gdy użytkownik zmieni wartość komponentu implementującego interfejs javax.faces.component.EditableValueHolder. Zdarzenia reprezentuje klasa javax.faces.event.ValueChangeEvent. Jednym ze sposobów obsługi zdarzeń jest implementacja odpowiednich klas nasłuchujących. Klasy nasłuchujące obsługujące zdarzenia akcji w aplikacji muszą implementować interfejs javax.faces.event.ActionListener i podobnie, klasy nasłuchujące obsługujące zdarzenia zmiany wartości muszą implementować interfejs javax.faces.event.ValueChangeListener. W podrozdziale zawarto opis implementacji obu rodzajów klas nasłuchujących. Aby obsłużyć zdarzenia wygenerowanie przez własne komponenty, trzeba zaimplementować klasę nasłuchiwania zdarzeń oraz procedurę obsługi zdarzenia, a także ręcznie kolejkować zdarzenia w komponencie. Dodatkowe informacje podajemy w tym rozdziale, w podrozdziale „Obsługa zdarzeń dla samodzielnie wykonanych komponentów”. UWAGA Nie trzeba tworzyć implementacji ActionListener, by obsłużyć zdarzenie

polegające tylko i wyłącznie na przejściu do innej strony bez wykonywania żadnego dodatkowego przetwarzania. Więcej informacji na ten temat zawiera podrozdział „Tworzenie metody obsługującej nawigację” książki Java EE 6. Przewodnik. Wydanie IV.

Implementacja klasy nasłuchiwania zdarzeń zmiany wartości Implementacja javax.faces.event.ValueChangeListener musi zawierać metodę processValueChange(ValueChangeEvent). Metoda odpowiada za obsługę zmiany wartości. Zostaje wywołana przez implementację JavaServer Faces w momencie zgłoszenia zdarzenia zmiany wartości. Instancja ValueChangeEvent zawiera zarówno stare, jak i nowe wartości komponentu zgłaszającego zdarzenie. W przypadku użycia księgarni Duke’a implementacja nasłuchująca NameChanged zostaje zarejestrowana dla komponentu UIInput o nazwie name na stronie bookcashier.xhtml. Implementacja zapisuje w zasięgu sesji nazwę, którą użytkownik wpisał w polu tekstowym dotyczącym wspomnianego komponentu.

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

125

Implementacja klasy nasłuchiwania zdarzeń

Strona bookreceipt.xhtml pobiera zapisaną wartość z zasięgu sesji:



Strona bookreceipt.xhtml wyświetla podany tekst wewnątrz komunikatu: "Dziękujemy, {0}, za zakup książek w naszej księgarni."

Oto fragment implementacji klasy nasłuchującej NameChanged: public class NameChanged extends Object implements ValueChangeListener {

}

@Override public void processValueChange(ValueChangeEvent event) throws AbortProcessingException { if (null != event.getNewValue()) { FacesContext.getCurrentInstance().getExternalContext(). getSessionMap().put("name", event.getNewValue()); } }

Gdy użytkownik wpisuje nazwę w polu tekstowym, wygenerowane zostaje zdarzenie zmiany wartości, co powoduje wywołanie metody processValueChange(ValueChangeEvent) w klasie nasłuchującej NameChanged. Metoda najpierw pobiera identyfikator komponentu, który zgłosił zdarzenie, z obiektu ValueChangeEvent i umieszcza go wraz z nazwą atrybutu w odwzorowaniu klucz-wartość sesji instancji FacesContext. Sposób rejestracji klasy nasłuchującej w komponencie opisano w punkcie „Rejestrowanie listenera zmiany wartości na komponencie” książki Java EE 6. Przewodnik. Wydanie IV.

Implementacja klas nasłuchujących akcji Implementacja javax.faces.event.ActionListener musi zawierać metodę processAction(ActionEvent). Metoda odpowiada za obsługę reakcji na zdarzenie akcji. Zostaje wywołana przez implementację JavaServer Faces w momencie zgłoszenia zdarzenia akcji. W przykładzie użycia księgarnia Duke’a wykorzystano dwie implementacje ActionListener: LinkBookChangeListener i MapBookChangeListener. Dodatkowe informacje na temat MapBookChangeListener zawarliśmy w tym rozdziale, w podrozdziale „Obsługa zdarzeń dla samodzielnie wykonanych komponentów”. Sposób rejestracji klasy nasłuchującej w komponencie opisano w punkcie „Rejestrowanie listenera akcji na komponencie” książki Java EE 6. Przewodnik. Wydanie IV.

126

Java EE 6. Zaawansowany przewodnik

Obsługa zdarzeń dla samodzielnie wykonanych komponentów

Obsługa zdarzeń dla samodzielnie wykonanych komponentów Zgodnie z opisem z tego rozdziału, z podrozdziału „Implementacja klasy nasłuchiwania zdarzeń”, zdarzenia dla standardowych komponentów je zgłaszających są kolejkowane automatycznie. We własnym komponencie trzeba ręcznie kolejkować zdarzenia z poziomu metody decode, jeśli ta je zgłasza. W tym rozdziale, w punkcie „Przeprowadzenie dekodowania” wyjaśniamy, w jaki sposób zakolejkować zdarzenie dla MapComponent, wykorzystując metodę decode. W tym podrozdziale wyjaśnimy, w jaki sposób napisać klasę, która reprezentuje zdarzenie kliknięcia mapy, a także jak napisać metodę przetwarzającą tego rodzaju zdarzenie. Zgodnie z opisem z tego rozdziału, z punktu „Omówienie strony faceletu”, atrybut actionListener znacznika bookstore:map wskazuje na klasę MapBookChangeListener. Metoda processAction klasy nasłuchującej obsługuje zdarzenie kliknięcia mapy obrazu. Oto kod metody processAction: @Override public void processAction(ActionEvent actionEvent) throws AbortProcessingException { AreaSelectedEvent event = (AreaSelectedEvent) actionEvent; String current = event.getMapComponent().getCurrent(); FacesContext context = FacesContext.getCurrentInstance(); String bookId = books.get(current); context.getExternalContext().getSessionMap().put("bookId", bookId); }

Gdy implementacja JavaServer Faces wywołuje metodę, jako argument przekazuje obiekt ActionEvent reprezentujący zdarzenie wygenerowane przez kliknięcie mapy obrazu. Kod rzutuje argument na obiekt AreaSelectedEvent (patrz plik tut-install/examples/case-studies/dukes-bookstore/src/java/dukesbookstore/ listeners/AreaSelectedEvent.java). Następnie pobiera obiekt MapComponent powiązany ze zdarzeniem i wydobywa z niego wartość atrybutu current wskazującą aktualnie wybrany obszar. Kod metody używa wartości atrybutu do pobrania identyfikatora książki z obiektu HashMap, który powstaje w innej części klasy MapBookChangeListener. Na końcu metoda umieszcza identyfikator pobrany z obiektu HashMap w odwzorowaniu sesyjnym klucz-wartość aplikacji. Poza metodą obsługującą zdarzenie potrzebna jest jeszcze sama klasa zdarzenia. Bardzo łatwo ją utworzyć — wystarczy, by dziedziczyła po klasie ActionEvent, zapewniała konstruktor przyjmujący komponent, w którym zakolejkowano zdarzenie, a także metodę zwracającą ten komponent. Oto treść klasy AreaSelectedEvent wykorzystywanej z mapą obrazu: public class AreaSelectedEvent extends ActionEvent { public AreaSelectedEvent(MapComponent map) { super(map); } public MapComponent getMapComponent() {

Rozdział 6 y Tworzenie własnych komponentów UI i innych obiektów

127

Definicja znacznika własnego komponentu w deskryptorze biblioteki znaczników

}

}

return ((MapComponent) getComponent());

Zgodnie z wyjaśnieniem z tego rozdziału, z podrozdziału „Tworzenie własnych klas komponentów”, by klasa MapComponent w ogóle mogła zgłaszać zdarzenia, musi zaimplementować interfejs ActionSource. Ponieważ dziedziczy po klasie UICommand, automatycznie implementuje wspomniany interfejs.

Definicja znacznika własnego komponentu w deskryptorze biblioteki znaczników Aby skorzystać z własnego znacznika, trzeba go zadeklarować w deskryptorze biblioteki znaczników (TLD). Plik TLD określa sposób użycia własnego znacznika na stronach JavaServer Faces. Kontener webowy używa TLD do walidacji znacznika. Znaczniki związane z zestawem rendererów HTML znajdują się w TLD BASIC_HTML, którego dokumentacja jest dostępna pod adresem http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/renderkitdocs/. Nazwa pliku TLD musi kończyć się fragmentem taglib.xml. W przykładzie użycia księgarnia Duke’a definicja własnych znaczników area i map znajduje się w pliku web/WEB-INF/bookstore.taglib.xml. Wszystkie definicje znaczników w TLD muszą znajdować się w elemencie facelet-taglib. Każdy znacznik definiuje element tag, który określa konkretną kombinację rodzaju komponentu i rodzaju renderera. Poniżej podajemy przykład definicji znaczników area i map:

http://dukesbookstore

area

DemoArea DemoArea

map

DemoMap DemoMap



Element component-type określa nazwę zdefiniowaną w adnotacji @FacesComponent. Element renderer-type określa parametr rendererType z adnotacji @FacesRenderer. Element facelet-taglib musi również zawierać element namespace, który ustala przestrzeń nazw do stosowania na stronach wykorzystujących własny komponent.

128

Java EE 6. Zaawansowany przewodnik

Użycie własnego komponentu

Szczegóły dotyczące określania przestrzeni nazw na stronach zawarliśmy w tym rozdziale, w podrozdziale „Użycie własnego komponentu”. Plik TLD znajduje się w folderze WEB-INF. Dodatkowo należy umieścić odpowiedni wpis w pliku deskryptora wdrożenia webowego (web.xml) i wskazać plik deskryptora biblioteki własnych znaczników:

javax.faces.FACELETS_LIBRARIES /WEB-INF/bookstore.taglib.xml

Użycie własnego komponentu By skorzystać z własnego komponentu na stronie, trzeba dodać własny znacznik powiązany z komponentem do strony WWW. Zgodnie z opisem z tego rozdziału, z podrozdziału „Definicja znacznika własnego komponentu w deskryptorze biblioteki znaczników”, trzeba upewnić się, że plik TLD definiujący wszystkie własne znaczniki znajduje się w paczce razem z aplikacją, jeżeli znaczniki mają zostać wykorzystane na stronach. Pliki TLD znajdują się w folderze WEB-INF/ lub podfolderze pliku WAR, lub w folderze META-INF/, lub podfolderze biblioteki znaczników w pliku JAR. Na stronie trzeba umieścić deklarację przestrzeni nazw, by strona miała dostęp do znaczników. Własne znaczniki z przykładu księgarnia Duke’a znajdują się w pliku bookstore.taglib.xml. Znacznik ui:composition ze strony index.xhtml deklaruje przestrzeń nazw zdefiniowaną w bibliotece znaczników:

Na końcu pozostaje już tylko dodać znacznik komponentu na stronie, by rozpocząć użycie własnego komponentu. Przykład użycia księgarnia Duke’a zawiera na stronie index.xhtml własny komponent mapy obrazu. Komponent umożliwia wybór książki przez kliknięcie odpowiedniego obszaru mapy obrazu: ...