In questa sezione sono riportate le domande più frequenti emerse durante l' utilizzo di guigen relative alla implementazione della business logic, intesa sia come scrittura dei metodi java associati agli ExecCommand sia alla modellazione di catene di comandi.
Q: quali sono i punti in cui posso inserire logica applicativa, intesa sia come comandi modellati, sia come logica custom scritta nel linguaggio target di programmazione (java)?
A: Guigen adotta il pattern command per la modellazione della logica applicativa. I punti in cui è possibile inserire i comandi che la realizzano sono:
E' importante notare che nel caso dei ContentPanel che contengono sia logica associata ad eventi di user interaction (EventHandler) sia logica da eseguire al refresh della schermata (ContentPanel.onRefreshCommand) viene eseguita prima la logica di onRefresh e successivamente la logica associata all'evento di user interaction. Se inoltre l'esito finale della catena di comandi modellata sull'EventHandler è il salto ad una differente schermata, al termine viene anche eseguita la logica di onRefresh sul ContentPanel di destinazione.
Q: Ho visto che è possibile strutturare la logica applicativa componendo catene di comandi. Sono possibili tutte le combinazioni? E' possibile utilizzare qualsiasi comando in qualsiasi dei punti possibili di attivazione (eventi, refresh,inizializzazione)?
A: I vincoli di composizione delle catene di comandi sono descritti in parte dalle caratteristiche strutturali dei comandi stessi, e in parte dipendono da ulteriori vincoli semantici (talvolta dipendenti dal contesto in cui i comandi sono utilizzati).
Di seguito un breve riassunto delle caratteristiche di componibilità dei vari comandi
Permette di eseguire un metodo di business logic. Non ha particolari vincoli di collocazione.
Permette di eseguire in sequenza una serie di comandi. Ha un unico vincolo semantico: se la sequenza contiene come figli di primo livello uno tra JumpCommand, JumpExtCommand, ShowDialogCommand, NOPCommand, RefreshViewCommand , questo deve comparire come ultimo step della sequenza.
Permette di saltare ad una differente schermata. Se inserito in un SequenceCommand deve essere l'ultimo step. Inoltre non può essere modellato in corrispondenza dell'evento implicito di onRefresh di una schermata.
Permette di saltare ad un URL specifico. Se inserito in un SequenceCommand deve essere l'ultimo step. Inoltre non può essere modellato in corrispondenza dell'evento implicito di onRefresh di una schermata.
Permette di visualizzare un DialogPanel. Se inserito in un SequenceCommand deve essere l'ultimo step. Inoltre non può essere modellato in corrispondenza dell'evento implicito di onRefresh di una schermata nè come comando di inizializzazione dell'applicazione (onInitCommand). In pratica, poichè il DialogPanel è di fatto un sotto-pannello di uno specifico ContnetPanel, il comando di apertura di quel dialog può solo essere modellato a fronte di un EventHandler associato ad un widget contenuto nello stesso ContentPanel che contiene il DialogPanel.
E'un comando ad azione nulla, serve solo per terminare correttamente la struttura delle catene di comandi. Se inserito in un SequenceCommand deve essere l'ultimo step.
Permette di effettuare il refresh selettivo della schermata. Se inserito in un SequenceCommand deve essere l'ultimo step. Inoltre non può essere modellato in corrispondenza dell'evento implicito di onRefresh di una schermata nè come comando da eseguire all'inizializzazione dell'applicazione.
Agiscono sulla visibilità/editabilità di uno o più widget e\o menu. Ha senso solo all'interno di un ContentPanel e possono operare solo sui Widget di quel ContentPanel.
Attiva uno tra gli ScreenState di un ContentPanel. Ha senso solo all'interno di un ContentPanel e può attivare solo uno degli stati previsti per quel ContentPanel.
Permette di attivare uno specifico tab/step/item di un tabset/wizard/multipanel. Ha senso solo all'interno di un ContentPanel e può operare solo sui multiPanel (o sottoclassi) contenuti in quel ContentPanel.
Permette di cancellare il valore di un ApplicationData. Non ha particolari vincoli di collocazione.
Demarca l'inizio/fine di una sessione di editing su un certo insieme di ApplicationData, permettendo la gestione di backup del valore iniziale, ripristino del valore iniziale, verifica di avvenute modifiche rispetto al valore iniziale. Non ha particolari vincoli di collocazione.
Permette di verificare se, in una sessione di editing, sono state effettuate delle modifiche sui dati monitorati nella sessione. Non ha particolari vincoli di collocazione.
Q: Ho la necessità di eseguire la stessa logica applicativa a fronte di due eventi distinti su uno stesso ContentPanel. E' possibile modellare un solo ExecCommand e referenziarlo nel due punti, in modo da evitare la scrittura dello stesso codice custom java due volte?
A: No, non è possibile: gli ExecCommand devono essere distinti e genereranno due distinti metodi java nel bean spring di back-end.
E' però possibile evitare di scrivere due volte tutta la logica di business creando (nell'apposita regione protetta) un metodo che conterrà la logica vera e propria, in modo tale che nei due metodi associati ai due ExecCommand sia necessario solo effettuare il richiamo di questo metodo comune.
Q: Ho modellato un ExecCommand che ha il compito di valorizzare uno specifico ApplicationData (che non è referenziato da nessun widget della schermata). Nell'oggetto di model in input al metodo generato non è però presente nessun metodo per accedere a tale application data e non riesco pertanto a valorizzarlo. Come mai?
A: Per rendere disponibile un ApplicationData alla business logic è necessario aggiungerlo all'elenco appData dell'oggetto ContentPanel.
Q: Ho modellato un ExecCommand, ho effetutato la generazione del codice... e ora?
A: Per ogni ExecCommand viene generato un metodo nello strato business logic dove è necessario inserire la logica che si vuol far eseguire al programma.
Il metodo corrispondente ad un ExecCommand viene generato in una classe java che viene registrata nel contesto spring. A seconda del punto in cui è modellato l'ExecCommand è differente la collocazione della classe:
BackEndFacadeCPBE<nome del content panel>La logica di business scritta nel metodo associato ad un ExecCommand può utilizzare:
getAppdataXXXX()
contenuti nel parametro theModel. Esempio:
...
String nome = theModel.getAppdataFiltroricerca().getNome();
...
getwidg_XXXX() contenuti nel parametro
theModel. Esempio:
...
String nome = theModel.getWidg_tfNome();
...
theModel. Esempio:
...
InputStream report = theModel.getSession().get("report_generato");
...
In presenza di alcune condizioni particolari, inoltre, sono a disposizione altre informazioni/operazioni:
...
String idRigaCliccata = theModel.getIdRiga();
Stirng idColonnaCliccata = theModel.getIdColonna();
...
resetClearStatus_widg_<nome_tabella>
che serve per resettare lo stato di paginazione della tabella specificata.
Esempio:
...
resetClearStatus_widg_myTable(themodel.getSession());
...
...
if (theModel.getSelectedTabValue().equals(TAB_MYTABSET_TAB1)){
// e' stato selezionato il tab 'tab1' del tabset 'mytabset'
...
}
...
getCurrentTab che permette di sapere qual'è il
tab (step/item) corrente all'interno di un tabset (wizard/multi). Nel bean spring
sono disponibili alcune costanti associate al singolo tab e al singolo contenitore
di tab. Esempio:
...
String currTabInMyTabset = getCurrentTab(theModel.getSession(), TABSET_MTABSET);
if (currTabInMyTabset.equals(TAB_MYTABSET_TAB1)){
...
// il tab corrente nel tabset 'mytabset' è 'tab1'
}
...
Affinchè il codice scritto manualmente sia preservato da rigenerazioni successive è necessario inserire il codice nelle apposite regioni protette.
Una regione protetta è delimitata da commenti speciali ed è identificata da un ID univoco all'interno dell'intera codeline. Esempio:
...
/*PROTECTED REGION ID(R-1222617025) ENABLED START*/
// inserire qui la logica applicativa da eseguire:
...
/*PROTECTED REGION END*/
...
Alcune best practices sulla scrittura della logtica di business:
applicationContext.xml i bean di cui sopra