15 lipca 2007

Java Persistence - Rozdział 5.8 Wymagania stawiane kontenerowi/serwerowi aplikacyjnemu

Rozdział 5.8 Wymagania stawiane kontenerowi/serwerowi aplikacyjnemu (ang. Requirements on the Container) jest bardzo krótki, gdyż treść podsumowuje już opisane wymagania jakie stawiane są kontenerowi, który odpowiedzialny jest za utrzymywanie stanu obiektów JPA. Przede wszystkim skrótowo przedstawiony jest sposób tworzenia kontekstów trwałych dostarczanych przez dowolnych dostawców JPA (integracja z dostawcami JPA) oraz sposób ich przekazywania między składowymi (komponentami) aplikacji.

5.8 Wymagania stawiane kontenerowi

Rolą serwera aplikacyjnego Java EE jest dostarczenie zestawu usług, które upraszczają konstruowanie aplikacji. Jedną z usług jest usługa utrwalania danych (usługa trwałości). W tej roli serwer występuje jako klient JPA korzystając bezpośrednio z fabryki zarządców encji oraz zarządzając zarządcami. Można wyróżnić "poziomy" integracji aplikacji z usługą utrwalania serwera aplikacyjnego:

1. Poziom zerowej integracji aplikacji z serwerem, w którym aplikacja tworzy zarządców poprzez Persistence (lub opcjonalnie przez metody interfejsu PersistenceProvider).
 @Stateless
public class KoordynatorTestowBean implements KoordynatorTestow {

public void uruchomTesty() {
uruchomAplikacyjnyKontekstTrwaly();
}

private void uruchomAplikacyjnyKontekstTrwaly() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestyEJB3EncjePU");
EntityManager em = emf.createEntityManager();
Prelegent p = new Prelegent("Jacek", "Laskowski");
em.persist(p);
em.close();
emf.close();
}

}
2. Integracja połowiczna aplikacji z serwerem poprzez korzystanie z utworzonej przez serwer fabryki zarządców, która pozyskiwana jest przez aplikację dzięki DI albo JNDI.
 @Stateless
public class KoordynatorTestowBean implements KoordynatorTestow {

@PersistenceUnit(unitName = "TestyEJB3EncjePU")
private EntityManagerFactory emf;

public void uruchomTesty() {
uruchomAplikacyjnyKontekstTrwalyPrzezZarzadzanaFabryke();
}

private void uruchomAplikacyjnyKontekstTrwalyPrzezZarzadzanaFabryke() {
EntityManager em = emf.createEntityManager();
Prelegent p = new Prelegent("Jacek", "Laskowski");
em.persist(p);
em.close();
}

}
3. Pełna integracja polegająca na przekazywaniu zarządców encji za pomocą DI albo JNDI.
 @Stateless
public class KoordynatorTestowBean implements KoordynatorTestow {

@PersistenceContext(unitName = "TestyEJB3EncjePU")
private EntityManager em;

public void uruchomTesty() {
uruchomSerwerowyKontekstTrwaly();
}

private void uruchomSerwerowyKontekstTrwaly() {
Prelegent p = new Prelegent("Jacek", "Laskowski");
em.persist(p);
}

}
Dowolna kombinacja integracji jest możliwa, nawet taka, w której wykorzystuje się wszystkie wymienione wyżej sposoby integracji.

Serwer aplikacyjny musi udostępniać fabrykę zarządców encji w drzewie JNDI, jeśli aplikacja korzysta z kontekstu trwałego zarządzanego przez serwer. Serwer ma możliwość korzystania z nieustandaryzowanego interfejsu integracji z dostawcą JPA. Wymaga się jednak, aby serwer wspierał również innych dostawców (niż domyślny) poprzez wykorzystanie metody PersistenceProvider.createContainerEntityManagerFactory(). Zamknięcie fabryki następuje porzez wywołanie metody EntityManagerFactory.close() przy zatrzymaniu serwera (jeśli wcześniej kontekst nie został zamknięty przez aplikację - tylko w sytuacji aplikacyjnych kontekstów trwałych).

Interfejs javax.persistence.spi.PersistenceProvider realizowany jest przez dostawcę JPA i pozwala na utworzenie fabryki zarządców. Realizacja interfejsu definiowana jest w pliku persistence.xml dla każdego zarządcy encji (=danego dostawcy JPA). Interfejs wykorzystywany jest bezpośrednio przez serwer aplikacyjny podczas tworzenia fabryki zarządców encji lub przez klasę Persistence dla samodzielnych aplikacji (aplikacji uruchomionych poza zasięgiem usług serwera aplikacyjnego).

Dobrym ćwiczeniem na rozpoznanie integracji dostawcy JPA z serwerem byłoby stworzenie własnego dostawcy JPA.

Dowolna aplikacja uruchomiona w ramach serwera aplikacyjnego może bezpośrednio korzystać z JPA, tj. samodzielnie zarządzać obiektami JPA dzięki aplikacyjnym kontekstom trwałym (kontekstom niezarządzanym przez serwer).

Serwer aplikacyjny jest zobowiązany do zarządzania cyklem rozwojowym kontekstów trwałych zarządzanych przez kontener i zarządzane obiekty typu EntityManager wstrzeliwuje (przekazuje) do komponentów aplikacji internetowej (m.in. servlety, filtry), ziarnom sesyjnym oraz sterowanym komunikatami EJB oraz umieszcza w drzewie JNDI.

Nie jest określone, czy nowy egzemplarz zarządcy encji jest tworzony każdorazowo dla kontekstu trwałego, czy zarządcy są czasami współdzieleni. Dokładne związywanie kontekstu trwałego z transakcją JTA przez kontener nie jest określone przez specyfikację.

Jeśli kontekst trwały jest związany z transakcją JTA, kontener korzysta z kontekstu trwałego dla kolejnych wywołań w ramach tej transakcji zgodnie z regułami przekazywania kontekstu trwałego opisanymi w rozdziale 5.6.3 (relacjonowałem tą część w notatce Java Persistence - Rozdziały 5.5 Zarządzanie transakcjami oraz 5.6 Konteksty trwałe zarządzane przez serwer).