Sei sulla pagina 1di 8

CP pensareprogettareprogrammare n.

136 giugno 2004

Non solo J2EE


di Giorgio Maone
` LApplication Server fornisce utilissimi servizi a chi sviluppa in Java, ma larchitettura J2EE e considerata, almeno per alcuni aspetti, complicata e pesante: siamo pronti per i Lightweight Container?

Giorgio Maone ` E responsabile tecnico per larea sviluppo software di InformAc` tion, societa di consulenza che dirige dal 1998. Si occupa di soluzioni multi-tiered su piattaforme Enterprise Java (J2EE) e Microsoft (.NET), di produzioni multimediali e di formazione negli ambiti Web, middle-tier, DB e multimedia.

pubblicato su WWW.INFOMEDIA.IT stampa digitale da Lulu Enterprises Inc. stores.lulu.com/infomedia


Infomedia
` Infomedia e limpresa editoriale che da quasi venti anni ha raccolto la voce dei programmatori, dei sistemisti, dei professionisti, degli studenti, dei ricercatori e dei professori dinformatica italiani. Sono pi` di 800 gli autori che hanno realizzato per le teu state Computer Programming, Dev, Login, Visual Basic Journal e Java Journal, molte migliaia di articoli tecnici, presentazioni di prodotti, tecnologie, protocolli, strumenti di lavoro, tecniche di sviluppo e semplici trucchi e stratagemmi. Oltre 6 milioni di copie distribuite, trentamila pagine stampate, fanno di questa impresa la pi` grande ed u inuente realt` delleditoria specializzata nel campo della a programmazione e della sistemistica. In tutti questi anni le riviste Infomedia hanno vissuto della passione di quanti vedono nella programmazione non solo la propria professione ma unattivit` vitale e un vero a divertimento. ` Nel 2009, Infomedia e cambiata radicalmente adottando ` un nuovo modello aziendale ed editoriale e si e organizzata attorno ad una idea di Impresa Sociale di Comunit` , a partecipata da programmatori e sistemisti, separando le attivit` di gestione dellinformazione gestite da un board a comunitario professionale e quelle di produzione gesti` te da una impresa strumentale. Questo assetto e in linea con le migliori esperienze internazionali e rende Infomedia ancora di pi` parte della Comunit` nazionale degli u a sviluppatori di software. ` Infomedia e media-partner di manifestazioni ed eventi in ambito informatico, collabora con molti dei pi` imporu tanti editori informatici italiani come partner editoriale e fornitore di servizi di localizzazione in italiano di testi in lingua inglese.

Limpaginazione automatica di questa rivista e realizzata al ` 100% con strumenti Open Source usando OpenOffice, Emacs, BHL, LaTeX, Gimp, Inkscape e i linguaggi Lisp, Python e BASH

For copyright information about the contents of Computer Programming, please see the section Copyright at the end of each article if exists, otherwise ask authors. Infomedia contents is 2004 Infomedia and released as Creative Commons 2.5 BY-NC-ND. Turing Club content is 2004 Turing Club released as Creative Commons 2.5 BY-ND. Le informazioni di copyright sul contenuto di Computer Programming sono riportate nella sezione Copyright alla ne di ciascun articolo o vanno richieste direttamente agli autori. Il contenuto Infomedia e 2004 Infome` dia e rilasciato con Licenza Creative Commons 2.5 BYNC-ND. Il contenuto Turing Club e 2004 Turing Club ` e rilasciato con Licenza Creative Commons 2.5 BY-ND. Si applicano tutte le norme di tutela dei marchi e dei segni distintivi. ` E in ogni caso ammessa la riproduzione parziale o totale dei testi e delle immagini per scopo didattico purch e vengano integralmente citati gli autori e la completa identicazione della testata. Manoscritti e foto originali, anche se non pubblicati, non si restituiscono. Contenuto pubblicitario inferiore al 45%. La biograa dellautore riportata nellarticolo e sul sito www.infomedia.it e di norma quella disponibi` le nella stampa dellarticolo o aggiornata a cura dellautore stesso. Per aggiornarla scrivere a info@infomedia.it o farlo in autonomia allindirizzo http://mags.programmers.net/moduli/biograa

FOCUS

Non solo J2EE


LApplication Server fornisce utilissimi servizi a chi sviluppa in Java, ma larchitettura J2EE considerata, almeno per alcuni aspetti, complicata e pesante: siamo pronti per i Lightweight Container?
di Giorgio Maone

a qualche tempo la comunit degli sviluppatori Java cosiddetti enterprise in fermento. La parola dordine sembra essere semplicit, e in molti iniziano ad esplorare percorsi alternativi alla piattaforma Java 2 Enterprise Edition tradizionalmente intesa. Nessuno mette in discussione le tecnologie fondanti, come Servlet o JDBC, ma linsofferenza da pi parti manifestata fin dalla loro comparsa verso astrazioni di livello pi alto (leggi EJB), si concretizza adesso in proposte variamente convincenti ma quantomeno tangibili. Ci si deve, almeno in parte, allattenzione che ormai riscuote lAspect Oriented Programming (AOP), non pi considerata speculazione teorica bens strumento pratico e, in quanto tale, valutabile e sfruttabile in termini pragmatici. SullAOP e sul principio non nuovissimo dellInversion of Control, o pi propriamente sulla sua specializzazione chiamata Dependency Injection, si basano alcuni framework applicativi che ambiscono a sostituire la monoliticit dellApplication Server con un approccio modulare e non invasivo, teso a cucire insieme i componenti eterogenei di unapplicazione riducendo le dipendenze esplicite, allo scopo di assicurare massima libert nelle scelte implementative. Prima di indagare le nuove tendenze, per opportuno fare brevemente il punto su ci che oggi J2EE rappresenta ed offre.

Tecnologie per la gestione della piattaforma J2EE Deployment Specification J2EE Management Specification J2EE Client Provisioning Java Authorization Contract for Containers Altre tecnologie Java DataBase Connectivity (JDBC) Java Data Objects (JDO) JavaMail Infrastruttura transazionale, cio Java Transaction API (JTA) e Java Transaction Service (JTS) Come si vede, gli EJB spesso considerati la tecnologia J2EE per antonomasia non sono che una tessera in un mosaico ricco e articolato: nessuno vieta di scrivere applicazioni J2EE facendone a meno. Molti progetti si basano effettivamente sullaccoppiata Servlet Container/JDBC e saltano a pi pari i livelli intermedi, magari con laiuto di un framework MVC come Struts e adottando il pattern DAO per non sporcare troppo il controller. Cionondimeno, gli EJB costituiscono un modello a componenti robusto, consolidato e prevedibile, che mostra allo sviluppatore un sentiero da seguire senza eccessivi sforzi di fantasia per partizionare lapplicazione ed usufruire gratuitamente di servizi indispensabili per progetti medio-grandi: gli Entity Bean rispecchiano le entit persistenti e le relazioni che tra esse intercorrono, e sono essenzialmente oggetti Java che vivono nel database, salvati e recuperati in maniera transazionale e trasparente (almeno quelli di tipo CMP); i Message-Driven Bean reagiscono ad eventi scatenati da messaggi accodati tramite JMS, e rappresentano la via ufficiale alla programmazione asincrona, visto che lEJB container proibisce il multi-threading esplicito; i Session Bean, infine, ospitano la logica applicativa, demarcano i confini delle transazioni (in modo dichiarativo o programmatico) ed interagiscono con altri EJB e con i client. In definitiva, i principali vantaggi ideali di unapplicazione composta da EJB sono: dislocazione dei componenti, che rispetto ai client possono essere locali (residenti nella stessa JVM) o remoti (anche su unaltra macchina); persistenza indipendente dal tipo di DBMS e dalluso di SQL, poich gli Entity Bean sono una forma di Object/Relational Mapping (ORM) e consentono al programmatore di lavorare su oggetti tipizzati piuttosto che su ResultSet generici;
Computer Programming n. 136 - Giugno 2004

Quel che passa il convento


Lhome page di J2EE [1] riassume le varie sfaccettature dellarchitettura raggruppandole come segue: Tecnologie per i Web Service Java API for XML Processing (JAXP) Java API for XML Registries (JAXR) Java API for XML-based RPC (JAX-RPC) SOAP with Attachments API for Java (SAAJ) Tecnologie per lo sviluppo orientato ai componenti Java Servlet JavaServer Pages (JSP) JavaServer Faces (JSF) Enterprise JavaBeans (EJB) Java Message Service (JMS) J2EE Connector Architecture (JCA) Giorgio Maone

gmaone@infomedia.it

responsabile tecnico per larea sviluppo software di InformAction, societ di consulenza che dirige dal 1998. Si occupa di soluzioni multi-tiered su piattaforme Enterprise Java (J2EE) e Microsoft (.NET), di produzioni multimediali e di formazione negli ambiti Web, middle-tier, DB e multimedia.

22

Application Server

caching e pooling, dal momento che tutti gli accessi ai dati avvengono attraverso lApplication Server (persistenza container managed) e che questultimo, pertanto, pu decidere cosa trattenere in memoria e quando, invece, il caso di scomodare il database; demarcazione dichiarativa delle transazioni, che sono in grado di propagarsi tra diversi metodi e coinvolgere risorse eterogenee (transazioni distribuite XA); sicurezza a livello di metodo (prima di eseguire una chiamata il container verifica che il chiamante abbia privilegi sufficienti). Daltra parte, com noto, gli EJB sono soggetti a dure critiche. Alcune, per cos dire storiche, riguardano soprattutto la quantit di codice necessaria a scriverli e configurarli nonch le performance non proprio brillanti. Al primo problema si pu ovviare adottando strumenti di generazione del codice, mentre le prestazioni sensibilmente migliorate con lintroduzione delle interfacce locali e la conseguente riduzione delle chiamate a metodo remoto dipendono molto dalla qualit dellApplication Server, dalla bont della sua configurazione e, ovviamente, dallaccortezza del programmatore. Le obiezioni pi solide, invece, vertono sulleccessiva invasivit dellAPI (interfacce da implementare e classi da estendere che rendono difficoltoso il riuso in altri contesti) e sulle rigidit degli Entity Bean come strumento ORM (granularit, ereditariet, relazioni, linguaggio di interrogazione). Parliamo quindi di criticit strutturali, che inducono a battere strade diverse verso unarchitettura J2EE priva degli EJB ma provvista dei vantaggi ad essi tradizionalmente associati.

oggi, essendo la riflessione sullAOP maturata giungendo a un buon livello di formalizzazione, si voglia offrire allo sviluppatore finale la possibilit di intervenire in modo semplice e selettivo sul processo di intercettazione. Lo scenario prospettato da JBoss 4 il ramo attualmente in fase di sviluppo affascinante: lapplicazione vera e propria composta da Plain Old Java Objects (POJO), vale a dire comunissimi oggetti Java a cui non sono prescritte interfacce o linee ereditarie particolari (in contrasto con gli EJB), e quindi in generale riutilizzabili anche fuori dallApplication Server. Aspetti come la persistenza, la transazionalit, linvocabilit remota, la sicurezza ecc. vengono specificati attraverso metadati esterni (descrittori XML) o interni al codice (speciali commenti JavaDoc o, in futuro, le annotations introdotte da J2SE 1.5): il framework JBossAOP li applicher magicamente al momento del deployment. Questo approccio si traduce, per la gioia di molti, in un J2EE senza EJB che mantiene intatta la sua potenza di fuoco. Ciononostante, il supporto per gli EJB sar conservato, anche se ovviamente limplementazione interna degli stessi far leva sullo strato AOP. Non si tratta solo di una scelta politica tesa a preservare la compatibilit con le applicazioni e i componenti esistenti: ladesione di JBoss Inc. allEJB Expert Group, annunciata il 5 aprile scorso, induce viceversa a sperare in una specifica EJB 3.0 pi leggera, semplice e potente che tesaurizzi lesperienza accumulata dal progetto open source.

Persistenza alternativa: Hibernate


Qualche lettore si sar gi chiesto come far JBoss 4 a rendere dinamicamente persistenti su database i POJO che, per definizione, non sono vincolati allimplementazione di interfacce particolari n sono obbligati a discendere da classi di un determinato framework. La risposta Hibernate [3], un maturo strumento ORM open source che vanta, tra le sue caratteristiche specifiche, proprio il basso tasso di intrusione e prescrizione rispetto agli oggetti da esso gestiti. Questa la principale motivazione che spinge una vasta platea di sviluppatori a preferirlo rispetto a soluzioni standard come Entity Bean e soprattutto alla diretta concorrente Java Data Objects (JDO) [4], specifica ufficiale per la persistenza degli oggetti Java. A cercare il pelo nelluovo, si pu obiettare che le tre tecnologie, pi che in competizione, sarebbero potenzialmente complementari, nellipotesi che gli Entity Bean utilizzino internamente Hibernate (come avverr in JBoss 4) e che, a sua volta, Hibernate implementi in futuro le interfacce JDO, congettura corroborata dalla presenza dellautore, Gavin King, nel JDO 2.0 Expert Group. Restando ai fatti, per mappare su un database relazionale oggetti Java con Hibernate sufficiente specificare alcuni metadati, manco a dirlo in formato XML, che possono essere centralizzati in un unico file di configurazione (come avviene con gli EJB) oppure divisi per package o per classe (opzione consigliata perch facilita il riuso). Tale incombenza enormemente alleviata da XDoclet [5], strumento per la programmazione Attribute Oriented di cui ci siamo gi occupati [6]: esso, attraverso un apposito task Ant chiamato HibernateDoclet, provvede automaticamente a generare i descrittori di mapping a partire da sorgenti commentati con particolari tag JavaDoc. Il Listato 1, ad esempio, si riferisce ad unentit che rappresenta una localit italiana. Il tag hibernate.class segnala che la classe deve essere mappata sul database, mentre con hibernate.property si contrassegnano le propriet persistenti. indispensabile individuare una o pi propriet, marcate con hibernate.id, come identificati23

La doppia vita di JBoss, leretico


JBoss [2] , oggi, il pi popolare Application Server Java. Trattandosi di un progetto open source (LGPL), gestito da sviluppatori J2EE che si confrontano quotidianamente con i limiti della piattaforma, la sua evoluzione riflette gli umori della base ed anticipa le nuove tendenze, inclusa quella che vorrebbe un ridimensionamento degli EJB ed una maggiore libert di scelta. La serie stabile 3.2.x costituisce una (eccellente) implementazione classica, attualmente in attesa della certificazione J2EE da parte di Sun. Il design fortemente modulare: alla base, un microkernel ridotto al minimo fornisce linfrastruttura di base per il classloading dinamico, lhot deployment di componenti e la gestione tramite interfaccia JMX; i servizi di medio livello (Web Server, transaction manager, security manager, gestori della persistenza, della cache, del clustering ecc.) sono nettamente divisi tra loro e ciascuno di essi racchiuso in un Service ARchive (SAR), che si pu aggiungere, rimuovere o sostituire a piacimento; i componenti applicativi, e segnatamente gli EJB, acquisiscono i comportamenti implementati dai servizi (transazionalit, persistenza, controlli di sicurezza) tramite wrapper chiamati Interceptor, che si frappongono a runtime tra il componente ed il suo utilizzatore. Gli Interceptor, in quanto mezzo per aggiungere dinamicamente comportamenti di interesse generale ad oggetti che implementano logiche applicative, rappresentavano gi dalla versione 2 di JBoss un elemento di Aspect Oriented Programming ante litteram. Non stupisce che
Computer Programming n. 136 - Giugno 2004

FOCUS
LISTATO 1
La classe Localita, unentit persistente scritta come un normale JavaBean e annotata con i tag XDoclet per Hibernate

oggetto Localita (Monreale, in provincia di Palermo) e salvarlo sul database potrebbe essere:
net.sf.hibernate.SessionFactory factory; // omessa configurazione preliminare

package com.informaction.geo.model; /** * @hibernate.class */ public class Localita { private private private private private Integer id; String des; String cap; String prefisso; Provincia provincia;

// della SessionFactory [...] net.sf.hibernate.Session session = factory.getSession(); Localita monreale = new Localita(); monreale.setDes(Monreale); monreale.setCap(90046); monreale.setPrefisso(091); // recupera un oggetto Provincia tramite ID Provincia palermo = (Provincia)session.get(Provincia.class, PA); monreale.setProvincia(palermo); session.save(monreale); // salva la localit session.flush(); // sincronizza il database

public Localita() { } /** * @hibernate.id generator-class=identity */ public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } /** * @hibernate.property */ public String getDes() { return des; } public void setDes(String des) { this.des = des; } /** * @hibernate.property */ public String getCap() { return cap; } public void setCap(String cap) { this.cap = cap; } /** * @hibernate.property */ public String getPrefisso() { return prefisso; } public void setPrefisso(String prefisso) { this.prefisso = prefisso; } /** * @hibernate.many-to-one * column=id_prov not-null=true */ public Provincia getProvincia() { return provincia; } public void setProvincia(Provincia provincia) { this.provincia = provincia; } }

Un punto di forza di Hibernate il suo linguaggio di interrogazione Hibernate Query Language (HQL), che risulta spesso molto pi espressivo dello stesso SQL, e comunque di gran lunga pi potente di EJBQL. Ecco, ad esempio, la query HQL che genera un report con il conteggio delle localit appartenenti a ciascuna provincia, raggruppando i totali per regione:
select localita.provincia.regione.des, localita.provincia.des, count(localita) from Localita localita group by 1, 2 Hibernate la tradurr pressappoco nella seguente join SQL: select regione.des, provincia.des, count(localita.id) from localita, provincia, regione where localita.id_prov=provincia.id and provincia.id_reg=regione.id and localita.id_prov=provincia.id group by 1, 2

LAPI Criteria permette, inoltre, di impostare dinamicamente i criteri di ricerca in maniera object oriented, piuttosto che esprimerli sotto forma di stringhe, e supporta le cosiddette query by example, cio la ricerca di oggetti che somigliano ad un certo modello. Viceversa, nei rari casi in cui non c alternativa, si possono eseguire query SQL a basso livello tramite Hibernate (che provveder comunque a mappare i risultati), oppure recuperare la java.sql.Connection utilizzata dalla Session corrente e operare direttamente tramite JDBC. Dulcis in fundo, il tool interattivo Hibern8IDE (Figura 1) aiuta a testare query HQL e codice Java (o, pi precisamente, BeanShell) nel contesto di Hibernate.

vo univoco che si tradurr in una primary key. Ad esplicitare la relazione molti a uno intercorrente tra la propriet provincia e lomonima classe, anchessa mappata, il tag hibernate.many-to-one, che in questo caso specifica anche la colonna da usare come foreign key. Unapplicazione che usa Hibernate innanzitutto configura un oggetto SessionFactory indicando, tra laltro, i mapping da usare e i parametri di connessione al DB. La factory sar in seguito utilizzata per ottenere oggetti Session, che sono linterfaccia principale per il dialogo con il motore di persistenza. Il codice Java per istanziare un 24

Chiamare le cose con il loro nome


Facciamo un passo indietro: curiosamente, al momento in cui scriviamo, la gi citata home page di J2EE non menziona la Java Naming and Directory Interface (JNDI) [7]; essa, tuttavia, assume nellarchitettura un ruolo centrale di collante, tenendo insieme i componenti e i servizi ospitati dallApplication Server. Le applicazioni, infatti, ottengono riferimenti alle risorse gestite dal container (EJB, code di messaggi, DataSource JDBC, UserTransaction JTA ecc.) attraverso un procedimento simile al seguente:
Computer Programming n. 136 - Giugno 2004

Application Server

import javax.naming.*; import javax.sql.*; public class DataManager { private NamingContext ctx = new InitialContext(); private DataSource dataSource = (DataSource)ctx.lookup(jdbc/mainDS); [...] }

intercettabilit tramite metodo factory, che consente di scegliere unimplementazione particolare, decorare e/o configurare loggetto prima di fornirlo allutilizzatore. Un effetto collaterale non trascurabile, daltro canto, il proliferare del codice di lookup un po dovunque, che si traduce in una forte dipendenza dellapplicazione dallinfrastruttura e, di conseguenza, in pesanti difficolt nel riutilizzare componenti al di fuori dellApplication Server, specie in unapplicazione desktop disconnessa o, comunque, in assenza di un server JNDI. Tale problema pu essere mitigato dalladozione del pattern Service Locator [8], che aiuta a centralizzare, schermare e ottimizzare gli accessi al servizio di Naming. Tuttavia, anche nellipotesi di sostituire limplementazione JNDI di un Service Locator con una versione in grado di fare a meno del container J2EE, come configurarla? Una possibile soluzione viene dai framework basati sulla Dependency Injection.

Nellesempio la classe DataManager recupera dal contesto JNDI (NamingContext) una sorgente dati tramite il nome simbolico jdbc/mainDS, al quale lamministratore del server lavr precedentemente associata intervenendo su un file di configurazione oppure operando su una GUI (laddove disponibile). Il codice lavora sullinterfaccia DataSource, la cui implementazione concreta varier a seconda del tipo di database, delleventuale gestione del pooling, del supporto per transazioni distribuite (XA) ecc. Lo scenario non dissimile da quello che, sotto Windows, riguarda ODBC: il sistemista configura una sorgente di dati particolare associandole un nome (DSN), che il programma sfrutter per cercarla ed utilizzarla secondo uninterfaccia uniforme. JNDI, tuttavia, generalizza il paradigma: consente di registrare (bind) e recuperare (lookup) risorse di ogni tipo (oggetti di qualunque classe, anche definita dallutente); una tecnologia distribuita, basata di serie su RMI, LDAP o CORBA ma estensibile con altri protocolli; offre supporto esplicito, tramite linterfaccia javax.naming.spi.ObjectFactory, per la creazione dinamica delle istanze richieste. I benefici evidenti sono: disaccoppiamento dellimplementazione dei servizi dai client, che ne conoscono solo le interfacce; trasparenza di posizione (un oggetto pu essere remoto, cio risiedere fisicamente su un elaboratore diverso da quello del client, senza che la procedura di lookup cambi);

Inversione, che invenzione!


Lespressione Inversion of Control (IoC) si riferisce a un concetto descritto in maniera sintetica quanto efficace da Michael Mattson gi nel 1996: La principale differenza tra un framework orientato agli oggetti ed una libreria di classi che il framework chiama il codice dellapplicazione. Normalmente il codice dellapplicazione a chiamare la libreria di classi. Questa inversione di controllo chiamata, a volte, il principio di Hollywood, ovvero Non chiamarci, chiameremo noi. [9] Si tratta di uno stile adottato, pi o meno consapevolmente, da ogni programmatore OOP diligente, anche perch aiuta a rispettare unaltra regola di corretto design, il Depency Inversion Principle (DIP) enunciato da Robert zio Bob Martin [10]: I moduli ad alto livello non devono dipendere dai moduli a basso livello. Gli uni e gli altri devono dipendere da astrazioni. Le astrazioni non devono dipendere dai dettagli. I dettagli devono dipendere dalle astrazioni. In parole povere (e in linguaggio Java): programmare per interfacce... LIoC, se non in teoria almeno in pratica, una delle prime cose su cui sbatte il naso un programmatore Java. Qualunque sia la tua specialit dalle Applet alle Servlet fino agli EJB ti abitui allidea di un contenitore (il browser o il server) che invoca i metodi dei tuoi oggetti, solitamente per controllarne il ciclo di vita. Questa forma di IoC, secondo la quale le classi che compongono unapplicazione implementano una o pi interfacce note, dando cos modo al framework di chiamarle, stata a lungo lunica teorizzata ed particolarmente adatta per le architetture orientate ai servizi. La sfrutta J2EE, per quanto in maniera implicita e poco sistematica, mentre ne fa la sua colonna portante il progetto Avalon [11], una specie di meta-container che si candida come infrastruttura per ogni sorta di server o di applicazione modulare. Una delle aree nelle quali si sono evidenziati i benefici dellIoC la risoluzione delle dipendenze tra componenti e servizi, o in altri termini lassemblaggio delle applicazioni. Della soluzione standard, JNDI, abbiamo gi discusso i pro e i contro. Lapproccio tipico di Avalon e di progetti similari chiamato Contextual Lookup: il compo25

FIGURA 1

Hibern8IDE, un tool per testare interattivamente query e codice Java in un contesto Hibernate

Computer Programming n. 136 - Giugno 2004

FOCUS
nente specifica le proprie dipendenze in un file di configurazione, e implementa uninterfaccia (Serviceable, nel caso di Avalon) attraverso la quale il container fornir un contesto di lookup personalizzato (ServiceManager) che consentir di recuperare tutti gli oggetti necessari e solamente quelli. Tornando allesempio del DataManager che ha bisogno di una DataSource, esso andrebbe riscritto cos:
import javax.sql.*; import org.apache.avalon.framework.*; public class DataManager implements Serviceable { private DataSource dataSource; public void service(ServiceManager sm) { dataSource = (DataSource)sm.lookup(dataSource); } [...] } <bean id=dataSource class=org.apache.commons.dbcp.BasicDataSource destroy-method=close> <property name=driverClassName> <value>org.hsqldb.jdbcDriver</value> </property> <property name=url> <value>jdbc:hsqldb:hsql://localhost:9001</value> </property> <property name=username> <value>sa</value> </property> <property name=password> <value></value> </property> </bean> } [...] }

La BeanFactory, cuore dellarchitettura di Spring, serve ad istanziare e collegare tra loro i diversi componenti (di servizio e applicativi) che formano lapplicazione, e pu essere configurata in maniera programmatica o tramite limmancabile descrittore XML. Il markup della BeanFactory semplice, ridotto allo stretto necessario per creare bean, assegnare loro un identificativo e popolarne le propriet. Tornando a noi, innanzitutto dovremo preparare una DataSource:

Non sembra un gran progresso: il nostro componente non pi accoppiato a JNDI, ma dipende comunque da Serviceable e da ServiceManager. Per di pi, riusare questo componente in assenza di Avalon sembra alquanto farraginoso: per configurarlo bisogna fornire unimplementazione alternativa di ServiceManager, riempirla e passarla al metodo service(). Allimprovviso una mente brillante, rimuginando sulla faccenda, folgorata dallesistenza di uninterfaccia implementata implicitamente dalla maggior parte degli oggetti Java e utilizzabile per configurare le dipendenze: i setter delle propriet. Sembra luovo di Colombo, al punto che si ritiene di aver scoperto un nuovo tipo di IoC, il cosiddetto Type 2, attorno al quale sar edificato Spring [12].

La rivoluzione leggera
Spring un framework applicativo open source, modulare e non invasivo, basato su AOP e Dependency Injection. Iniezione delle dipendenze la designazione proposta da Martin Fowler [13] per deflazionare luso dellespressione Inversion of Control, il cui contenuto semantico andava scivolando dal principio generale enunciato in [9] verso laccezione pi riduttiva di pattern impiegato per risolvere le dipendenze tra gli oggetti. Seguendo il consiglio di Fowler, non si parler pi di IoC Type 2 e IoC Type 3 bens, rispettivamente, di Setter Dependency Injection e Constructor Dependency Injection. Questultima, introdotta da PicoContainer [14], analizza il costruttore delloggetto per dedurne le dipendenze e tentare di soddisfarle al momento della creazione. Una scuola di pensiero (a cui il sottoscritto aderisce) tende a preferire tale procedura perch riduce il rischio di trovarsi a maneggiare oggetti non correttamente inizializzati, che Joshua Bloch chiamerebbe cattivi cittadini. Adottando la Setter Injection, scelta predefinita in Spring, il DataManager si riscrive come un normale Java Bean, privo di dipendenze dal framework:
import javax.sql.*; public class DataManager { private DataSource dataSource;

Si tratta di una BasicDataSource (cfr. [15]) che punta ad un database HSQL e che chiamiamo semplicemente dataSource. A questo punto possiamo dichiarare il nostro DataManager, iniettandogli la DataSource di cui sopra:
<bean id=dataManager class=DataManager> <property name=dataSource> <ref bean=dataSource/> </property> </bean>

In questo caso abbiamo risolto la dipendenza in maniera esplicita, indicando il nome della propriet e quello del bean da assegnarle. Spring, tuttavia, offre diverse opzioni di autowiring, cio di risoluzione automatica, tra le quali byName, che cerca tra i bean definiti nella factory quello il cui id coincide col nome della propriet da valorizzare; byType, che invece cerca un bean il cui tipo sia tale da renderlo assegnabile alla propriet (funziona se c uno ed un solo bean idoneo). Nel nostro esempio, essendoci una sola DataSource che per di pi si chiama come la propriet, le varianti
<bean id=dataManager class=DataManager autowire=byType />

e
public void setDataSource( DataSource dataSource) { this.dataSource = dataSource <bean id=dataManager class=DataManager autowire=byName />

26

Computer Programming n. 136 - Giugno 2004

Application Server

si equivalgono. Spring, inoltre, supporta anche la Constructor Injection (altrimenti non lo userei). Quindi, supposto che DataManager preveda un costruttore siffatto:
public DataManager(DataSource dataSource) { this.dataSource=dataSource; }

si potr scrivere
<bean id=dataManager class=DataManager autowire=constructor />

dietro dipendenze inutili legate al Web-tier. Lestrema flessibilit di Spring e la sua discrezione (intesa come scarsa propensione ad intromettersi nel codice applicativo) sono le fondamenta della sua popolarit: al momento in cui scriviamo, viaggia attorno agli 8.000 download mensili. La mia azienda lo sta adoperando per realizzare due versioni distinte della stessa applicazione: una desktop con interfaccia utente Swing e database embedded (HSQLDB), laltra Web based (Tapestry) con RDMBS MySQL. Entrambe sfruttano Hibernate, ed il riuso delle classi business, grazie alla Dependency Injection e allAOP, pressoch totale, a dispetto delle differenze infrastrutturali.

oppure, esplicitamente:
<bean id=dataManager class=DataManager> <constructor-arg> <ref bean=dataSource/> </constructor-arg> </bean>

Conclusioni
Quanto scritto finora non vuole essere un manifesto contro J2EE: al contrario, i framework ed i principi illustrati vanno considerati un approccio alternativo per combinare tra loro le valide tecnologie che compongono la piattaforma. Anche lo slogan J2EE senza EJB va preso con le dovute cautele: sarebbe un peccato disperdere il patrimonio di conoscenze accumulato da fior di sviluppatori su strumenti che, se maneggiati con sapienza, producono risultati egregi. Daltronde ci sono ottimi motivi per credere che la specifica EJB 3.0 assorbir molti dei concetti fin qui esposti, dallAOP alla Dependency Injection passando per i metadati espressi in annotation: finalmente gli Enterprise Java Bean si programmeranno come i POJO. Se tutto va bene, dopo una gestazione lunga e travagliata, siamo vicini alla nascita di J3EE, sotto il segno della semplicit.

Eliminando il setter ed il costruttore di default, ci si assicurer cos che un DataManager sia sempre provvisto della sua brava DataSource.

La primavera Aspect Oriented


Spring molto pi che un framework semplice e potente per configurare le applicazioni riducendo le dipendenze esplicite tra i componenti. Non a caso chiamato anche Lightweight Container, alludendo al fatto che fornisce un ambiente di esecuzione paragonabile a quello di un Application Server J2EE, ma senza compromettere la riusabilit dei componenti in altri contesti e incoraggiando pratiche virtuose come la programmazione per interfacce. Incorpora infatti un sottosistema Aspect Oriented compatibile con le specifiche pubblicate dalla AOP Alliance e abbinabile alla programmazione per metadati tramite attributi che lutente pu utilizzare per scopi specifici ma che d il meglio di s nel fornire, in maniera trasparente, servizi dinfrastruttura quali: demarcazione dichiarativa delle transazioni, sia locali che distribuite, sui metodi dei POJO; remoting basato su RMI e Web Service JAX-RPC o Caucho (protocolli Hessian e Burlap); gestione automatica delle sessioni di persistenza Hibernate. Per le applicazioni Web, il framework offre una sua interessante proposta di MVC, ma anche un eccellente supporto per le tecnologie consolidate (JSP/JSF, Struts, Velocity) ed emergenti come Tapestry [17]. Alcuni template dedicati facilitano e standardizzano limplementazione di Data Access Object basati su JDBC, Hibernate, JDO o iBATIS [18]. Il criterio ispiratore , di sicuro, la libert di scelta: a seconda delle necessit, Spring pu sostituire lApplication Server tradizionale oppure collaborare proficuamente con esso. Nella seconda ipotesi, semplifica luso degli EJB e permette di relegare i lookup JNDI nella BeanFactory, coniugando cos i vantaggi del servizio di Naming standard con quelli della Dependency Injection. Il design pulito e ben ripartito: le librerie di supporto che coprono aree non sovrapposte sono archiviate in JAR separati e autonomi, in modo che unapplicazione desktop, ad esempio, non debba portarsi
Computer Programming n. 136 - Giugno 2004

BIBLIOGRAFIA & RIFERIMENTI


[1] [2] [3] [4] [5] [6] Home page di J2EE, http://java.sun.com/j2ee Home page di JBoss, http://www.jboss.org Home page di Hibernate, http://www.hibernate.org Java Data Objects, http://java.sun.com/products/jdo Home page di XDoclet, http://xdoclet.sourceforge.net Gorgio Maone Sviluppo J2EE rapido con XDoclet, Computer Programming n. 122 [7] Java Naming and Directory Interface, http://java.sun.com/products/jndi/ [8] Service Locator Pattern, http://java.sun.com/blueprints/ corej2eepatterns/Patterns/ServiceLocator.html [9] Michael Mattson, Object-Oriented Frameworks: a survey of methodological issues, PhD thesis, University College of Karlskrona/Ronneby, 1996 [10] Robert C. Martin, The Dependency Inversion Principle, C++ Report, 1996, http://www.objectmentor.com/resources/articles/dip.pdf [11] Il progetto Avalon, http://avalon.apache.org [12] Home page di Spring, http://www.springframework.org [13] Martin Fowler - Inversion of Control Containers and the Dependency Injection pattern, http://martinfowler.com/articles/injection.html [14] PicoContainer, un framework basato su Constructor Injection, http://picocontainer.org [15] Commons DBCP, libreria di classi per il connection pooling, http://jakarta.apache.org/commons/dbcp [16] Liniziativa AOP Alliance, http://aopalliance.sourceforge.net [17] Tapestry, framework Web a componenti, http://jakarta.apache.org/tapestry/ [18] iBATIS, framework per laccesso ai DB SQL, http://www.ibatis.com

27

Potrebbero piacerti anche