Java EE: JSF + EJB + JPA Celem ćwiczenia jest utworzenie prostej aplikacji bazodanowej umożliwiającej przeglądanie i dodawanie zleceń serwisowych. Ćwiczenie pokazuje współpracę technologii JSF (podstawowej technologii implementacji interfejsu użytkownika na platformie Java EE) z technologiami EJB (podstawową technologią implementacji logiki biznesowej) i JPA (standardową technologią odwzorowania obiektowo-relacyjnego, stanowiącego dominujące obecnie podejście do obsługi komunikacji z bazą danych). Do realizacji ćwiczenia wykorzystane zostało środowisko NetBeans 7.2 wraz z serwerem aplikacji GlassFish v3.1.2 i serwerem bazy danych Java DB. 1. Uruchom środowisko NetBeans. 2. Utwórz nowy projekt typu Enterprise Application: a. Wybierz z menu opcję File->New Project. b. W pierwszym kroku kreatora jako typ projektu wybierz Enterprise Application z kategorii Java EE. c. W drugim kroku kreatora jako nazwę projektu podaj Requests, a pozostałe ustawienia w tym oknie pozostaw domyślne. d. W ostatnim kroku kreatora jako serwer wybierz GlassFish v3.1.2 i Java EE 6 jako wersję Javy EE. Upewnij się czy zaznaczone jest tworzenie dwóch typów modułów: EJB i webowego. Pozostaw zaproponowane przez kreator nazwy modułów. e. Po zakończeniu działania kreatora obejrzyj organizację aplikacji w oknie Projects. Zwróć uwagę, że w środowisku NetBeans moduły składowe aplikacji Enterprise Application stanowią odrębne projekty, a główny projekt łączy je w całość (inne środowiska IDE mogą stosować inną organizację kodu). 3. Korzystając z menu kontekstowego przejdź do edycji właściwości projektu modułu webowego. Dodaj do projektu framework JavaServer Faces.
4. Uruchom serwer bazy danych Java DB korzystając z panelu Services.
5. Z poziomu panelu Services połącz się z bazą danych sample na lokalnym serwerze Java DB (derby).
6. Utwórz w bazie danych tabelę, na której działać będzie tworzona aplikacja, realizując poniższe kroki: a. Wywołaj okno poleceń SQL dla bazy danych sample wybierając z menu kontekstowego dla węzła reprezentującego połączenie opcję Execute Command. b. Korzystając z okna poleceń SQL wykonaj kolejno poniższe polecenia SQL (pierwsze trzy mogą zakończyć się błędami – służą do ewentualnego usunięcia istniejących już tabel):
DROP TABLE requests; DROP TABLE employees; DROP TABLE departments; CREATE TABLE requests (id INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT requests_pk PRIMARY KEY, request_date DATE, request_text VARCHAR(60) NOT NULL); CREATE TABLE departments (id INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT dept_pk PRIMARY KEY, department_name VARCHAR(60) NOT NULL); CREATE TABLE employees (id INT NOT NULL GENERATED ALWAYS AS IDENTITY CONSTRAINT emp_pk PRIMARY KEY, employee_name VARCHAR(60) NOT NULL, salary DECIMAL(8,2) NOT NULL, department_id INT REFERENCES departments(id)); INSERT VALUES INSERT VALUES
INTO requests(request_date, request_text ) (CURRENT_DATE, 'Please check TV in room 242'); INTO requests(request_date, request_text ) (CURRENT_DATE, 'Repair fridge in room 311');
c. Upewnij się odpowiednim zapytaniem, że faktycznie zostały dodane dwa wiersze do tabeli REQUESTS.
7. W projekcie EJB utwórz jednostkę trwałości, w ramach której obiekty aplikacji będą zachowywane w bazie danych. W tym celu: a. Kliknij lewym przyciskiem myszy na ikonie projektu EJB w panelu projektów i z menu kontekstowego wybierz File->New File. Następnie z kategorii Persistence wybierz typ pliku Persistence Unit. Kliknij przycisk Next.
b. W drugim kroku kreatora zmień nazwę jednostki trwałości na RequestsPU, a z listy dostępnych źródeł danych wybierz jdbc/sample. Dla pozostałych opcji pozostaw ustawienia domyślne. Kliknij przycisk Finish.
8. Utworzenie za pomocą kreatora zbioru encji na podstawie istniejących tabel w bazie danych. a. Kliknij prawym przyciskiem myszy na ikonie projektu EJB w drzewie projektów i z menu kontekstowego wybierz New->Entity Classes from Database. b. Z listy dostępnych źródeł danych wybierz jdbc/sample. c. Następnie na liście tabel do wyboru w lewym panelu, przy zaznaczonym polu wyboru Include related tables, zaznacz myszą tabele REQUESTS i EMPLOYEES i kliknij przycisk Add. Zauważ, że na liście wybranych tabel (w prawym panelu) automatycznie została uwzględniona tabela DEPARTMENTS, do której odwołuje się klucz obcy z tabeli EMPLOYEES. Kliknij przycisk Next.
d. W kolejnym kroku kreatora jako nazwę pakietu podaj req.entities. Zmień zaproponowane nazwy klas encji na liczbę pojedynczą (Department, Employee, Request). W pozostałych polach pozostaw wartości domyślne. Kliknij Next.
e. W ostatnim kroku kreatora sprawdź jakie wartości są dostępne dla opcji Association Fetch i Collection Type. Pozostaw wartości zaproponowane przez kreator i kliknij Finish.
f. Obejrzyj kod wygenerowanej klasy Request. Upewnij się, że rozumiesz znaczenie wszystkich adnotacji. g. Odszukaj w wygenerowanych klasach Employee i Department pola i ich adnotacje odpowiedzialne za dwukierunkową nawigację między obiektami encji. Zwróć uwagę, że encja Employee udostępnia powiązany obiekt Department, a nie wartość klucza obcego. 9. W projekcie EJB utwórz nowy bezstanowy komponent sesyjny EJB 3.x, który będzie pełnił funkcję fasady udostępniającej operacje na obiektach trwałych. a. Z menu kontekstowego projektu EJB uruchom kreator Session Beans For Entity Classes z kategorii Persistence.
b. Wskaż, że tworzony komponent fasadowy ma obsługiwać tylko encję Request i kliknij Next.
c. W ostatnim kroku kreatora zmień proponowany pakiet dla klasy komponentu na req.facade. Zaznacz, że komponent ma być dostępny tylko przez interfejs lokalny. Kliknij Finish.
d. W klasie komponentu fasadowego podmień definicję metody findAll(), tak aby wykorzystywała zdefiniowane dla klasy encji zapytanie nazwane (odszukaj nazwę tego zapytania nazwanego i wpisz je w miejsce wielokropka w poniższej instrukcji, która ma stanowić ciało metody findAll()). return getEntityManager().createNamedQuery("...").getResultList();
10. W projekcie webowym uruchom kreator tworzenia nowej strony JSF (JSF Page z kategorii JavaServer Faces). Jako nazwę strony wprowadź requestsList (odpowiednie rozszerzenie nawy pliku zostanie nadane automatycznie). Pozostałe opcje pozostaw domyślne (zwróć uwagę na wybór składni Facelets, nie JSP) i kliknij Finish. 11. Utwórz komponent backing bean obsługujący stronę JSF. W tym celu:
a. Uruchom w projekcie webowym kreator JSF Managed Bean z kategorii JavaServer Faces. b. Jako nazwę klasy komponentu podaj RequestsList, a jako nazwę pakietu req.backing. Pozostaw wybrany zasięg request typowy dla komponentów backing bean. Kliknij Finish.
12. Przejdź do edycji kodu klasy komponentu zarządzanego. Wprowadź w nim poniższe modyfikacje: a. Wywołaj menu kontekstowe klikając prawym klawiszem myszy wewnątrz klasy przed jej konstruktorem. Z menu wybierz Insert Code->Call Enterprise Bean. W oknie dialogowym z dostępnymi komponentami zaznacz komponent fasadowy. Skoryguj zaproponowaną nazwę referencji, tak aby zaczynała się z małej litery i wybierz korzystanie z interfejsu lokalnego. Kliknij OK.
b. Poniżej konstruktora wklej poniższą metodę, która ma pośredniczyć w dostępie do metody komponentu fasadowego i udostępniać listę wszystkie obiekty encji w formie właściwości komponentu zarządzanego. Samodzielnie uzupełnij kod metody i zaimportuj wykorzystywane klasy. Zapisz wszystkie zmiany. public List getAllRequests() { ... }
13. Przejdź do edycji źródła strony JSF. Usuń treść zawartą w elemencie . Następnie techniką drag-and-drop z palety komponentów umieść na stronie wewnątrz elementu komponent JSF Data Table From Entity. W oknie dialogowym, które pojawi się po upuszczeniu komponentu na stronie wybierz encję Request i właściwość komponentu backing bean udostępniającą wszystkie instancje encji Request.
14. Obejrzyj kod wygenerowany przez kreator i dokonaj następujących poprawek: a. Usuń źle umiejscowione znaczniki i (pozostawiając zawartość między nimi!) b. W znaczniku dodaj atrybut dla przestrzeni nazw znaczników JSF Core wskazując f jako prefiks dla znaczników z tej przestrzeni.
c. Dodaj w znaczniku atrybut border z wartością 1.
d. Usuń nagłówek (wraz z zawartością) poprzedzający element . e. Zmień format daty w komponencie formatującym na yyyy-MM-dd. 15. Wyświetl właściwości głównego projektu aplikacji. Wybierz kategorię Run i w sekcji Web Module Information jako względny adres startowy podaj /faces/requestsList.xhtml. Kliknij OK.
16. Zapisz wszystkie zmiany i uruchom główny projekt aplikacji. 17. Wróć do edycji źródła utworzonej strony JSF i wstaw wewnątrz elementu przed elementem poniższe trzy elementy (korzystając z podpowiedzi i autouzupełniania edytora tekstowego): z atrybutem value o wartości New request, z atrybutem id o wartości newReqInputText, z atrybutem value o wartości Add. 18. Przejdź do edycji kodu klasy komponentu backing bean. Wywołaj poprzez menu kontekstowe edytora kreator Insert Code->AddProperty. Dodaj prywatną właściwość newRequest typu String z publicznymi metodami getter i setter.
19. Analogicznie do poprzedniego punktu ćwiczenia dodaj w klasie backing bean właściwość requestsDataTable typu javax.faces.component.html.HtmlDataTable. 20. Przejdź do edycji strony JSF. Dokonaj powiązania jej komponentów z komponentem backing bean dodając następujące atrybuty do wskazanych elementów: