In questo articolo vedremo come avviare lo sviluppo di una web application il cui front-end è sviluppato con tecnologia Flex e il back-end sviluppato con Java, su sistema operativo Windows.
Nella prima parte seguiremo passo passo la configurazione di un progetto unico per realizzare applicazioni Flex/Java EE. Poi esamineremo gli elementi necessari a creare un solo progetto per lo sviluppo di applicazioni enterprise basate su interfaccia grafica Flex e su servizi sviluppati in Java.
I tools necessari
Iniziamo elencando gli strumenti che ci permetteranno di creare il progetto:
- Eclipse (Classic 3.7 Indigo);
- Web Tools Platform (per Indigo), da installare come plugin di Eclipse con la classica procedura per installare un nuovo software inserendo il seguente link:
http://download.eclipse.org/webtools/repository/indigo/
- Apache Tomcat (in questo articolo utilizzeremo la versione 6.0);
- Flash Builder 4.5 (Plugin per Eclipse);
Creazione del Dynamic Web Project
Dopo aver installato tutti gli strumenti elencati, il primo passo è creare un progetto di tipo Dynamic Web: in Eclipse, clicchiamo su File > New > Other…
(oppure digitiamo Ctrl+N
).
Nella schermata che appare scorriamo l'albero fino ad individuare la voce Web
, selezionandola comparirà l'elenco dei tipi di progetto, tra cui la voce Dynamic Web Project. Dopo averla selezionata, clicchiamo Next.
Specifichiamo il nome del progetto in Project name
, lasciando invariati gli altri parametri, esattamente come mostrato in figura. Cliccando su Next, apparirà la maschera in cui indicare le cartelle che ospitano i sorgenti:
Cliccando il pulsante Edit…
modifichiamo il nome della directory src
in java-src
e clicchiamo Next.
Tale modifica risulta necessaria per separare la directory contenente il codice sorgente Java e la directory contenente i sorgenti che implementano l'interfaccia grafica (in Flex). Successivamente infatti, creeremo una directory che chiameremo flex-src
. A questo punto appare l'ultima schermata di configurazione del progetto.
Lasciamo inalterati i parametri e clicchiamo su Finish
. Inizierà il processo di creazione automatico del progetto all'interno del workspace, al termine del quale Eclipse ci chiederà se mutare la prospettiva corrente nella prospettiva Java EE.
Decidiamo di scegliere la risposta affermativa e osserviamo i risultati della creazione del progetto nel Project Explorer:
Aggiungere un progetto Flex
A questo punto possiamo trasformare il nostro progetto da Java EE a Flex/Java EE grazie ad una serie di operazioni. Iniziamo cliccando col tasto destro sul progetto, nel menu che appare individuiamo la voce Add/Change Project Type > Add Flex Project Type…
.
Una volta cliccato, iniziamo a configurare il progetto Flex selezionando l'SDK:
Clicchiamo su Next
, nella schermata visualizzata non modifichiamo nessun parametro e ultimiamo l'aggiunta del progetto Flex cliccando su Finish
. Eclispe a questo punto ci chiederà se cambiare la prospettiva da Java EE in Flash:
Confermiamo, e verifichiamo le modifiche effettuate al progetto nel Package Explorer
. Se tutto è andato a buon fine, ci ritroveremo la prospettiva di figura 11. In particolare, dovremmo avere un errore nel tab Problems
che ci segnala l'impossibilità della creazione del wrapper HTML.
Per risolvere questo problema, seguiamo esattamente il suggerimento proposto dall'IDE: clicchiamo col tasto destro sulla riga d'errore (quella cerchiata in rosso) e, nel menu che appare clicchiamo su Recreate HTML Templates
Tale correzione, comporta due modifiche: l'eliminazione della segnalazione del problema e la creazione di un'ulteriore directory all'interno del nostro progetto, denominata html-template
, che costituirà il wrapper HTML segnalato dall'errore appena corretto.
Configurazione di un progetto Server
Prima di addentrarci nella configurazione del progetto Flex/Java EE, è necessario creare un nuovo progetto di tipo Server. Tale progetto permette di simulare l'esecuzione dell'application server Apache Tomcat attraverso Eclipse. Questo ci permetterà di lanciare da Eclipse, attraverso un unico comando di run, l'intera applicazione. Procediamo come segue: File > New > Other
e dall'elenco individuiamo la voce Server espandendo la relativa directory:
Clicchiamo su Next
e avanziamo alla schermata successiva:
Dall'elenco della directory Apache, selezioniamo Tomcat v6.0 Server (supponendo che abbiate installato la versione 6.0 come indicato all'inizio dell'articolo); clicchiamo su Next e avanziamo nella schermata di figura 16:
Dalla finestra Available
(che contiene l'elenco dei Dynamic Web Project del workspace corrente) selezioniamo il nostro progetto e clicchiamo su Add >
per aggiungerlo alla nostra configurazione. Clicchiamo su Finish per terminare. In Project Explorer comparirà il progetto appena creato con il nome Servers.
Allo stesso tempo vedremo comparire una nuova voce nella tab Servers:
Notiamo che selezionando la voce, si evidenziamo delle icone utili per la gestione del server; grazie a queste icone potremo effettuare lo Start e lo Stop del server, Start del server in debug mode ecc…
.
Clicchiamo sull'icona che rappresenta un Play per avviare il server (ricordiamo che al deploy di nuovi file .class all'interno della WEB-INF di Tomcat è necessario riavviare il server).
Nella seconda parte dell'articolo vedremo come effettuare la configurazione del progetto Flex/Java EE
Configurazione del progetto Flex/Java EE
La configurazione del progetto è la parte più critica, per cui è necessario rispettare i passaggi descritti. Innanzitutto effettuiamo alcune modifiche alle directory presenti nel progetto:
- Selezioniamo la directory src, e rinominiamola in flex-src (la directory che contiene i sorgenti flex, cioè i file mxml e le classi in action script)
- Allo stesso modo, rinominiamo la directory libs in flex-libs (la directory che conterrà eventuali librerie di supporto per lo sviluppo della web application)
- Aggiungiamo una nuova directory al progetto, denominandola java-libs (directory che conterrà eventuali librerie java da aggiungere al Java Build Path).
Dopo aver effettuato il download dell'esempio allegato a questo articolo, estraiamolo e visitiamone il contenuto; individuiamo la cartella WEB-INF nella directory WebContent
e la copiamo nella cartella WebContent
del nostro progetto, sovrascrivendo quella che c'è.
Questa Il motivo di quest'ultima operazione, consiste nel fatto che la WEB-INF
copiata contiene dei file di configurazione appositamente parametrizzati per poter essere utilizzati in un progetto Flex/Java EE, che permettono all'applicazione Flex di "comunicare" con l'applicazione Java EE, attraverso Blaze DS (che approfondiremo in un articolo a parte). In particolare, le directory d'interesse sono libs e flex e il file web.xml.
La directory libs, in questo caso contiene tutte le librerie che costituiscono BlazeDS (chiaramente possiamo includere tutte le librerie necessarie al nostro progetto).
La directory flex, contiene i file di configurazione per la parametrizzazione dei servizi di messaging e remoting implementati da BlazeDS.
Infine web.xml, che costituisce il file di configurazione generale dell'applicazione che verrà eseguita in Apache Tomcat. A questo punto lanciamo la finestra delle proprietà del progetto cliccando su Project > Properties
.
Nell'elenco a sinistra selezioniamo Flex Build Path e assicuriamoci che sia selezionato il tab Library path:
In questa finestra effettuiamo le seguenti modifiche:
Selezioniamo la cartella libs
e clicchiamo su Edit…
. Nella finestra che compare clicchiamo su Browse e individuiamo il progetto presente nel nostro workspace; una volta individuata la directory del progetto, selezioniamo la "nuova libs" che precedentemente abbiamo rinominato in flex-libs.
A questo punto è necessario aggiungere una serie di librerie che permetteranno all'applicazione Flex di comunicare con quella Java; clicchiamo sul pulsante Add SWC Folder…
e nella finestra che compare è necessario inserire il seguente percorso (o lo individuiamo cliccando su Browse):
{MyFileSystem}AdobeAdobe Flash Builder 4.5eclipsepluginscom.adobe.flexbuilder.project_4.5.1.313231dcradSwcs4.5libs
La directory libs selezionata contiene le librerie fds.swc e serializers.swc.
Chiaramente la dicitura {MyFileSystem}
deve essere sostituita con la directory che ospita la cartella Adobe (ad esempio C:Programmi(x86)
);
Allo stesso modo aggiungiamo una seconda directory SWC, inserendo questo path:
{MyFileSystem}AdobeAdobe Flash Builder 4.5eclipsepluginscom.adobe.flexbuilder.project_4.5.1.313231dcradSwcs4.5locale
La directory locale contiene le librerie fds_rb.swc
e serializers_rb.swc
.
Con un'operazione analoga alle precedenti, aggiungiamo tre file swc: clicchiamo sul pulsante Add SWC…
e inseriamo:
fiber.swc: {MyFileSystem}AdobeAdobe Flash Builder 4.5eclipsepluginscom.adobe.flexbuilder.project_4.5.1.313231fiberSwcs4.5libsfiber.swc fiber_rb.swc: {MyFileSystem }AdobeAdobe Flash Builder 4.5eclipsepluginscom.adobe.flexbuilder.project_4.5.1.313231fiberSwcs4.5localefiber_rb.swc playerfds.swc: {MyFileSystem }AdobeAdobe Flash Builder 4.5eclipsepluginscom.adobe.flexbuilder.project_4.5.1.313231fiberSwcs4.5libsplayerfds.swc
Nella finestra Build path libraries
selezioniamo libs e clicchiamo sul pulsante Edit…
. Nella finestra che appare, clicchiamo su Browse
e individuiamo la directory flex-libs
selezionandola dal nostro progetto presente nel workspace. All'interno della cartella flex-libs
aggiungiamo tutte le librerie che ci occorrono per realizzare il progetto finale, e secondo questa configurazione, tali librerie sono automaticamente aggiunte al build path dell'applicazione Flex.
Ad esempio, se stiamo sviluppando l'interfaccia grafica utilizzando il framework PureMVC, una volta scaricata la libreria PureMVC_AS3_2_0_4.swc
, la andremo a copiare all'interno di flex-libs
.
A questo punto, individuiamo la voce Main source folder correntemente impostata con il valore src: clicchiamo su Browse e cambiamola in flex-src selezionandola dal nostro progetto; con questa operazione abbiamo reso la directory flex-src, precedentemente creata, la cartella principale dei sorgenti per lo sviluppo dell'applicazione flex.
Spostiamoci alla voce Output folder correntemente impostata con bin-debug e con analoga operazione, impostiamo il valore WebContent, ovviamente sempre appartenente al progetto che stiamo creando: in questo modo l'output che consiste nei file swf prodotti dalla compilazione dei nostri sorgenti, verranno salvati nella WebContent del dynamic web project creato.
Se abbiamo effettuato correttamente tutte le operazioni descritte, il Flex Build Path avrà la consistenza della figura seguente:
Cliccando su OK, eclipse effettuerà un update di tutti i riferimenti che abbiamo impostatato.
Rilanciamo la finestra Project > Properties
e individuiamo la voce Flex Applications. Nella finestra Select the runnable application files
, impostiamo il file mxml che verrà eseguito quando effettueremo il Run dell'applicazione; allo stato corrente, la directory flex-src
contiene il file Main.mxml
, quindi selezioniamo questo. Una volta aggiungo, selezioniamolo e clicchiamo sul pulsante Set as Default, in maniera tale che quando aggiungeremo altri file al nostro progetto, questo resterà il file che sarà eseguito per default.
Al termine di questa impostazione, Flex Applications sarà configurata come in figura:
Clicchiamo su OK per aggiornare i riferimenti.
Rilanciamo la finestra Project > Properties
e individuiamo la voce Flex Compiler. Nella finestra Additional compiler arguments
impostiamo l'argomento -service
che permette di indicare il file di configurazione da leggere in fase di compilazione per l'individuazione dei servizi che svilupperemo.
Per impostare l'argomento scriviamo all'interno della finestra prima citata la seguente stringa:
-services "{MyFileSystem}workspacehtml.it_staruprojectWebContentWEB-INFflexservices-config.xml" -locale en_US
Analizzando tale stringa, si intuisce che all'argomento services associamo il file di configurazione services-config.xml
presente nella directory WebContentWEB-INFflex
del progetto.
Clicchiamo su Apply
per aggiornare i riferimenti.
Individuiamo la voce Flex Server: qui imposteremo la tipologia di application server che eseguirà l'applicazione finale (quindi Apache Tomcat).
Per la voce Application server type
, selezioniamo Java dal menu a tendina che compare (ovviamente impostiamo Java perchè l'application server che vogliamo utilizzare è Apache Tomcat); si attiveranno altre voci come in figura:
Il primo passo è scegliere BlazeDS per utilizzare i servizi di remoting JAVA; successivamente compiliamo i campi di Server location, in particolare:
Root folder: deve contenere il path che individua directory che contiene i file che verranno eseguiti dall'application server.
La nostra applicazione verrà eseguita all'interno di Eclipse sfruttando la configurazione del progetto Servers precedentemente descritta) che simula l'esecuzione di Apache Tomcat in Eclipse; ricordiamo inoltre che l'output (consistente nei file .class e .swf che vengono generati dalla compilazione e che verranno eseguiti a run-time), è salvato nella cartella WebContent
(come impostato anche in Output folder), quindi sarà proprio WebContent
a diventare la nostra Root folder.
Per impostare tale directory, al solito clicchiamo su Browse
e individuiamo la WebContent
del nostro progetto. Il risultato sarà un path del tipo:
{MyFileSystem}workspacehtml.it_staruprojectWebContent
Root URL: deve contenere l'URL del progetto quando questo viene eseguito nell'application server locale; genericamente sarà un URL del tipo
http://{servername}:{port}/{my_project_folder}/
Nel caso specifico il server locale ci suggerisce di impostare servername=localhost
, la porta sarà la 8080
dato che viene eseguito Tomcat. Quindi inseriremo un URL di questo tipo:
http://localhost:8080/html.it_startuproject/
Context root: deve contenere il nome del nostro progetto.
Clicchiamo su Validate Configuration
per sincronizzare le impostazioni con la versione simulata dell'application server, e infine su OK
.
Qui termina la configurazione del progetto e possiamo iniziare a creare tutti i servizi necessari al progetto.
Nella terza parte vedremo come creare e consumare un servizio BlazeDS/Java.
Creazione di un service Java-BlazeDS
In questo esempio creeremo un semplice servizio e vedremo come l'applicazione client in Flex comunica con tale servizio attraverso BlazeDS.
Per semplicità, l'esempio consisterà nell'inserire un valore intero N all'interno di un campo di testo e nella stampa dei primi N numeri naturali; l'interfaccia sviluppata in Flex permetterà di inserire il valore N e di presentare in un datagrid tali numeri, mentre il servizio in Java catturerà il valore di input inserito e calcolerà i valori da presentare a video.
Nella directory java-src, creiamo un nuovo package chiamandolo services, che diventerà la sede dei nostri servizi; all'interno di quest'ultimo, realizziamo una classe (che chiameremo MyService.java
) che implementa il servizio:
package services;
import java.util.ArrayList;
public class MyService {
public ArrayList<Integer> getSequence(int limit){
ArrayList<Integer> sequence = new ArrayList<Integer>();
for (int i=1; i<=limit; i++)
sequence.add(i);
return sequence;
}
}
Successivamente dobbiamo segnalare l'esistenza del nuovo servizio a BlazeDS; per farlo, inseriamo il codice seguente all'interno del file remoting-config.xml all'interno del tag <service>:
<destination id="my_service">
<properties>
<source>services.MyService</source>
<scope>request</scope>
</properties>
</destination>
Questo markup indica a BlazeDS il nome del servizio creato (attributo id="my_service"
del tag destination
), la classe che implementa il servizio (tag source
) e la visibilità del servizio (impostata a livello di richiesta nel tag scope
).
Assicuriamoci di visualizzare la perspective Java EE, selezioniamo dalla sezione view il tab Servers e avviamo il server precedentemente creato: questa operazione è necessaria perchè permette di compilare la classe creata e di eseguire BlazeDS segnalandogli la creazione del servizio.
Spostiamoci ora nel lato client dell'applicazione, creando un'interfaccia contenente un campo di input in cui inserire l'intero N
, un pulsante che attiva l'evento per la visualizzazione del risultato, e un datagrid che visualizza il risultato.
Nota: lo scopo dell'esempio è solo quello di mostrare i passaggi per la creazione di un servizio da utilizzare in un'applicazione Flex, pertanto trascureremo un'implementazione a regola d'arte del codice, implementando all'interno di un'unica classe tutto il codice necessario.
Implementiamo il seguente codice di all'interno del file Main.mxml
:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"
width="400" height="250">
<fx:Declarations><!-- Place non-visual elements (e.g., services, value objects) here --></fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable] private var sequence:ArrayCollection;
[Bindable] private var limit:int;
private function getSequence():void{ }
]]>
</fx:Script>
<mx:VBox horizontalAlign="center" paddingTop="10">
<s:Label fontSize="19" fontWeight="bold" text="Stampiamo una sequenza di numeri!"/>
<mx:HBox verticalAlign="middle" width="100%">
<s:Label text="Inserisci un valore limite:"/>
<s:TextInput id="tiLimit"/>
<s:Button label="Stampa" click="getSequence()"/>
</mx:HBox>
<mx:DataGrid id="tableSequence" dataProvider="{sequence}">
<mx:columns>
<mx:DataGridColumn headerText="Sequenza"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
</s:Application>
In flex-src, creiamo un nuovo package chiamato services, e assicuriamoci di visualizzare la perspective Flash e che il progetto sia selezionato; nella sezione view, selezioniamo il tab Data/Services
:
Clicchiamo su Connect to Data/Service…
e si avvierà un tool automatico per la conessione ai servizi.
Nella finestra che appare, selezioniamo BlazeDS e clicchiamo Next
; alla richiesta di autenticazione rispondiamo spuntando la voce No password required
e clicchiamo su Ok
, apparirà la seguente finestra:
Spuntiamo la destinazione my_service e in Service package scriviamo services (il package creato in precedenza) e cliccando su Finish vedremo comparire il nostro servizio. Inoltre nel package services di flex-src verranno generate due classi denominate MyService.as e _Super_MyService.as. In particolare quest'ultima, contiene il codice per eseguire il remoting dal lato client, e come suggerito nei commenti non dobbiamo modificare tale implementazione.
Prima di utilizzarlo nell'applicazione, possiamo anche testarlo: selezioniamo il tab Test Operation.
Notiamo che la voce Service
è gia impostata con il nome del nostro servizio, e cliccando sulla voce è possibile visualizzare l'elenco di tutti i servizi creati, in Operation troviamo l'elenco delle operazioni appartenenti al servizio selezionato.
Con questo tool possiamo simulare l'esecuzione dell'operazione selezionata e qualora questa presenta dei parametri di input, questi saranno visualizzati nella tabella composta dalle colonne Parameter
, Type
ed Enter Value
; siccome la nostra operazione riceve in ingresso un valore, possiamo fornirglielo scrivendo in Enter Value
il valore intero N
; cliccando su Test
eseguiremo l'operazione e vedremo comparire il risultato nella tabella sottostante.
Senza perderci in ulteriori dettagli, implementiamo il seguente script nel file Main.mxml
:
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.messaging.messages.RemotingMessage;
import mx.rpc.AsyncToken;
import mx.rpc.Responder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import services.MyService;
private var service:MyService = new MyService();
private var responder:mx.rpc.Responder = new mx.rpc.Responder(onResult, onFault);
[Bindable] private var sequence:ArrayCollection;
[Bindable] private var limit:int;
private function getSequence():void{
limit = int(tiLimit.text) as int;
var at:AsyncToken = service.getSequence(limit);
at.addResponder(responder);
}
private function onResult(evt:ResultEvent):void{
switch ( (evt.token.message as RemotingMessage).operation ){
case "getSequence":
if (evt.result != null){
sequence = evt.result as ArrayCollection;
}
}
}
private function onFault(evt:FaultEvent):void{
Alert.show("Failure remoting method call");
}
]]>
</fx:Script>
Dopo la serie di import, notiamo l'istanziamento della classe MyService
e di un oggetto Responder
. Tale oggetto implementa l'interfaccia IResponder
e implementa il codice per effettuare le chiamate ai metodi remoti (quelli appartenenti alle classi Java che costituiscono i nostri servizi).
I parametri del costruttore dell'oggetto sono due funzioni onResult e onFault che implementano rispettivamente il codice da eseguire in caso di fornitura di un risultato da parte del metodo remoto e il codice da eseguire in caso di fallimento della chiamata al metodo remoto.
Il codice del metodo getSequence
prevede:
- il recupero del valore N inserito nella text input;
- dichiarazione di un oggetto AsyncToken a cui assegnare il valore della funzione getSequence(limit) dell'oggetto service che effettua la chiamata remota. La classe
AsyncToken
permette di impostare i dati supplementari per le RPC asincrone e di associare alla RPC il responder creato.
A questo punto, non ci resta che mandare in esecuzione l'applicazione.
Conclusioni
In un mix di teoria e pratica, abbiamo visto passo-passo come avviare il progetto di un'applicazione enterprice costituita da un lato server sviluppato in Java e dal lato client in Flex che comunicano tra loro attraverso un meccanismo noto come Remoting Procedure Call implementato dall'applicazione BlazeDS (versione open-source di Adobe dell'applicazione LiveCycle).
L'idea era anche quella di trasmettere l'importanza di avere un ambiente di lavoro ben configurato e gli strumenti giusti che semplificano il lavoro di sviluppo di applicazioni di questo tipo: creazione ed evoluzione di un progetto il tutto integrato e controllato all'interno di un unico ambiente di sviluppo.