La modellazione a “strati” dei framework orientati al web favorisce l‘integrazione tra diverse tecnologie. La filosofia di Spring è quella di lasciare totale libertà nelle scelte architetturali. In particolare è possibile integrare altri framework orientati allo strato Controller nel pattern MVC, sostituendo la soluzione MVC dello stesso Spring. In questo articolo viene trattata la tematica di integrazione con il framework open source più utilizzato al momento in ambito Java, vale a dire Struts.
Introduzione
Le tematiche di integrazione, ai diversi livelli e nei contesti applicativi più vari, affollano gran parte dei pensieri, e degli incubi, degli sviluppatori. Il mondo web è particolarmente complicato, data l‘eterogeneità tecnologica insita nelle architetture distribuite. Non stupisce il fatto che i progettisti di Spring abbiano improntato la “filosofia” di base del loro prodotto all‘estrema flessibilità e alla libertà di scelta delle soluzioni e dei singoli componenti architetturali. Oltre alle possibilità di scelta all‘interno del “carniere” Spring, è possibile anche integrare altre tecnologie, mantenendo comunque un soddisfacente disaccoppiamento applicativo. Questo è vero per esempio per quanto riguarda l‘accesso ai dati, che abbiamo visto in uno dei precedenti articoli, ma anche per quanto riguarda le tecnologie orientate a gestire il coordinamento dei componenti applicativi e di quelli di interfaccia nell‘ambito MVC, ossia lo strato di controllo. Riguardo a quest‘ultimo punto, per ottemperare ai suoi obblighi di flessibilità , Spring offre un supporto specifico per i vari framework presenti sul mercato. In questo articolo viene fatto riferimento particolare a Struts, che è sicuramente quello più diffuso in ambito Java.
I framework MVC e Struts
I framework disponibili in ambito Java per l‘ambiente web sono basati tutti grosso modo sul pattern MVC dal punto di vista della modellazione; dal punto di vista tecnologico ovviamente si basano tutti sulla tecnologia Servlet, che è lo standard per le applicazioni web nel mondo Java. In realtà , più o meno tutti sono orientati a risolvere le problematiche dello strato Controller e talvolta di quello di View piuttosto che del Model. Spring, al contrario, offre una serie di soluzioni per il Model, tutte più o meno basate sull‘Inversion of Control e sull‘Aspect Oriented, che costituiscono di per sà© un‘ossatura solida e flessibile; per completare il quadro, Spring fornisce anche una sua implementazione dell‘MVC, per niente inferiore a quelle degli altri framework, oltre a un sottoprogetto denominato Spring Web Flow che rappresenta una soluzione più innovativa e sofisticata rispetto alla soluzione di base. Ci si può chiedere quindi che vantaggio ci possa essere a utilizzare l‘MVC di un altro framework, piuttosto che quello di Spring. Il vantaggio può essere quello di riutilizzare le competenze acquisite in altre tecnologie, oppure di integrare senza grosse modifiche delle porzioni applicative già realizzate. Struts è sicuramente il framework più conosciuto in ambito Java ed è largamente documentato. È essenzialmente un framework orientato alla parte Controller dell‘MVC, e dunque è progettato di conseguenza: ha una servlet che funge da Front Controller, la ActionServlet, la quale delega a un componente RequestProcessor la logica di elaborazione della richiesta web. L‘elaborazione effettiva è poi demandata come in Spring a un componente “controller”. Il ruolo controller è interpretato in Struts da estensioni di classi specifiche (Actions) che risolvono le situazioni più comuni. Ricordiamo che in Spring invece tali componenti sono dei JavaBeans configurati nell‘ApplicationContext. Oltre alle problematiche comuni dello strato di controllo (validazione etc.), Struts mette a disposizione anche dei tag specifici per la parte View e una tecnologia chiamata Tiles a supporto della gestione del layout costruita basandosi sulle funzionalità di “inclusione” delle pagine JSP.
Integrazione di Struts
È possibile integrare Struts seguendo due diverse modalità . Si può scegliere di trattare le action di Struts come bean di Spring, configurabili con l‘IoC alla stregua di qualunque altro bean, oppure utilizzare semplicemente i bean di Spring all‘interno delle action di Struts. La seconda modalità verrà trattata nel paragrafo successivo. Per quanto riguarda il primo caso è disponibile un plugin che consente di caricare un context-file di Spring per la servlet ActionServlet di Struts. Tale contesto è “figlio” del WebApplicationContext caricato attraverso il ContextLoaderListener configurato nel web.xml secondo la prassi di Spring, che ricordiamo di seguito:
org.springframework.web.context.ContextLoaderListener contextConfigLocation /WEB-INF/applicationContext.xml
Il parametro contextConfigLocation permette di specificare il file di configurazione. Il file di contesto derivato dal WebApplicationContext ha per convenzione lo stesso nome della servlet di Struts, ed è prefissato da -servlet.xml: in questo modo se la servlet di Struts è configurata con nome “action” il file corrispondente di Spring sarà WEB-INF/action-servlet.xml. Per configurare il plugin è necessario aggiungere la seguente riga alla fine del file di configurazione di Struts:
value="/WEB-INF/action-servlet.xml.xml,/WEB-INF/applicationContext.xml"/>
Come si vede, è possibile utilizzare la proprietà contextConfigLocation all‘interno del tag “plug-in” per personalizzare il percorso dei file di contesto, oppure tralasciarla per utilizzare i percorsi di default. Dopo aver configurato il plug-in, è possibile configurare le proprie action con Spring utilizzando due diverse possibilità :
Sovrascrivendo il RequestProcessor di Struts con la classe DelegatingRequestProcessor di Spring.
Utilizzando la DelegatingActionProxy nell‘attributo type dell‘elemento
Entrambe queste possibilità permettono di gestire le action e le loro dipendenze all‘interno del file di configurazione di Spring. L‘associazione tra le action definite in Struts e il loro corrispettivo in Spring avviene attraverso l‘attributo path della configurazione di Struts. Per esempio se una action è configurata in questa maniera:
dovrà esistere un bean con attributo name uguale a “/nome” nel file di configurazione di Spring:
Se si vuole sovrascrivere il RequestProcessor, occorre aggiungere le seguenti righe alla configurazione di Struts:
value="org.springframework.web.struts.DelegatingRequestProcessor"/>
Occorre notare che, una volta fatto questo, non è necessario che la configurazione delle action nel file di configurazione di Struts contenga un valore per l‘attributo type. Il tipo è infatti specificato nel file di Spring dove la action è configurata con un qualsiasi altro bean. Se si vuole invece utilizzare l‘alternativa che prevede l‘uso della classe DelegatingActionProxy, occorre configurare la action in Struts in questo modo:
In questo caso, tutte le action di Struts sono dei proxy che delegano la loro logica elaborativa ai beans corrispondenti configurati in Spring secondo la convenzione sulla corrispondenza dei nomi precedentemente specificata. Per quanto riguarda la configurazione delle actions nel file di Spring non cambia niente.
Utilizzare le classi ActionSupport
Come accennato precedentemente, è possibile alternativamente utilizzare i beans di Spring all‘interno delle proprie actions. Questo perché l‘ApplicationContext è memorizzato nello “scope” del contesto della servlet, ed è possibile recuperarlo con un codice del tipo:
WebApplicationContext ctx
= WebApplicationContextUtils.getWebApplicationContext(servletContext);
Per semplicità , è anche possibile utilizzare una famiglia di sottoclassi delle action di Struts prefissate con “Support” che forniscono un metodo getWebApplicationContext():
- ActionSupport
- DispatchActionSupport
- LookupDispatchActionSupport
- MappingDispatchActionSupport
Conclusioni
La libertà nelle scelte architetturali è uno dei punti di forza di Spring. Vengono fornite un insieme di funzionalità niente affatto banali e al tempo stesso sono lasciate aperte le possibilità di integrazione con le più disparate tecnologie. Nei prossimi articoli verranno prese in rassegna altre tematiche di integrazione, come quelle relative agli EJB e ai Web Services.
Riferimenti
[1] Spring Reference 2.0
http://www.springframework.org/
[2] Craig Walls – Ryan Breidenbach, “Spring in Action”, Manning, 2005