## Guigen - Design rationale

In questo capitolo sono descritte le scelte di design che sono alla base del codice generato da guigen, con le principali cartucce di generazione, ovvero:

- applicazione web struts2 + spring
- applicazione web struts2 + spring con funzionalità ricche
- applicazione web con strato client fat

### Architettura target

E' importante notare in via preliminare che le tre cartucce corrispondono a tre differenti architetture applicative che godono di alcune importanti proprietà:

1. l'architettura delle applicazioni generate con la cartuccia struts2+spring è considerata l'architettura base e risponde alle specifiche del framework di sviluppo CSI
2. l'architettura delle applicazioni generate con la cartuccia web spring+struts2 con l'abilitazione delle funzionalità ricche è un'estensione dell'architettura base
3. l'architettura delle applicazioni generate con la cartuccia web con fat client è a sua volta un'estensione dell'architettura del punto precedente

Questa importante proprietà fa si che sia possibile fa convivere le tre tipologie architetturali nella stessa applicazione in esecuzione. Per questo motivo in questo capitolo verranno descritte le tre tipologie architetturali (e le conseguenti scelte di design) in modo incrementale, a partire dall'architettura base. Le tre tipologie architetturali saranno di seguito denominate come segue:

1. base webapp
2. enriched webapp
3. fat webapp

#### base webapp

E' l'architettura base, quella che viene generata se si utilizza la cartuccia struts2 senza l'abilitazione delle funzionalità ricche. Si tratta di una classica applicazione web realizzata in tecnologia J2EE (compatibile con i runtime WLS 9.2 e JBoss 4.3, JBoss 6.0, JBoss 6.2). I framework utilizzati sopra lo strato J2EE per la realizzazione del core dell'applicazione sono:

- struts2 per la realizzazione dello strato Model-View-Controller (in particolare lo strato di View è utilizzata la tecnologia JSP
- spring per la realizzazione dello strato di business logic (non è previsto uno strato EJB)

L'applicazione può interagire con sistemi esterni tramite accesso a servizi. Inoltre, a seconda della modalità di autenticazione/accesso modellate, l'architettura sarà completata con l'integrazione opportuna con i sistemi di SSO/security.

Per l'implementazione dello strato di accesso ai dati è possibile utilizzare datagen, che si innesta nell'architettura complessiva nello strato spring. In alternativa è possibile utilizzare un backend SOA.

##### Scelte di design specifiche

###### mapping ContentPanel

Ad ogni ContentPanel corrispondono i seguenti elementi del design target:

- una pagina JSP che realizza lo strato di View, ed è composta di tag HTML o JSP combinati a seconda del portale target
- una struts action che ha la responsabilità di:
  - recepire e gestire tutti e soli gli eventi di U.I destinati alla pagina in questione: per fare ciò tali action possiedono un metodo pubblico per ciascun EventHandler modellato nel ContentPanel in questione
  - eseguire la logica applicativa associata all'evento implicito di refresh della pagina, che viene scatenato:
    - al momento della visualizzazione della pagina
    - prima dell'esecuzione della logica associata ai vari eventi di U.I
    Per tale motivo questa logica è scatenata nel metodo prepare della action.
  - fornire allo strato JSP eventuali informazioni riguardanti lo stato della schermata (principalmente abilitazione/disabilitazione, visibilità/invisibilità dei vari widget a fronte dello stato applicativo e/o dei constraint di sicurezza): a questo scopo la action mette a disposizione alcuni metodi pubblici:
    - isWidgetEnabled
    - isWidgetVisible
- uno spring bean che espone allo strato struts un metodo di business per ogni ExecCommand contenuto nella schermata (N.B. questo è l'unico punto in cui è necessario inserire codice manualmente)

Questa scelta di mapping tra il concetto di ContentPanel e gli elementi dei framework utilizzati si discosta alquanto dalle modalità più frequentemente utilizzate con il framework struts (che tipicamente non prevedono questa "monoliticità" sistematica relativamente alla schermata ma una serie più liberamente composta di coppie action->view destinazione) e si ispira in modo più netto a meccanismi tipici del mondo dei fat-client. La scelta dipende principalmente da una migliore gestibilità della generazione del codice e dalla maggior facilità di riutilizzare questo modello nelle architetture estese (entriched e fat-client).

A fronte di questa scelta il flusso di navigazione tra schermate è realizzato sempre tramite il meccansimo di chaining delle action di struts: in pratica, supponendo:

- che lo stato dell'applicazione sia tale che la schermata corrente sia S1
- che esista un evento di U.I associato ad un widget di S1 (es. "CLICKED" su un pulsante B1 il cui effetto finale sia quello di passare alla schermata S2

allo scatenarsi dell'evento di U.I. viene invocato il metodo handler (`handle_B1_CLICKED()`) sulla action associata alla schermata S1, e questo comporta:

1. l'invocazione del metodo `prepare()` della action associata alla schermata S1, ovvero l'esecuzione della logica associata all'evento implicito di refresh della schermata S1 (viene eseguito il "programma" di comandi modellato come onRefreshCommand)
2. l'invocazione della logica associata all'EventHandler relativo all'evento scatenato (viene eseguito il "programma" di comandi associati all'EventHandler
3. viene restituito un result di tipo chain che punta alla action associata alla schermata S2 (metodo `execute()`) il che comporta:
   - l'esecuzione della logica di "onRefresh" associata alla schermata S2 (viene eseguito il metodo `prepare()`) della action associata alla schermata S2)
   - il rendering della view relativa alla schermata S2

###### command engine

La logica di business è modellata secondo il pattern command, nei vari punti in cui questo è previsto (inizializzazione dell'applicazione, refresh della schermata, event handler, ingresso o inizializzaizone di una schermata, ...). A livello di codice generato il pattern command è implementato come segue:

- vengono messe a disposizione una serie di classi di implementazione dei vari comandi (es. ExecCommand, JumpCommnad, VisibilityCommand, ...) ciascuna delle quali estende un'interfaccia comune che ha un unico metodo `String doCommand()`;
- ciascun tipo di comando avrà un insieme di parametri di configurazione specifici del tipo di comando (es. JumpCommand -> nome della schermata a cui "saltare")
- alcuni tipi di comando avranno la possibilità di passare il controllo dell' esecuzione ad uno o più comandi successivi (es. SequenceCommand, ExecCommand) e questo permette di implementare i flussi di operazioni
- i comandi specifici vengono istanziati in catene coerenti a quanto modellato
- l'esecuzione parte dall'invocazione del metodo `doCommand()` del primo comando della catena, che comporterà:
  - l'esecuzione della logica specifica del comando
  - il passaggio (con chiamata ricorsiva sempre al metodo `doCommand()`) ad un eventuale comando successore (se previsto dalla tipologia di comando e dalla logica di controllo)
  - la restituzione allo strato chiamante del codice di esito che rappresenta il result di struts e che stabilisce quale debba essere la successiva pagina

Le catene di comandi sono serializzate in file json che vengono caricati al momento dell' esecuzione della stessa.

###### stato applicativo

Lo stato di un'applicazione guigen è definito dalla valorizzazioen dell'insieme degli ApplicationData accessibili ad un certo istante in una certa schermata, ovvero:

- gli ApplicationData di tipo USER_REQUEST, la cui valorizzazione è disponibile a partire dall'evento di U.I fino al termine del successivo rendering di schermata: i dati di questa tipologia sono mantenuti direttamente nello stato della action di struts
- gli ApplicationData di tipo SESSION, la cui valorizzazione è disponibile per tutta la durata della sessione applicativa: i dati di questa tipologia sono mantenuti in sessione e i metodi get/set della action puntano alla sessione
- gli ApplicationData di tipo PAGE, la cui valorizzazione è disponibile fino a che il flusso applicativo non passa ad una schermata differente: i dati di questa tipologia sono mantenuti in sessione e i metodi get/set della action puntano alla sessione

###### visibilità/abilitazione dei widget

Lo stato di visibilità o abilitazione dei singoli widget è un'informazione necessaria allo strato JSP per decidere che tipo di rendering utilizzare per essi. Tale informazione è messa a disposizione della JSP da un apposita coppia di metodi disponibili su tutte le action associate ai vari ContentPanel:

- `isWidgetEnabled(<id del widget>)`
- `isWidgetVisible(<id del widget>)`

La logica secondo la quale questi metodi forniscono l'informazione relativa al singolo widget tiene conto di:

- stato di default del widget
- stato corrente del widget derivante dall'eventuale applicazione di comandi che hanno come effetto quello di alterare la visibilit&agravE; o la abilitazione (ONOFFCommand, VisibilityCommand, ScreenStateCommand...)
- eventuali SecurityConstraint

###### U.I. rendering

Il rendering delle varie schermate è realizzato tramite pagine JSP. Esiste una JSP per ogni ContentPanel. Tale JSP principale può essere a sua volta strutturata mediante il meccanismo dell'inclusione in frammenti destinati a coprire particolari esigenze di rendering, quali ad esempio:

- la visualizzazine del tab selezionato in un TabSetPanel
- la visualizzazione dello step corrente in un WizardPanel
- la visualizzazione del pannello attivo in un MultiPanel

Queste tipologie di frammenti sono inclusi a runtime in base allo stato della U.I. Esistono poi altre tipologie di frammenti che sono inclusi sempre nella schermata, ovvero:

- i frammenti di header e footer
- il frammento relativo alla MenuBar (che viene incluso se nella schermata è presente un widget MenuView
- i frammenti relativi ad eventuali UserDefinedWidget o UserDefinedPanel

La composizione delle schermate (ovvero il reale contenuto finale della pagina html) dipende dal portale target. Attualmente esistono due grossi filoni:

1. portali aderenti alle specifiche dell' XHTML universale, che è un insieme di pattern/snippet/template di codice XHTML progettati appositamente per l'utilizzo in MDD, neutri rispetto alla grafica effettiva che dovrà essere ottenuta e, per questo motivo, graficabile mediante appositi skin CSS
2. portali non aderenti alle specifiche dell XHTML universale per i quali è prevista una struttura HTML specifica (modalità deprecata e per la quale è previsto un piano di dismissione)

Relativamente alla modalitè "neutral", esistono poi due possibilitè di referenziazione delle risorse grafiche (immagini, css):

1. inclusione delle risorse nell'applicazione: le risorse sono contenute nel pacchetto e servite dall'application server
2. installazione delle risorse nel web server: le risorse sono installate nel virtualhost del web server e sono servite dal web server stesso

La scelta dell'una o dell'altra modalità dipende da diversi fattori (portale di esposizione, opportunità specifiche) e non comporta differenze nella modellazione dell'applicazione.

#### enriched webapp

E' un'estensione dell'architettura base destinata ad assolvere a alcuni requisiti funzionali aggiuntivi, tipicamente descritti nel catalogo dei widget come modalità ricca, e sintetizzabili come segue:

- enhancement di vario genere a livello client dei vari widget (es. tooltip, tabelle personalizzabili, ...)
- funzionalità dinamiche (es. refresh parziale, eventi di selezione, suggestion, ...)

Per l'implementazione di tali funzionalità aggiuntive viene usato pesantemente codice Javascript che gira nel browser dell'utente: solo in questo modo infatti à possibile eseguire le logiche client-side necessarie. Al fine di garantire l'utilizzabilità dell'applicazione anche a chi non dovesse utilizzare un browser compatibile con tale linguaggio è previsto un meccanismo di downgrade funzionale automatico che, in pratica, permette di utilizzare l'applicazione nella modalità prevista dall'architettura base. Tale meccanismo di basa sul rilevamento client-side della disponibilità del linguaggio javascript e la differenziazione server side del rendering a seconda che tale rilevamento abbia fornito un esito positivo o negativo. Il risultato ottenuto è che l'utente riuscirà comunque a svolgere le funzionalit� principali rinunciando però necessariamente alle sotto-funzionalità ausiliarie.

##### Scelte di design specifiche

Le scelte di design di questo tipo di architettura sono additive rispetto a quelle dell' architettura base.

###### arricchimento della U.I

L'implementazione delle funzionalità "ricche" dal lato client è realizzata con un meccanismo denominato arricchimento della U.I, che è il seguente: si parte dalla struttura di U.I prevista dall'architettura base e, per i widget ove questo sia previsto, viene messo in opera una modifica client-side di tale widget; questa modifica ne determina l'arricchimento ch edà il nome al meccanismo. Alcuni esempi di arricchimento:

- aggiunta di tooltip a comparsa sulle label dei widget (si applica alle label dei widget esistenti)
- aggiunta delle funzionalità di personalizzazione del layout di una tabella (si applica ad una Table HTML esistente)
- aggiunta della logica per l'innesco 8in modalità AJAX) del metodo server side associato all'evento di selezione (VALUE_CHANGED) di una ComboBox
- aggiunta di un date picker per l'implementazione completa del widget Calendar (nella modalità base il calendar è un semplice TextField)

Affinchè l'effetto di arricchimento delle singole porzioni di schermata sia quello desiderato questo deve essere applicato nei momenti corretti e il nomero di volte corrette. Al fine di garantire questo corretto comportamento gli arricchimenti relativi ad un singolo ContentPanel sono registrati (con indicazione del frammento "affetto"). Il registro così ottenuto può essere perciò utilizzato per applicare selettivamente gli arricchimenti:

- al caricamento della schermata o ad un refresh totale della schermata vengono applicati tutti gli arricchimenti
- al refresh di una particolare porzione di schermata vengono applicati solo gli arricchimenti associati a quel range di schermata

###### metodi "data provider"

Rispetto alla architettura base la modalità enriched webapp prevede la creazione di una serie di metodi denominati di data provider:

- ne viene generato uno per ogni MultiDataWidget (ComboBox, Table, Textfield utilizzato in modalità suggestion)
- il nome del metodo è `provide_<nome_widget>_DATASET()`
- il result struts restituito dai metodi è sempre "provideData", che corrisponde ad un result globale di tipo stream che restituisce al client il contenuto dell'InputStream contenuto nell'attributo `dataProviderStream`
- il contenuto della collection che rappresenta la fonte dati viene serializzato in formato JSon

Questi metodi data provider sono utilizzati pesantemente nella modalità fat client. La scelta di farli generare già nell'architettura enriched webapp è stata effettuata per permettere eventuali implementazioni custom. Sono invece direttamente utilizzati nell'implementazione della funzionalità di suggestion del TextField: al termine dell'esecuzione della logica necessaria per effettuare l'estrazione dei dati da restituire all'utente come suggestion, invece di restituire direttamente il codice del result, il metodo handler delega l'esecuzione al metodo data provider del widget, il quale provvede a restituire allo strato client l'elenco dei suggerimenti in formato JSon.

###### metodo per suggestion

L'implementazione del metodo handler relativo alla funzionalità di suggestion su TextField (ovvero quella relativa all'evento KEY_PRESSED associato al campo di testo) differisce leggermente rispetto alla modalità normale: al termine dell'esecuzione della catena di comandi, infatti, il controllo viene passato al metodo data provider che provvede a fornire al widget client side l'elenco delle suggestion in formato JSon

#### fat webapp

E' un'estensione dell'architettura enriched webapp che permette una implementazione alternativa dello strato di U.I, che sposta sul client una gran parte della logica di rendering; proprio per questo si parla di architettura fat webapp. Di fatto lo strato di View+Controller si sposta totalmente sul client e si trasforma in uno strato costituito da componenti di user interface che interagiscono con il lato server (business logic + front-controller) principalmente in modalità AJAX. Tale strato server, di fatto, non fornisce più in risposta al client un rendering preconfezionato (html) ma fornisce informazioni (dati applicativi e non) destinate a popolare i widget che compongono la schermata.

E'importante notare come questa tipologia architetturale possa essere implementata con differenti tecnologie client di componentizzazione di interfaccia: l'unico vincolo è che le tecnologie candidate siano in grado di implementare le (semplici) specifiche di interazione con lo strato server. Allo stato attuale la tecnologia client utilizzata è basata sulle librerie ExtJS (linguaggio javascript), ma sarebbe ugualmente possibile, ad esempio, ottenere una implementazione basata su Adobe Flex o java swing, ...

##### Scelte di design specifiche

Le scelte di design specifiche di questa architettura sono additive rispetto alla architettura enriched webapp.

###### mapping content panel

Rispetto all'architettura base i cambiamenti sono pochi e additivi. Viene mantenuta l' associazione tra ciascun ContentPanel la action di struts corrispondente, mentre lo strato di pura view viene implementato con un unico modulo JS che contiene tutta la struttura dell'applicazione.

###### ripartizione della logica di esecuzione dei comandi tra client e server

Rispetto all'architettura base nella modalità fat-client vi è una differente ripartizione sui vari tier architetturali della responsabilità di esecuzion delle catene di comandi. Infatti, mentre nell'architettura base la responsabilità completa dell'esecuzione dei comandi è affidata allo strato server (struts + spring), nella modalità fat si verifica una differente ripartizione delle responsabilità, guidata da alcuni criteri precisi:

- la business logic funzionante nella modalità base deve essere totalmente riusabile senza nessun intervento anche nella modalità fat
- non deve essere necessario per l'utilizzatore scrivere manualmente codice javascript
- l'unico codice scritto manualmente deve conrinuare ad essere quello che realizza la business logic e deve essere scritto in java (strato spring)
- per l'esecuzone di quei comandi che agiscono solo a livello di user interface (es. accensione/spegnimento di widget) deve essere evitato il più possibile l'accesso alla componente server
- i comandi che realizzano logica applicativa possono essere realizzati mediante un "salto" server side

A fronte di questi criteri, dunque, l'esecuzione di ciascuna catena di comandi avviene principalmente lato client, ad eccezione del comando ExecCommand per cui è prevista una interazione con lo strato server in modo che questo possa invocare il metodo di business corrispondente (N.B: lo stesso utilizzato nell'architettura base). Lo scambio di informazioni client-server avviene anche in questo caso tramite JSon.

###### metodi exec command

Al fine di realizzare la differente ripartizione di responsabilit� nell'esecuzione dei comandi (descritta al paragrafo precedente) è necessario introdurre in ciascuna action una ulteriore serie di metodi, detti di exec command che hanno l'unico scopo di esporre allo strato di componenti client i metodi di business disponibili nello strato spring. Se, durnate l'esecuzione di una catena di comandi lato client, lo step corrente comprenderà un ExecCommand, l'esecuzione del metodo di business associato verr&agravE; delegata allo strato server, che restituirà successivamente le informazioni necessarie per aggiornare i widget (con i dati modificati per effetto dell'esecuzione della business logic).

###### metodi di data provider

In questa architettura sono utilizzati pesantemente i metodi cosiddetti di data provider introdotti già nell'architettura arricchita per tutti i widget che sono associati ad una collezione/fonte dati. Esempi:

- la Table riceve i dati da visualizzare dal corrispondente metodo di data provider (per questo tipo di widget tale metodo ha anche il compito di gestire in modo del tutto automatico filtri e ordinamenti)
- la ComboBox riceve l'elenco delle opzioni dal corrispondente metodo di data provider

Il client ha inoltre a disposizione una nuova tipologia di metodo di data provider, associato all'intero ContentPanel: il metodo `provide_CPDATA()` ha infatti il compito di restituire allo strato client il contenuto degli ApplicationData da utilizzare per popolare i valori dei vari widget coerentemente con lo stato applicativo. Sono esclusi i dati di tipo collection che sono invece forniti dagli specifici metodi di data provider. La combinazione di queste due tipologie di metodi di fornitura dati permette di mantenere lo stato dell'applicazione sul server e trasferire sul client solo le informazioni necessarie.

###### flusso tra le schermate

Il flusso tra due schermate differenti è realizzato caricando i componenti JS relativi alla schermata target, come effetto dei comandi di navigazione (JumpCommand).