11 lipca 2007

Java Persistence - Rozdział 5.7 Kontekst trwały zarządzany przez aplikację (aplikacyjny kontekst trwały)

Kolejna relacja z lektury specyfikacji Java Persistence API. W rozdziale 5. Zarządcy encji i konteksty trwałe pozostały (pod)rozdziały 5.7, 5.8 oraz 5.9. Tym razem zajmę się rozdziałem 5.7 o aplikacyjnych kontekstach trwałych głównie wykorzystywanych w aplikacjach desktopowych w środowisku Java SE.

5.7 Kontekst trwały zarządzany przez aplikację (aplikacyjny kontekst trwały)

Użycie zarządzcy trwałego zarządzanego przez aplikację (ang. application-managed entity manager) nakłada na aplikację obowiązek bezpośredniej komunikacji z fabryką zarządców trwałych w celu zarządzania cyklem rozwojowym zarządcy trwałego oraz tworzenia i niszczenia kontekstów trwałych z nim związanych.

Określenia zarządca trwały zarządzany przez aplikację oraz aplikacyjny zarządca trwały są w tym kontekście jednoznaczne. Będę używał ich naprzemiennie.

Kontekst trwały zarządzany przez aplikację przypomina rozszerzony kontekst trwały zarządzany przez kontener, tj. może istnieć dłużej niż pojedyńcza transakcja. Decyzję o utworzeniu i zamknięciu (zniszczeniu) kontekstu trwałego podejmuje aplikacja (aplikacją jest również sam serwer aplikacyjny Java EE i bez względu na jego rolę w specyfikacji Java EE interfejs publiczny JPA jest identyczny - istotna różnica to, kto odpowiada za zarządzanie kontekstami i całą infrastukturą JPA).

Metody EntityManager.close() oraz EntityManager.isClose() służą do zarządzania cyklem rozwojowym aplikacyjnego zarządcy trwałego i kontekstów trwałych z nim związanych.

Metoda EntityManager.close() służy do zamknięcia zarządcy trwałego i zwolnienia zajmowanych/zarządzanych przez niego zasobów (konteksty trwałe). Wywołanie jakiejkolwiek metody na zarządcy encji, na którym wywołano metodę close(), oraz egzemplarzy Query, które zostały przez niego stworzone, zakończy się wyjątkiem java.lang.IllegalStateException za wyjątkiem metod EntityManager.getTransaction() oraz EntityManager.isOpen() (która zwróci false). Jeśli metoda EntityManager.close() zostanie wywołana w trakcie aktywnej transakcji, konteksty trwałe z nim związane pozostają zarządzane aż do czasu zakończenia transakcji.

Metoda EntityManager.isOpen() określa, czy zarządca encji jest otwarty. Wartość true zwracana jest do momentu zamknięcia zarządcy (wywołanie metody EntityManager.close()).

Rozszerzony kontekst trwały jest powoływany do życia w momencie utworzenia zarządcy trwałego korzystając z metody EntityManagerFactory.createEntityManager(), aż do zamknięcia zarządcy przez EntityManager.close(). Aplikacyjny kontekst trwały jest samodzielnym kontekstem trwałym, tj. nie jest przekazywany do zasobów uczestniczących w tej samej transakcji.

Użycie zarządcy trwałego JTA nakłada na aplikację obowiązek utrzymania zarządcy w ramach aktywnej transakcji JTA. Jeśli zarządca trwały JTA utworzony został poza aktywną transakcją JTA to aplikacja dba o ich połączenie, kiedy konieczne, korzystając z metody EntityManager.joinTransaction().

Rozdział 5.7.1. Examples przedstawia kilka przykładów kontekstów trwałych ze względu na ich zarządzanie - aplikacja vs kontener. Pierwszy przykład 5.7.1.1 Application-managed Persistence Context used in Stateless Session Bean jest wyjątkowo ciekawy, ponieważ uwidacznia znaczenie wykorzystania usług serwera aplikacyjnego - usługi monitora transakcyjnego - do automatycznego zarządzania transakcjami. Mimo, że bezstanowe ziarno sesyjne EJB same zarządza zarządcą encji (przypadek aplikacyjnego zarządcy encji) to utrzymywanie aktywnej transakcji JTA spoczywa na barkach serwera aplikacyjnego. Metody getOrder() oraz getProduct() z biznesowego interfejsu ziarna korzystają z mechanizmu wyszukiwania JTA (metody EntityManager.find() oraz EntityManager.createQuery()), a to nie wymaga aktywnej transakcji, ale już wywołanie metody EntityManager.persist() musi być związane z aktywną transakcją, a jej utworzeniem/zamknięciem zajmuje się serwer (ang. container-managed transaction demarcation). Podczas tworzenia zarządcy trwałego następuje związanie zarządcy z aktywną transakcją JTA i stąd niekonieczne jest explicite wywołanie metod EntityManager.joinTransaction() lub EntityManager.getTransaction(), a później EntityTransaction.begin().

Kolejny przykład w sekcji 5.7.1.2 Application-managed Persistence Context used in Stateless Session Bean, szczególnie implementacja metody createLineItem() ukazuje konieczność związania aplikacyjnego zarządcy trwałego z aktywną transakcją, gdyż utworzenie zarządcy nastąpiło poza aktywną transakcją JTA. Każde wywołanie metody bezstanowego ziarna sesyjnego EJB wiąże się z wywołaniem metody EntityManager.clear(), co czyści kontekst trwały, więc jakiekolwiek wywołanie metody EntityManager.contains() na danej encji (nawet tej, która była utrwalona/odszukana wcześniej) zwróciłoby false.

W sekcji 5.7.1 znajdują się jeszcze 2 przykłady mniejszego kalibru merytorycznego w porównaniu z poprzednimi dwoma. Zainteresowanych zapraszam do specyfikacji na strony 127 i 128.