Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 62 di 68
  • livello ninja
Indice lezioni

Transaction: modello programmatico

Come realizzare una transazione in maniera programmatica: applicazione bank account
Come realizzare una transazione in maniera programmatica: applicazione bank account
Link copiato negli appunti

Vediamo in questa lezione un esempio di sviluppo programmatico delle transazioni. Come esempio ci rifaremo proprio all'ambito bancario, grazie anche alla presenza del componente BankAccount, sviluppato nelle scorse lezioni.

Vedremo proprio come grazie allo sviluppo per componenti sia possibile creare livelli di servizio sempre più avanzati, riutilizzando gli strumenti base già a disposizione. Quello che faremo sarà estendere la web application che si occupava di amministrare i conti correnti bancari, aggiungendo una nuova funzione, il bonifico.

Il bonifico è un'operazione di scambio denaro tra due conti correnti: si identificano i due conti, si fa un prelievo dal conto mittente e si fa un deposito sul conto destinatario. Avremmo due possibilità per fare questa operazione. La prima è quella di creare uno stateless session bean in cui eseguire la logica: in questo modo potremmo sfruttare il modello dichiarativo delle transazioni. La seconda è quella di prevedere una funzione sul controller ed utilizzare il modello programmatico delle transazioni ed è quello che andremo a fare.

Riprendiamo la servlet che funge da controllo. Aggiungiamo il metodo che si occupa dell'operazione di bonifico.

//Controller.java
..//

  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ..//
    //Nuovo metodo di logica

    if (op.equalsIgnoreCase("bonifico"))
      doBonifico(request,response);  
  }

  //Il metodo effettua l'operazione di bonifico, preoccupandosi di gestire la logica transazionale dell'operazione in maniera programmatica
  private void doBonifico(HttpServletRequest request, HttpServletResponse response) throws IOException {
    //Recupero i parametri necessari a portare a termine l'operazione
    String idBeneficiario=request.getParameter("idBeneficiario");
    String idMittente=request.getParameter("idMittente");
    String amount=request.getParameter("amount");
    double amt=Double.parseDouble(amount);
    
    //Recupero la transazione dall'ambiente di esecuzione
    UserTransaction ut=null;
    try {
      ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
    } catch (NamingException e2) {
      e2.printStackTrace();
      return;
    }
    
    try {
      //Inizio la transazione
      ut.begin();
      
      //effettuo l'operazione di prelievo dal mittente
      BankAccountLocal mit = bah.findByPrimaryKey(new AccountPK(idMittente));
      mit.prelievo(amt);
      
      //effettuo l'operazione di deposito sul beneficiario
      BankAccountLocal ben = bah.findByPrimaryKey(new AccountPK(idBeneficiario));
      ben.deposito(amt);
      
      //tutte le operazioni sono andate a buon fine, commit!
      ut.commit();
      response.getOutputStream().println("L'operazione di bonifico è andata a buon fine.");
      
    } catch (Exception e) {
      try {
        System.out.print("Rolling back...");
        ut.rollback();
        System.out.println("... done");
      } catch (Exception e1) {
        e1.printStackTrace();
      }
      e.printStackTrace();
      
      //Segnalazione di operazione riuscita
      response.getOutputStream().println("Operazione non riuscita!"+e.getMessage());
    }
  }
..//

Dopo aver recuperato i parametri, recuperiamo un oggetto UserTransaction dall'ambiente di esecuzione. Per i dettagli di questo oggetto si può leggere la documentazione delle JTA. La transazione deve mantenere tra il metodo begin() e commit() le operazioni che la definiscono ed eseguire il rollback() nel caso in cui ci siano delle eccezioni.

Come si vede dal codice in rosso, la logica è molto semplice ed intuitiva. Se va tutto bene, effettuiamo il commit(), cioè rendiamo effettive le operazioni svolte sinora, altrimenti effettuiamo il rollback(), cioè ripristiniamo lo stato di partenza (indicato dal begin()).

Il recupero delle transazioni dall'ambiente di esecuzione avviene, al solito, tramite una chiamata JNDI. L'application server si occuperà di instanziarne una e restituirla al chiamante.

Modificate la pagina index.html, aggiungendo la form per chiamare questa operazione:

..//
<h3>Operazione di bonifico</h3>

<form action="controller">
  <input type="hidden" name="op" value="bonifico" /;>
  ID Mittente: <input type="text" name="idMittente" /><br/><br/>
  ID Beneficiario: <input type="text" name="idBeneficiario" /><br/><br/>
  Ammontare: <input type="text" name="amount" /><br/><br/>
  <input type="submit" value="Invia" />
</form>
..//

Per far fallire l'applicazione e testare l'efficacia della transazione sarà sufficiente inserire un beneficiario errato.

Ecco la risposta del server sia in caso positivo, sia in caso negativo.

Figura 1. Operazione eseguita correttamente (verde) e fallita(rosso)
Operazione eseguita correttamente (verde) e fallita(rosso)

Ti consigliamo anche