Primo articolo su Web Beans, un insieme di servizi per Java EE nati per rendere più agevole lo sviluppo di applicazioni. In questa prima parte verrà fatta una panoramica generale sulle specifiche, prima di passare a una trattazione più dettagliata delle varie caratteristiche che si dipanerà negli articoli successivi.
I servizi forniti da Web Beans sono complementari a quelli del modello di programmazione tradizionale di Java EE. Tali servizi forniscono, tra le altre cose, un ciclo di vita dei componenti stateful migliorato rispetto a quello Java EE, un approccio typesafe alla dependency injection, facilitazioni che riguardano l’interazione tramite event notification e un migliore approccio per quanto riguarda gli interceptor.
Web Beans può essere di notevole aiuto non solo nell’ambito delle web application, ma anche nel caso di applicazioni Java SE che operano con un container EJB lite (come previsto, per esempio, da specifiche EJB 3.1 (per maggiori approfondimenti leggere l’articolo [1] e successivi).
Java EE 5 ha un solido supporto per quanto riguarda l’accesso a risorse in maniera transazionale grazie a tecnologie ormai mature quali, ad esempio, EJB3 [3], JTA [4], JCA [5] e JPA [6]. La piattaforma Java EE 5 prevede anche diverse tecnologie largamente diffuse che riguardano l’implementazione del presentation layer, quali ad esempio Servlet [7], JSP [8] e JSF [9]. Però i due tier, il web e il transactional, sono evoluti in maniera indipendente l’uno dall’altro, perdendo l’opportunità di sviluppare insieme un component model per le web application in grado di fornire l’accesso mediante transazioni alle risorse enterprise. Web Beans dovrebbe colmare questa lacuna.
Componenti Web Bean
Web Beans è un component model compatibile sia con il web tier che con il transactional tier. Si integra, per esempio, sia con JSF che con EJB3, unificando i rispettivi modelli di queste due tecnologie. In più, Web Beans fornisce un conversation model e una gestione del context relativo alla persistenza che permettono di risolvere quei problemi legati alla gestione degli stati e alla gestione delle transazioni che affliggono JSF e JPA. Ma l’utilità di Web Beans non è limitata solo all’ambito JSF ed EJB: esso è svincolato dall’utilizzo di queste due tecnologie. Un Web Bean può anche non essere un EJB: nel caso in cui un componente necessiti dei servizi tipici degli EJB, poiche’ in Web Beans non è stata fatta alcuna duplicazione riguardo tali funzionalità, un Web Bean deve essere implementato come Session Bean. Inoltre, un Web Bean non è necessariamente limitato ad esistere all’interno di un container EE. Così il suo codice può essere riutilizzato in un contesto Java SE.
Vediamo ora in dettaglio cos’è un Web Bean. Un Web Bean è un componente applicativo che contiene business logic. Può essere invocato sia direttamente da codice Java che tramite Unified Expression Language (EL). Può accedere a risorse in maniera transazionale. Le dipendenze tra Web Bean sono gestite automaticamente dal Web Beans container, così come il loro ciclo di vita. La maggior parte dei Web Bean sono stateful e contextual. Client diversi di un componente vedono un componente in stati diversi, ma non hanno alcun controllo sul suo ciclo di vita: quindi non possono creare ne’ distruggere istanze. È il context che definisce il ciclo di vita di un’istanza e lo scope di visibilità delle istanze per i client. Un grosso vantaggio del modello contextual è che esso permette di trattare i componenti stateful come services. I client non hanno bisogno di sapere come viene gestito il ciclo di vita dei componenti che usano, e spesso neanche di sapere come è fatto tale ciclo di vita. I componenti sono accoppiati in maniera lasca poiche’ interagiscono tra di loro tramite uno scambio di messaggi (utilizzando delle API pubbliche) e il ciclo di vita di ognuno dipende dalla propria implementazione. Così è possibile sostituire un componente con uno completamente diverso ma che implementa le stesse API e che ha un ciclo di vita completamente differente dal precedente senza toccare l’implementazione degli altri.
Secondo quanto asseriscono le specifiche, un Web Bean comprende:
- un component type;
- un insieme di bindings;
- una bean implementation;
- uno scope;
- un deployment type;
- un bean name (opzionale);
- un insieme di interceptor bindings.
Component types
Un component type definisce il tipo di componente visibile ai client. Un componente può averne più di uno. Il componente dell’esempio seguente ne ha tre (BookShop, Business e Shop):
public class BookShop extends Business implements Shop { ... }
Un component type può essere un’interfaccia, una classe concreta o astratta che può essere dichiarata final o avere dei metodi final. Può essere anche di tipo array o di tipo primitivo. Tutti i component hanno di default il component type java.lang.Object. Il client di un Web Bean può eseguirne il cast facendo riferimento ad uno qualsiasi dei suoi component type.
Bindings
Più Web Beans possono implementare un component type. Vediamo un esempio. Supponiamo di avere un’applicazione che ha due diverse implementazioni di un’interfaccia chiamata PaymentProcessor:
class SynchronousPaymentProcessor implements PaymentProcessor { ... } class AsynchronousPaymentProcessor implements PaymentProcessor { ... }
Un client può avere necessità di distinguere fra le due diverse implementazioni. Una prima idea potrebbe essere quella di far specificare al client in maniera esplicita la classe che implementa l’interfaccia in questione. Ma in questo modo si viene a creare una forte dipendenza tra il client e l’implementazione, vanificando il ricorso alla interfaccia. Un binding type rappresenta una sorta di semantica visibile al client, associata a un type che è soddisfatto solo da alcune implementazioni del type stesso. Quindi, facendo sempre riferimento all’esempio precedente, è possibile introdurre due binding type che rappresentano le due implementazioni:
@Synchronous class SynchronousPaymentProcessor implements PaymentProcessor { ... } @Asynchronous class AsynchronousPaymentProcessor implements PaymentProcessor { ... }
Quando il container Web Bean incontrerà il seguente codice:
@Synchronous PaymentProcessor paymentProcessor;
verrà iniettata un’istanza di SynchronousPaymentProcessor.
Mentre, quando incontrerà il seguente codice:
@Asynchronous PaymentProcessor paymentProcessor;
verrà iniettata un’istanza di AsynchronousPaymentProcessor.
Se un Web Bean non dichiara esplicitamente un binding, allora esso avrà comunque il binding di default del tipo javax.inject.Current. I binding possono essere definiti come Java Annotation, tramite la la meta-annotation javax.inject.BindingType. Ritornando all’esempio precedente:
@BindingType @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface Synchronous {} @BindingType @Retention(RUNTIME) @Target({METHOD, FIELD, PARAMETER, TYPE}) public @interface Asynchronous {}
Alternativamente, anziche’ utilizzare @BindingType, si può dichiarare un binding type in beans.xml:
Conclusioni
In questo primo articolo è stata fatta una breve introduzione ai Web Beans e si sono descritte solo alcune delle loro caratteristiche principali. Nel prossimo articolo vedremo le altre caretteristiche insieme a qualche esempio concreto per capire meglio i vantaggi introdotti da questa nuova tecnologia.
Riferimenti
[1] Giovanni Puliti, “EJB 3.1: l’evoluzione della specie – I parte: Una panoramica sulle novità “, Mokabyte 135, Dicembre 2008 (e parte II su MB 136, parte III su MB 137)
https://www.mokabyte.it/cms/article.run?articleId=RQ7-2IR-C28-EUI_7f000001_10911033_222c1413
[2] JSR-299 Expert Group, “JSR-299: Context and Dependency Injection for Java”
[3] Enterprise JavaBeans 3
http://java.sun.com/products/ejb/
[4] JTA
http://java.sun.com/javaee/technologies/jta/index.jsp
[5] JCA
http://java.sun.com/j2ee/connector/
[6] JPA
http://java.sun.com/developer/technicalArticles/J2EE/jpa/
[7] Servlet
http://java.sun.com/products/servlet/
[8] JSP
http://java.sun.com/products/jsp/
[9] JSF
http://java.sun.com/javaee/javaserverfaces/