Transakcje w Dżakarcie
Jakarta Transactions ( JTA ; dawniej Java Transaction API), jeden z interfejsów API Jakarta EE , umożliwia przeprowadzanie transakcji rozproszonych w wielu zasobach X/Open XA w środowisku Java . JTA była specyfikacją opracowaną w ramach Java Community Process jako JSR 907. JTA zapewnia:
- rozgraniczenie [ wymagane wyjaśnienie ] granic transakcji
- X/Open XA API umożliwiające udział zasobów w transakcjach.
Architektura X/Open XA
W architekturze X/Open XA menedżer transakcji lub monitor przetwarzania transakcji (monitor TP) koordynuje transakcje w wielu zasobach, takich jak bazy danych i kolejki komunikatów. Każdy zasób ma własnego menedżera zasobów. Menedżer zasobów zwykle ma własny interfejs API do manipulowania zasobem, na przykład interfejs JDBC do pracy z relacyjnymi bazami danych. Ponadto zarządca zasobów umożliwia monitorowi TP koordynację transakcji rozproszonych pomiędzy jego własnym i innych zarządców zasobów. Wreszcie jest aplikacja, która komunikuje się z monitorem TP, aby rozpocząć, zatwierdzić lub cofnąć transakcje. Aplikacja komunikuje się również z poszczególnymi zasobami za pomocą własnego API w celu modyfikacji zasobu.
Implementacja JTA architektury X/Open XA
JTA API składa się z klas w dwóch pakietach Java :
JTA jest wzorowany na architekturze X/Open XA, ale definiuje dwa różne interfejsy API do wyznaczania granic transakcji. Rozróżnia serwer aplikacji , taki jak serwer EJB , oraz komponent aplikacji. Udostępnia interfejs javax.transaction.TransactionManager
, który jest używany przez sam serwer aplikacji do rozpoczynania, zatwierdzania i wycofywania transakcji. Zapewnia inny interfejs, javax.transaction.UserTransaction
, który jest używany przez ogólny kod kliencki, taki jak serwlet lub EJB, do zarządzania transakcjami.
Architektura JTA wymaga, aby każdy menedżer zasobów zaimplementował interfejs javax.transaction.xa.XAResource
, aby mógł być zarządzany przez monitor TP. Jak wspomniano wcześniej, każdy zasób będzie miał swój własny interfejs API, na przykład:
- relacyjne bazy danych używają JDBC
- usługi przesyłania wiadomości używają JMS
- uogólnione zasoby EIS ( Enterprise Information System ) [ wymagane wyjaśnienie ] wykorzystują API Java EE Connector .
Interfejs aplikacji do programowania
Jakarta Transactions API składa się z trzech elementów: interfejsu rozgraniczenia transakcji aplikacji wysokiego poziomu, interfejsu menedżera transakcji wysokiego poziomu przeznaczonego dla serwera aplikacji oraz standardowego mapowania Java protokołu X/Open XA przeznaczonego dla menedżera zasobów transakcyjnych.
Interfejs UserTransaction
Interfejs javax.transaction.UserTransaction
zapewnia aplikacji możliwość programowego kontrolowania granic transakcji. Ten interfejs może być używany przez programy klienckie Java lub komponenty bean EJB.
Metoda UserTransaction.begin()
uruchamia transakcję globalną i wiąże ją z wątkiem wywołującym. Powiązanie transakcji z wątkiem jest zarządzane w przejrzysty sposób przez Menedżera transakcji.
Obsługa transakcji zagnieżdżonych nie jest wymagana. Metoda UserTransaction.begin zgłasza wyjątek NotSupportedException, gdy wątek wywołujący jest już powiązany z transakcją, a implementacja menedżera transakcji nie obsługuje transakcji zagnieżdżonych.
Propagacja kontekstu transakcji między aplikacjami jest zapewniana przez podstawowe implementacje menedżera transakcji na komputerach klienckich i serwerach. Format kontekstu transakcji używany do propagacji zależy od protokołu i musi być negocjowany między hostami klienta i serwera. Na przykład, jeśli menedżer transakcji jest implementacją specyfikacji JTS , użyje formatu propagacji kontekstu transakcji określonego w specyfikacji CORBA OTS 1.1. Propagacja transakcji jest niewidoczna dla aplikacji.
@Adnotacja transakcyjna
Adnotacja javax.transaction.Transactional
umożliwia aplikacji deklaratywne kontrolowanie granic transakcji. Ta adnotacja może być zastosowana do dowolnej klasy, którą specyfikacja Jakarta EE definiuje jako zarządzany komponent bean (w tym komponent bean zarządzany przez CDI).
Poniższy przykładowy kod ilustruje użycie @Transactional w zarządzanym komponencie bean CDI o zakresie żądań:
@RequestScoped public class ExampleBean { @Transactional public void foo () { // Transakcja jest tutaj aktywna // Wykonaj pracę } // Po zwróceniu metody transakcja zostaje zatwierdzona lub wycofana }
Zachowanie transakcyjne można skonfigurować za pomocą atrybutu w adnotacji. Dostępne opcje ściśle odzwierciedlają te ze EJB .
Adnotacja @TransactionScoped
Adnotacja javax.transaction.TransactionScoped
zapewnia aplikacji możliwość zadeklarowania, że zakres, w którym żyje komponent bean, jest powiązany z czasem aktywności danej transakcji.
Poniższy przykładowy kod ilustruje użycie @TransactionScoped w zarządzanym komponencie bean CDI o zakresie żądań:
@TransactionScoped klasa publiczna TxScopedBean { publiczny numer int ; public int getNumber () { zwraca numer ;} public void setNumber ( int number ) { this . liczba = liczba ;} } @RequestScoped klasa publiczna ExampleBean { @Inject private TxScopedBean
txScopedBean ; @Transactional public void foo () { txScopedBean . ustawLiczbę ( 1 ); } @Transactional public void bar () { System . na zewnątrz print ( tXscopedBean . getNumber ()); } }
Jeśli metoda foo() zostanie najpierw wywołana na zarządzanej instancji ExampleBean, a następnie wywołana zostanie metoda bar(), wydrukowana liczba będzie równa 0, a nie 1. Wynika to z faktu, że każda metoda miała własną transakcję, a zatem własną instancję TxScopedBean . Liczba 1, która została ustawiona podczas wywołania foo() nie będzie zatem widoczna podczas wywołania bar() .
Obsługa UserTransaction w serwerze EJB
EJB muszą obsługiwać interfejs UserTransaction do użytku przez komponenty bean EJB z wartością komponentu BEAN w adnotacji javax.ejb.TransactionManagement
(nazywa się to transakcjami zarządzanymi przez komponent bean lub BMT). Interfejs UserTransaction jest udostępniany komponentom EJB albo przez interfejs EJBContext przy użyciu metody getUserTransaction, albo bezpośrednio przez wstrzyknięcie przy użyciu ogólnego @Resource
adnotacja. W związku z tym aplikacja EJB nie łączy się bezpośrednio z Menedżerem transakcji w celu rozgraniczenia transakcji; zamiast tego komponent bean EJB polega na serwerze EJB, który zapewnia obsługę wszystkich operacji transakcyjnych zgodnie z definicją w specyfikacji Jakarta Enterprise Beans. (Podstawowa interakcja między serwerem EJB a TM jest niewidoczna dla aplikacji; ciężar wdrożenia zarządzania transakcjami spoczywa na kontenerze EJB i dostawcy serwera).
Poniższy przykładowy kod ilustruje użycie UserTransaction poprzez transakcje zarządzane przez komponent bean w komponencie sesyjnym EJB:
@Stateless @TransactionManagement ( BEAN ) klasa publiczna ExampleBean { @Resource private UserTransaction utx ; public void foo () { // rozpocznij transakcję utx . rozpocząć (); // Wykonaj pracę // Zatwierdź utx . zatwierdzić (); } }
Alternatywnie, UserTransaction można uzyskać z SessionContext:
@Stateless @TransactionManagement ( BEAN ) klasa publiczna ExampleBean { @Resource private SessionContext ctx ; public void foo () { UserTransaction utx = ctx . getUserTransaction (); // rozpocznij transakcję utx . rozpocząć (); // Wykonaj pracę // Zatwierdź utx . zatwierdzić (); } }
Należy jednak zauważyć, że w powyższym przykładzie, jeśli adnotacja @TransactionManagement(BEAN)
zostanie pominięta, transakcja JTA jest automatycznie uruchamiana za każdym razem, gdy wywoływana jest funkcja foo()
i jest automatycznie zatwierdzana lub wycofywana, gdy funkcja foo()
zostaje zakończona. Korzystanie z UserTransaction nie jest zatem konieczne w programowaniu EJB, ale może być potrzebne w przypadku bardzo specjalistycznego kodu.
Obsługa UserTransaction w JNDI
UserTransaction powinien być dostępny pod java:comp/UserTransaction
(jeśli implementacja JTA jest zainstalowana w środowisku).