|
In genere, per eseguire la business logic di uno use case in cui dei client necessitino servizi offerti da entity bean, tali oggetti, che risiedono su server, devono poter essere acceduti e modificati. Questo scenario prevede molte chiamate di rete che appesantiscono il carico della trasmissione dati, maggiorando il numero delle transazioni necessarie e rendendo il codice di difficile mantenimento. Si consideri un classico use case in uno scenario di e-Banking: un web client richiede ad una servlet di trasferire fondi da un acconto ad un altro acconto. 
Fig. 1 SESSION FACADE L’intero scenario necessita di almeno sei chiamate di rete: tre per cercare gli appositi entity bean e tre per il processo di trasferimento da un acconto all’altro. Ognuna di queste chiamate ai metodi degli entity bean è una chiamata diretta da parte del client, rappresenta quindi un’unità di lavoro separata e avviene in una transazione differente per ogni chiamata. Proprio per questo motivo, se qualcosa andasse storto nel depositare i soldi, il prelievo verrebbe comunque effettuato e i soldi risulterebbero persi: l’utente viene riconosciuto e autorizzato per l’operazione di prelievo e deposito; i soldi vengono prelevati dal conto 1 (in una transazione) e depositati sul conto 2 (in un’altra transazione). Se il deposito fallisce viene invocata la condizione di rollback per la fase in questione, ma non altrettanto avviene per quella di prelievo (avvenuta in una transazione separata e quindi committed): il tutto risulta in uno stato inconsistente degli oggetti. Si potrebbe pensare di risolvere il problema in diversi modi: - aggiungendo business logic agli entity bean per gestire più operazioni per lo stesso client. Questo approccio è vivamente sconsigliato, visto che verrebbero mescolate la logica applicativa con la logica di persistenza e i risultati sarebbero di scarsa mantenibilità del codice e difficile riutilizzazione.
- utilizzare JTA (Java Transaction API) per rendere l’ invocazione dei metodi di ogni bean un’ operazione della stessa transazione. Anche in questo approccio si riscontrino forti remore:
o le performance sono ancora basse, il che è dovuto alle sei chiamate via rete; o se il client ed il server sono molto lontani, la transazione potrebbe durare a lungo, risultando in un eccessivo bloccaggio dei dati su cui si lavora e rendendo molto lento l’accesso degli altri client; o il client agisce direttamente su un API relativa agli entity bean: ogni futuro cambiamento all’API si rifletterebbe in un necessario cambiamento del codice del client; o scarsa riutilizzabilità: la logica del trasferimento fondi è incapsulata (sarebbe più corretto dire intrappolata) nel client; o la logica applicativa e quella di gestione del server vengono fuse: i ruoli degli sviluppatori sono confusi e una futura scelta di ottimizzazione del server implicherebbe un cambiamento della logica applicativa stessa. Serve quindi un intermediario che si occupi delle chiamate verso gli entity bean: i session bean sono stati progettati proprio per questo scopo. Come soluzione del problema, si consiglia di utilizzare il pattern Session Facade; il Session Facade consiste nell’utilizzo di uno strato di session bean (in genere stateless, ma funzionante anche con stateful) che operi da interlocutore con lo strato di entity bean (non più acceduti direttamente dal client).  Fig. 2 SESSION FACADE La facciata di session bean consiste in un unico punto di ingresso per le chiamate agli entità bean e consente quindi l’esecuzione dello use case in uno strato dedicato unicamente alla business logic. Il ServizioBanca session bean è “deployato” sullo stesso server degli entity bean Utente e Acconto: la loro interazione avviene tramite le interfacce locali riducendo il carico di rete; l’unica chiamata di rete che viene effettuata è quella dal client al ServizioBanca session bean. Inoltre, l’intero processo di trasferimento gira sotto un’unica transazione iniziata dal session bean (nei deployment descriptor basta settare l’attributo <transaction> a REQUIRED). La logica necessaria ad una applicazione bancaria è molto più vasta di quella presa in considerazione: altri use case dell’applicazione possono essere raggruppati in session bean. Ad esempio, uno use case relativo agli investimenti potrebbe prevedere nell’architettura dell’applicazione un session bean Investimenti che contenga logica legata all’investimento di denaro e che faccia parte della facciata dei session bean. Il Session Facade non viene quindi solo impiegato per ottimizzare le performance, ma suggerisce un’architettura standard per il partizionamento delle applicazioni J2EE in modo che i limiti tra il client e il server siano marcati da uno strato di session bean. I metodi dei session contengono la business logic di tutti gli use case dell’applicazione (totale separazione tra business e data logic).
|