Java Transaction API
{{F|programmazione|aprile 2018|}}
{{W|informatica|aprile 2018}}
La '''''Java Transaction API''''' ('''JTA''') è una delle [[Application programming interface|API]] offerte dalla [[Java EE]] (Java Enterprise Edition), ed ha lo scopo di abilitare delle [[Transazione distribuita|transazioni distribuite]], eseguite attraverso risorse [[X/Open XA]] multiple in un ambiente [[Java (linguaggio di programmazione)|Java]]. JTA è una specifica sviluppata sotto le direttive del [[Java Community Process]] come [https://jcp.org/en/jsr/detail?id=907 JSR 907]. La JTA mette a disposizione:
* una demarcazione dei confini delle transazioni.
* delle [[X/Open XA]] API che permettono alle risorse di partecipare alle transazioni.

== Architettura X/Open XA ==
In questa architettura, un Transaction Manager o un [[Transaction processing|Transaction Processing monitor]] (TP monitor) coordina le transazioni attraverso le risorse multiple come database o code di messaggi. Ogni risorsa ha il suo Resource Manager. Il Resource Manager, tipicamente, utilizza le proprie API per manipolare le risorse, ad esempio far lavorare le API [[JDBC]] con i database relazionali. Il Resource Manager permette, inoltre, che un TP monitor coordini una transazione distribuita tra se stesso e altri Resource Manager. Finalmente, entra in azione l'applicazione che comunica con il TP monitor per eseguire le tipiche operazioni sulle transazioni, come l'avvio (begin), il [[commit]] e il [[rollback]]. L'applicazione comunica anche con le risorse individuali per modificarle, usando le proprie API.

== Implementazione della JTA nell'architettura X/Open XA ==
La JTA API consiste in una serie di classi suddivise nei due seguenti [[Package (Java)|package Java]]:
* [https://docs.oracle.com/javaee/7/api/javax/transaction/package-summary.html javax.transaction]
* [https://docs.oracle.com/javaee/7/api/javax/transaction/xa/package-summary.html javax.transaction.xa]

La JTA è fabbricata sul modello dell'architettura X/Open XA, ma definisce due differenti API per il demarcamento dei confini delle transazioni. Si distingue tra un [[application server]] come un server [[Enterprise JavaBeans|EJB]] e un application component. Fornisce un'interfaccia [https://docs.oracle.com/javaee/7/api/javax/transaction/TransactionManager.html javax.transaction.TransactionManager], che è usato dall'application server vero e proprio per fare dei begin, dei commit e dei rollback delle transazioni. Fornisce inoltre un'interfaccia differente, la [https://docs.oracle.com/javaee/7/api/javax/transaction/UserTransaction.html javax.transaction.UserTransaction], che è usata dal codice generico di un client, come una servlet o un EJB, per gestire le transazioni.

L'architettura JTA richiede che ogni Resource Manager implementi l'interfaccia [https://docs.oracle.com/javaee/7/api/javax/transaction/UserTransaction.html javax.transaction.xa.XAResource] in modo da essere gestita dal TP monitor. Come spiegato in precedenza, ogni risorsa avrà la propria API specifica, per esempio:
* I database relazionali usano JDBC
* I servizi di messaggistica usano [[Java Message Service|JMS]]
* Le risorse EIS (Enterprise Information System) generalizzate usano la Java EE Connector Architecture.

== Java Transaction API ==
La Java Transaction API consiste di tre elementi: un'interfaccia di demarcamento delle transazioni ad alto livello nell'applicazione, un'interfaccia Transaction Manager sempre ad alto livello, e una mappatura Java standard del protocollo X/Open XA destinato ad un Resource Manager transazionale.

=== Interfaccia ''UserTransaction'' ===
L'interfaccia [https://docs.oracle.com/javaee/7/api/javax/transaction/UserTransaction.html javax.transaction.UserTransaction] fornisce all'applicazione l'abilità di controllare i limiti delle transazioni in modo programmatico. Questa interfaccia può essere usata dai programmi Java lato client o dai bean EJB.

Il metodo '''''begin()''''' inizia una transazione globale e la associa con il thread in chiamata. L'associazione transaction-to-thread è gestita in modo trasparente dal Transaction Manager.

Non è richiesto un supporto per le transazioni annidate. Il metodo begin() lancia l'eccezione ''NotSupportedException'' quando il thread è già associato con una transazione e l'implementazione del Transaction Manager non supporta le transazioni annidate.

Il contesto in cui si propaga la transazione tra applicazioni è assegnato dalle implementazioni in background dei Transaction Manager sulle macchine client e server. Il formato del contesto usato per la propagazione è dipendente dal protocollo e deve essere negoziato tra gli host client e server. Per esempio, se il Transaction Manager è un'implementazione della specifica [[Java Transaction Service|JTS]], userà quello specificato in CORBA OTS 1.1. La propagazione delle transazioni è trasparente all'applicazione.

=== Annotazione ''@Transactional'' ===
L'annotazione [https://docs.oracle.com/javaee/7/api/javax/transaction/Transactional.html javax.transaction.Transactional] fornisce all'applicazione l'abilità di controllare i limiti delle transazioni in modo dichiarativo. Questa annotazione può essere applicata ad ogni classe che la Java EE definisce come ''managed bean'' (che include i CDI managed bean).

L'esempio di codice sottostante illustra l'uso di ''@Transactional'' in un ambito dove si richiedono i CDI managed bean:

<syntaxhighlight lang="java">
@RequestScoped
public class ExampleBean {

    @Transactional
    public void foo() { // La transazione qui è attiva
        
        // Esegue del codice

    } // Dopo il return, alla transazione viene fatto un commit o un rollback
}
</syntaxhighlight>

Il comportamento della transazione può essere configurato con un attributo nell'annotazione.

=== Annotazione ''@TransactionScoped'' ===
L'annotazione [https://docs.oracle.com/javaee/7/api/javax/transaction/TransactionScoped.html javax.transaction.TransactionScoped] fornisce all'applicazione la possibilità di dichiarare che, l'ambito durante il quale un Bean vive, è legato al tempo in cui una certa transazione è attiva.

L'esempio di codice sottostante mostra l'uso di ''@TransactionScoped'' in un ambito dove si richiedono i CDI managed bean:

<syntaxhighlight lang="java">
@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());
    }
}
</syntaxhighlight>

Se il metodo ''foo()'' è chiamato per primo su un'istanza gestita di ExampleBean e successivamente viene chiamato il metodo ''bar()'', il numero stampato a video sarà 0 e non 1. Questo perché ogni metodo ha la propria transazione e perciò anche la propria istanza di TxScopedBean. Il numero 1 che viene assegnato durante la chiamato a ''foo()'' non sarà quindi visibile durante la chiamata a ''bar()''.

== Supporto di ''UserTransaction'' nei server EJB ==
I server [[Enterprise JavaBeans|EJB]] sono richiesti per supportare l'interfaccia ''UserTransaction'' per l'uso dagli EJB Bean con il valore BEAN nell'annotazione [https://docs.oracle.com/javaee/7/api/javax/ejb/TransactionManagement.html javax.ejb.TransactionManagement] (questa è chiamata bean-managed transaction o BMT). L'interfaccia ''UserTransaction'' è esposta ai componenti EJB attraverso sia con l'interfaccia EJBContext che usa il metodo getUserTransaction, sia direttamente usando la generica annotazione ''@Resource''. Pertanto, un'applicazione EJB non si interfaccia direttamente con il Transaction Manager per la demarcazione delle transazioni; invece, gli EJB Bean contano sul server EJB per fornire supporto per tutto il suo lavoro transazionale, come definito nell'Enterprise JavaBeans Specification. (L'interazione sottostante tra EJB Server e TM è trasparente all'applicazione; l'onere di implementare la gestione delle transazioni è sul EJB container e sul server provider.)

Il codice di esempio sottostante mostra l'uso di ''UserTransaction'' attraverso le transazioni bean-managed in una session EJB Bean:

<syntaxhighlight lang="java">
@Stateless
@TransactionManagement(BEAN)
public class ExampleBean {

    @Resource
    private UserTransaction utx;

    public void foo() {
        // start a transaction
        utx.begin();

        // Do work

        // Commit it
        utx.commit();
    }
}
</syntaxhighlight>

In alternativa, la ''UserTransaction'' può essere ottenuta dal ''SessionContext'':

<syntaxhighlight lang="java">
@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();
    }
}
</syntaxhighlight>

Bisogna notare che nell'esempio se l'annotazione ''@TransactionManagement(BEAN)'' fosse stata omessa, una transazione JTA sarebbe iniziata automaticamente ogni volta che viene chiamato ''foo()''  e, sempre automaticamente, avverrebbe un commit e un rollback quando si esce da ''foo()''. L'uso di una ''UserTransaction'' non è quindi necessario nella programmazione EJB, ma può essere richiesto nel codice più specializzato.

== Supporto di ''UserTransaction'' in JNDI ==
''UserTransaction'' è disponibile sotto ''java:comp/UserTransaction'', se nell'ambiente è installata un'implementazione della JTA.

== Implementazioni Open source per la JTA ==
Alcune implementazioni open source per la JTA sono elencate qui di seguito (aggiornato a settembre 2010):
* Narayana
* Atomikos TransactionsEssentials
* Bitronix JTA

== Voci correlate ==
* [[Transazione (basi di dati)|Transazione]]
* [[Transazione distribuita]]
* [[Java EE]]

== Collegamenti esterni ==
* {{Collegamenti esterni}}

{{portale|informatica}}

[[Categoria:Teoria delle basi di dati]]
[[Categoria:Java EE]]