Jakarta Transacties - Jakarta Transactions
De Jakarta Transactions ( JTA ; voorheen Java Transaction API), een van de Jakarta EE API's , maakt het mogelijk om gedistribueerde transacties uit te voeren over meerdere X/Open XA- bronnen in een Java- omgeving. JTA was een specificatie ontwikkeld onder het Java Community Process als JSR 907. JTA voorziet in:
- afbakening van transactiegrenzen
- X/Open XA API waardoor resources kunnen deelnemen aan transacties.
X/Open XA-architectuur
In de X/Open XA-architectuur coördineert een transactiemanager of transactieverwerkingsmonitor (TP-monitor) de transacties over meerdere bronnen, zoals databases en berichtenwachtrijen. Elke resource heeft zijn eigen resourcemanager. De resourcemanager heeft doorgaans zijn eigen API voor het manipuleren van de resource, bijvoorbeeld de JDBC- API om met relationele databases te werken. Bovendien stelt de resourcemanager een TP-monitor in staat om een gedistribueerde transactie tussen zijn eigen en andere resourcemanagers te coördineren. Ten slotte is er de applicatie die communiceert met de TP-monitor om de transacties te starten, vast te leggen of terug te draaien. De applicatie communiceert ook met de individuele bronnen met behulp van hun eigen API om de bron te wijzigen.
JTA-implementatie van de X/Open XA-architectuur
De JTA API bestaat uit klassen in twee Java-pakketten :
De JTA is gemodelleerd naar de X/Open XA-architectuur, maar definieert twee verschillende API's voor het afbakenen van transactiegrenzen. Het maakt onderscheid tussen een applicatieserver zoals een EJB- server en een applicatiecomponent. Het biedt een interface, javax.transaction.TransactionManager, die door de applicatieserver zelf wordt gebruikt om de transacties te starten, vast te leggen en terug te draaien. Het biedt een andere interface, de javax.transaction.UserTransaction, die wordt gebruikt door algemene klantcode zoals een servlet of een EJB om de transacties te beheren.
De JTA-architectuur vereist dat elke resourcemanager de javax.transaction.xa.XAResourceinterface moet implementeren om door de TP-monitor te kunnen worden beheerd. Zoals eerder vermeld, heeft elke resource zijn eigen specifieke API, bijvoorbeeld:
- relationele databases gebruiken JDBC
- berichtenservices gebruiken JMS
- gegeneraliseerde EIS ( Enterprise Information System ) - bronnen gebruiken Java EE Connector API .
Interface voor applicatieprogrammering:
De Jakarta Transactions API bestaat uit drie elementen: een demarcatie-interface voor applicatietransacties op hoog niveau, een transactiebeheerinterface op hoog niveau bedoeld voor een applicatieserver en een standaard Java-toewijzing van het X/Open XA-protocol bedoeld voor een transactionele resourcemanager.
Gebruikerstransactie-interface
De javax.transaction.UserTransactioninterface biedt de applicatie de mogelijkheid om transactiegrenzen programmatisch te beheren. Deze interface kan worden gebruikt door Java-clientprogramma's of EJB-bonen.
De UserTransaction.begin()methode start een globale transactie en koppelt de transactie aan de aanroepende thread. De transactie-naar-thread-associatie wordt transparant beheerd door de Transactiemanager.
Ondersteuning voor geneste transacties is niet vereist. De methode UserTransaction.begin genereert de NotSupportedException wanneer de aanroepende thread al is gekoppeld aan een transactie en de implementatie van transactiebeheer geen geneste transacties ondersteunt.
Transactiecontextpropagatie tussen applicatieprogramma's wordt verzorgd door de onderliggende transactiebeheerimplementaties op de client- en servermachines. Het transactiecontextformaat dat wordt gebruikt voor propagatie is protocolafhankelijk en moet worden onderhandeld tussen de client- en serverhosts. Als de transactiemanager bijvoorbeeld een implementatie is van de JTS- specificatie, zal deze het transactiecontextpropagatieformaat gebruiken zoals gespecificeerd in de CORBA OTS 1.1-specificatie. Transactievoortplanting is transparant voor applicatieprogramma's.
@Transactionele annotatie
De javax.transaction.Transactionalannotatie biedt de toepassing de mogelijkheid om transactiegrenzen declaratief te controleren. Deze annotatie kan worden toegepast op elke klasse die de Jakarta EE-specificatie definieert als een beheerde bean (inclusief CDI beheerde bonen).
Het onderstaande codevoorbeeld illustreert het gebruik van @Transactional in een door CDI beheerde bean met aanvraagbereik:
@RequestScoped
public class ExampleBean {
@Transactional
public void foo() { // A transaction is active here
// Do work
} // After the method returns transaction is committed or rolled back
}
Transactiegedrag kan worden geconfigureerd via een attribuut op de annotatie. De beschikbare opties sluiten nauw aan bij die van de EJB- specificatie.
@TransactionScoped annotatie
De javax.transaction.TransactionScopedannotatie biedt de toepassing de mogelijkheid om te verklaren dat de reikwijdte waarin een boon leeft, is gekoppeld aan de tijd dat een bepaalde transactie actief is.
Het onderstaande codevoorbeeld illustreert het gebruik van @TransactionScoped in een CDI-beheerde bean met aanvraagbereik:
@TransactionScoped
public class TxScopedBean {
public int number;
public int getNumber() {return number;}
public void setNumber(int number) {this.number = number;}
}
@RequestScoped
public class ExampleBean {
@Inject
private TxScopedBean txScopedBean;
@Transactional
public void foo() {
txScopedBean.setNumber(1);
}
@Transactional
public void bar() {
System.out.print(tXscopedBean.getNumber());
}
}
Als methode foo() eerst wordt aangeroepen op een beheerd exemplaar van VoorbeeldBean en vervolgens methode bar() wordt aangeroepen, is het afgedrukte nummer 0 en niet 1. Dit komt omdat elke methode zijn eigen transactie had en dus zijn eigen exemplaar van TxScopedBean . Het nummer 1 dat is ingesteld tijdens de oproep naar foo() zal daarom niet worden gezien tijdens de oproep naar bar() .
Ondersteuning voor gebruikerstransacties in EJB-server
EJB- servers moeten de UserTransaction-interface ondersteunen voor gebruik door EJB-beans met de BEAN-waarde in de javax.ejb.TransactionManagement annotatie (dit wordt bean-managed transacties of BMT genoemd). De UserTransaction-interface wordt blootgesteld aan EJB-componenten via de EJBContext-interface met behulp van de getUserTransaction-methode, of rechtstreeks via injectie met behulp van de algemene @Resourceannotatie. Een EJB-toepassing communiceert dus niet rechtstreeks met de Transactiemanager voor het afbakenen van transacties; in plaats daarvan vertrouwt de EJB-bean op de EJB-server om ondersteuning te bieden voor al zijn transactiewerk zoals gedefinieerd in de Jakarta Enterprise Beans-specificatie. (De onderliggende interactie tussen de EJB-server en het TM is transparant voor de toepassing; de last van het implementeren van transactiebeheer ligt bij de EJB-container- en serverprovider.)
Het onderstaande codevoorbeeld illustreert het gebruik van UserTransaction via door bean beheerde transacties in een EJB-sessiebean:
@Stateless
@TransactionManagement(BEAN)
public class ExampleBean {
@Resource
private UserTransaction utx;
public void foo() {
// start a transaction
utx.begin();
// Do work
// Commit it
utx.commit();
}
}
Als alternatief kan de UserTransaction worden verkregen via de SessionContext:
@Stateless
@TransactionManagement(BEAN)
public class ExampleBean {
@Resource
private SessionContext ctx;
public void foo() {
UserTransaction utx = ctx.getUserTransaction();
// start a transaction
utx.begin();
// Do work
// Commit it
utx.commit();
}
}
Merk echter op dat in het bovenstaande voorbeeld, als de @TransactionManagement(BEAN)annotatie wordt weggelaten, een JTA-transactie automatisch wordt gestart wanneer deze foo()wordt aangeroepen en automatisch wordt vastgelegd of teruggedraaid wanneer deze foo()wordt afgesloten. Het gebruik van een UserTransaction is dus niet nodig bij EJB-programmering, maar kan nodig zijn voor zeer gespecialiseerde code.
Ondersteuning voor gebruikerstransacties in JNDI
De UserTransaction moet beschikbaar zijn onder java:comp/UserTransaction(als er een JTA-implementatie in de omgeving is geïnstalleerd).