MokaByte Numero 46  - Novembre 2000
Lotus Domino e Java
Le form 
III parte
di 
Matteo Baccan
Viaggio nel mondo di Lotus Notes e 
dell'interfacciamento con Java

In questa puntata concluderemo la parte relativa al trattamento delle form, analizzeremo il condizionamento della fase di salvataggio dati e vedremo come è possibile mandare una semplice e-mail, utilizzando le sole classi Notes di creazione di documenti. 

A questo punto dovrebbe essere chiaro a tutti come si compone una form Notes, com’è possibile porre dei valori di default e com’è possibile aggiungere, alla fase di salvataggio, una schermata di conferma dei dati inseriti.
Gli argomenti che tratteremo in questa puntata saranno relativi alla fase di controllo dei dati inseriti.
Vedremo come è possibile rimandare l’utente alla maschera di inserimento dati, in caso d'errore, inoltre scopriremo come può convivere del codice Java, JavaScript e LotusScript all’interno della stessa maschera. Infine tramite una semplice form, spediremo un messaggio di posta elettronica.
 
 
 

Campi speciali
L'esempio che prenderemo in considerazione è presente nel file allegato a questa puntata, e si basa su una form Notes contenente, al suo interno, i seguenti campi Nome, Cognome, Citta, Indirizzo e email.
In questa form è anche presente un SaveAgent, inserito tramite la proprietà WebQuerySave, utilizzando la seguente riga di LotusScript:

@Command([ToolsRunMacro]; "testQuerySaveAgent3")

Tale script serve ad indicare che, al salvataggio della maschera, deve essere chiamato l’agente di nome testQuerySaveAgent3.
Quello che abbiamo ottenuto è un oggetto, utilizzabile tramite un normale browser, ma non ancora condizionabile nella fase di salvataggio dati. Non esiste infatti nessuna direttiva in grado di evitare che quello che viene scritto venga salvato su disco.
Vediamo allora come evitare questo salvataggio automatico.
All'interno di Notes, come abbiamo già visto, esistono una serie di campi definiti speciali. Tali campi hanno la caratteristica di poter condizionare il normale comportamento del programma.
Per questa particolare casistica è stato creato il campo SaveOptions, che, se creato di tipo computed ed impostato a “0”, evita che il dato inserito lato Internet venga salvato all'interno del database Notes.
In questo modo sarà possibile, da parte di un agente WebQuerySave, decidere se salvare i dati oppure no.
 
 
 

Controlliamo i dati inseriti
Iniziamo ora a scrivere i controlli per poter verificare che, nei campi che abbiamo inserito nella maschera di richiesta dati, siano effettivamente contenuti dei valori corretti.
Come abbiamo gia osservato in una precedente puntata del corso, all’interno di un agente è possibile accedere ai valori dei campi di una form, semplicemente utilizzando il metodo getDocumentContext:

Document doc = agentContext.getDocumentContext();

In questo modo, tramite il metodo getItemValueString, è possibile prendere il valore di un campo e controllare se contiene i giusti valori. Nel nostro caso l’obiettivo è quello di verificare se i campi Nome, Cognome e email contengono un valore valido. Per fare questo occorrerà quindi scrivere del codice simile a questo:

String cNome = doc.getItemValueString("Nome");
String cCognome = doc.getItemValueString("Cognome");
String cEmail = doc.getItemValueString("email");

String cErr = "";
if( cNome==null || cNome.trim().length()==0)
   cErr = "Il campo Nome non puo' essere vuoto";
else if( cCognome==null || cCognome.trim().length()==0)
   cErr = "Il campo Cognome non puo' essere vuoto";
else if( cEmail==null || cEmail.trim().length()==0)
   cErr = "Il campo Email non puo' essere vuoto";

if( cErr.length()>0 )
   getAgentOutput().println( cErr );
else {
   doc.replaceItemValue("SaveOptions","1");
}

In questo esempio è stato interrogato il documento corrente e sono stati presi i valori Nome, Cognome e email, con il metodo getItemValueString. Inoltre è stato controllato che nel campo ci fosse presente un valore e che tale valore fosse almeno di un carattere.
Il particolare interessante di questo codice è però dato dal controllo finale, dove viene verificato il valore di cErr che è la variabile che contiene l’eventuale errore rilevato durante la fase di controllo dei dati.
Se cErr contiene un valore viene utilizzato il metodo getAgentOutput, presente nella classe base dell’agente corrente, per accedere allo stream di stampa e visualizzare un dato lato browser.
Nel caso che invece sia stato tutto inserito nel modo corretto, ci si limita a cambiare il valore del campo SaveOptions, passandolo da 0, che era il valore al quale lo avevamo impostato, ad 1 che abilita il salvataggio delle informazioni inserite.
Questa pratica è molto semplice e ci permette di includere tutti i controlli di una maschera alla fine, dopo che l’utente ha inserito i dati. Inoltre ci permette di controllare tutto lato server. In alternativa esistono almeno due modi diversi di validare i dati.
Tali modi sono dati dall’uso di JavaScript e dall’uso di LotusScript server side.
Nel caso di JavaScript non abbiamo però la certezza matematica della corretta digitazione dei campi, infatti se l’utente che utilizza tale maschera salvasse su disco la form HTML e ne cambiasse o togliesse i controlli inseriti, impostando il POST sul server Notes, potrebbe tranquillamente inserire dei dati in maniera scorretta.
Nel caso dell’uso di LotusScript la cosa invece cambia, in quanto il codice è eseguito lato server, e quindi è impossibile, da parte dell’utente remoto, poter fare qualsiasi tipo di manipolazione al codice che controlla la maschera.
 
 

Figura 1: esempio di form avanzata
(clicca per un ingrandimento)

Sopra a tutto questo è comunque sempre possibile utilizzare un WebQuerySave che, oltre a garantire il fatto di essere eseguito lato server, e quindi in modo non intercettabile, ci permette una migliore gestione dei controlli, potendo accedere contemporaneamente a tutti i valori dei campi, più ad una serie di caratteristiche non intercettabili lato LotusScript o JavaScript.
Vediamo comunque come utilizzare queste tecniche complementari, per poter effettuare dei controlli alternativi a WebQuerySave.
 
 
 

Un po’ di JavaScript
In primo metodo che andremo ad analizzare è dato dall’utilizzo di un normale codice JavaScript. All’interno del Domino Designer è possibile gestire, oltre i normali eventi Notes, anche gli eventi JavaScript che verranno poi scaricati sulla form HTML che Domino andrà a creare.
Il primo evento che andremo ad utilizzare sarà onBlur. Tale evento appartiene ad ogni singolo campo inserito nella form ed è invocato all’uscita dal campo stesso. È facile intuire che, se in tale evento andassimo a porre del codice di controllo, tale codice sarebbe eseguito non appena, tramite TAB o tramite il click del mouse, andassimo a comandare il passaggio al control successivo.
Ipotizzando di avere un campo dal nome email e volendo controllare che non fosse vuoto, potremmo semplicemente valorizzare l’evento onBlur del campo email col seguente codice JavaScript:

if( email.value.length==0 ) 
alert( 'il campo email non puo\' essere vuoto' );

Come si può notare, il codice così scritto è del normale JavaScript, che viene scaricato all’interno della definizione HTML del control:

<INPUT NAME="email" VALUE="" onBlur="if( email.value.length==0 ) 
 alert( 'il campo email non puo\' essere vuoto' );
">

Se provate l’esecuzione di tale script all’interno del vostro browser noterete come, all’uscita di questo campo, il sistema vi proporrà a video una maschera d’errore.
Un’altra possibilità di controllo, sempre in JavaScript, è data dall’utilizzo delle evento onSubmit. Tale evento però appartiene alla form e non più al control in esso contenuta.
Inoltre, mentre l’evento onBlur non è vincolante, nel senso che, per poter essere eseguito dobbiamo necessariamente passare sul control che lo gestisce, l’evento onSubmit è vincolante, quindi sarà eseguito sempre, appena verrà chiamato il salvataggio del form.
Inoltre onSubmit ha un valore di ritorno che può essere usato per evitare il salvataggio della form. Nel caso restituisca un valore false, il browser eviterà di effettuare il post dei dati.
Ecco un piccolo esempio chiarificatore di tale concetto:

if( Indirizzo.value.length==0 ) {
 alert( 'il campo indirizzo non puo\' essere vuoto' );
 return false;
}

In questo caso viene controllato il control Indirizzo, ne viene presa la lunghezza e, se uguale a zero, viene visualizzato un messaggio d’errore e viene ritornato un valore false, in questo modo non sarà possibile salvare la form in nessun modo.
Ovviamente queste due tecniche di controllo hanno sia dei vantaggi che degli svantaggi. Il vantaggio più evidente è dato dal fatto che non viene appesantito il server con una serie di inutili controlli ed attivazioni di agenti, che comunque rappresentano un carico considerevole, nel caso si abbiano un numero molto alto di client.
 
 

Figura 2: form lato web
(clicca per un ingrandimento)

Questa tecnica ha però anche degli svantaggi, primo fra tutti il fatto che, tali controlli, essendo client side, si possono facilmente rimuovere. Inoltre, nel caso che il browser non gestisca JavaScript o che l’utente abbia volutamente disabilitato la sua esecuzione, i controlli non verrebbero minimamente eseguiti, vanificando ogni tipo di elaborazione.
Personalmente credo che sia interessante utilizzare un po’ di script client side, dato che, in molti casi, evita la scrittura di agenti inutili lato server, ed alleggerisce abbastanza il carico di rete in caso di architetture pesanti.
 
 

Figura 3: conferma della form lato web
(clicca per un ingrandimento)

 
 

Un po’ di LotusScript
Un altro modo, completamente diverso di controllare un campo è dato dall’utilizzo di LotusScript e più esattamente dell’evento InputValidation. Tale evento ha la particolarità di essere eseguito lato server, quindi in modo non aggirabile, e di poter essere scritto in un linguaggio nativo Notes, quindi estremamente portabile. Se volessimo, ad esempio, controllare la presenza del carattere @ all'interno del campo email, dato che è un carattere obbligatorio nel caso della posta elettronica, potremmo inserire del codice molto simile a questo:

@If(@Contains( email ; "@" ); @Success; @Failure("Email scorretta"))

Se nel campo email è contenuto il valore @, viene ritornato un valore positivo @Success, altrimenti viene riportato un valore negativo @Failure.

Un po’ di riepilogo
Vediamo ora di ricapitolare le operazioni che vengono fatte da Notes per validare una form di inserimento dati:

  • Prima di tutto vengono sentiti gli eventi JavaScript, essendo eseguiti client side. Quindi gli eventi onBlur dei singoli control e, all'atto del salvataggio, onSubmit. Tali eventi sono gestiti direttamente dal browser e non contattano in nessun modo il server Notes.
  • Successivamente, se tutto è stato eseguito in modo corretto, il browser esegue un'operazione di POST, mandando i dati al server. Lato server, la prima operazione che viene fatta è quella di eseguire tutti i vari Input Validation.
  • Nel caso che tutto sia eseguito correttamente, viene poi chiamato l’agente di WebQuerySave che rappresenta l’ultimo passo prima del salvataggio vero e proprio della form all’interno del database Notes.
Come si può vedere tutti questi controlli sono complementari e possono essere fatti contemporaneamente all’interno di un form Notes.
 
 
 
 
Figura 4: l’agente di controllo
(clicca per un ingrandimento)

 
 

Creiamo una mail di conferma
Ora che abbiamo visto in dettaglio come controllare i dati inseriti in una maschera Notes, vediamo come creare un piccolo servizio aggiuntivo al nostro sito Internet.
Il servizio aggiuntivo è quello dell'invio di un messaggio di posta elettronica.
Se la versione di Notes server che state utilizzando è correttamente configurata e la posta permette di mandare dei messaggi verso la rete Internet, creare un messaggio di conferma ordine o di conferma dati inseriti o semplicemente dei messaggi di amministrazione, come potrebbero essere degli avvisi di malfunzionamento o delle statistiche, è un’operazione estremamente semplice.
La creazione di un’email in Notes si basa sulla creazione di un documento di tipo Memo. Tale documento deve poi contenere i campi Subject e Body, che rappresentano la minima implementazione di un messaggio di posta elettronica.
 

Figura 5: input validation
(clicca per un ingrandimento)

 

Ovviamente l’ultimo comando da eseguire è quello di send del documento, che avverte Notes di prendere l’oggetto appena creato e trattarlo come un messaggio di posta elettronica.
Per voler schematizzare il problema ecco di seguito le poche righe necessarie per creare questa operazione:

Document docmail = db.createDocument();
docmail.appendItemValue("Form", "Memo");
docmail.appendItemValue("Subject", "Corso Notes”);
docmail.appendItemValue("Body", "Ho provato il tuo esempio”);
docmail.send( false, “baccan@infomedia.it” );

Come si può notare la procedura è molto semplice, ed è sicuramente più veloce rispetto ad un'interfacciamento diretto con un server di posta SMTP.
 
 
 

Figura 6: esempio di onBlur
(clicca per un ingrandimento)

 
 

Conclusioni
In questa terza puntata abbiamo osservato come sia possibile controllare qualsiasi tipo di dato inserito all’interno di una maschera Notes e come sia possibile condizionare il salvataggio di un gruppo di campi in modo estremamente semplice. Dopo queste prime puntate dovremmo essere in grado di creare autonomamente delle maschere da utilizzare lato Internet, con i relativi controlli di congruenza.
Nella prossima puntata vedremo come organizzare i dati all’interno di una vista e come presentarli ad un ipotetico utente remoto, impostando una modalità di visualizzazione diversa da quella utilizzata per inserirli.
 
 
 
 

Figura 7: esempio di onSubmit
(clicca per un ingrandimento)

 
 
 

Bibliografia
[1] http://www.lotus.com sito Internet di riferimento per i prodotti Lotus
[2] http://www.notes.net sito ufficiale di Lotus Domino. Da questo sito è possibile scaricare tutti gli aggiornamenti di Domino, dalla versione 4.0 all’ultimissima versione disponibile.
[3] http://www.infomedia.it/artic/Baccan, sito contenente alcuni articoli di approfondimento degli argomenti trattati.
 
 

Riquadro :getAgentOutput()

Una piccola nota deve essere fatta a proposito di getAgentOutput().println,  in quanto Domino, in caso di presenza di righe molto lunghe, tende a spezzarle  arbitrariamente. mettendo al loro interno dei caratteri di accapo.
Anche se a prima vista tale comportamento potrebbe non essere fastidioso,  in quanto, quando l' HTML viene interpretato, vengono ignorati i caratteri di  a capo, tale prassi risulta particolarmente dannosa nel caso che la stringa  venga interrotta all'interno di un comando, perché la pagina ne rimane  danneggiata e porta il browser ad una cattiva interpretazione dei caratteri  ricevuti dal server.


Matteo Baccan è uno specialista di progettazione e sviluppo in C++, Java e Lotus Notes, nonché coautore di dBsee 4, dBsee++ ed autore di dBsee400. Attualmente si occupa dello studio di tecniche avanzate di programmazione in ambito Internet/Intranet tramite Lotus Notes e Java, presso ISA Italian Software Agency. Si possono consultare alcune sue pubblicazioni presso http://www.infomedia.it/artic/Baccan. Può essere contattato tramite e-mail all'indirizzo baccan@infomedia.it

Chi volesse mettersi in contatto con la redazione può farlo scrivendo a mokainfo@mokabyte.it