Come
abbiamo visto nella prima puntata di questo corso, costruire una maschera
di inserimento dati, utilizzabile in ambito Internet è un’operazione
molto semplice. Poter poi mischiare del design Notes con del codice HTML,
è una possibilità molto interessante e permette di superare
quelli che sono gli eventuali vincoli che, l’ambiente di disegno, ci andrebbe
a porre durante le fasi di preparazione delle singole maschere.
Il
primo aspetto che analizzeremo ora è dato dal modo con il quale,
all’interno di Notes, è possibile inserire delle classi Java, che
verranno eseguire all’ingresso e all’uscita della form.
Campi speciali
ed eventi
Per
poter effettuare questo tipo di operazione, esistono vari modi. Il primo
in assoluto, pensato dai progettisti Notes, è quello di utilizzare
un particolare tipo di campo, nel quale inserire il nome dell’agente che
deve essere eseguito in partenza o in uscita dalla form.
Tale
campo è $$QueryOpenAgent per l’agente d’ingresso nella form
e $$QuerySaveAgent per l’agente d’uscita dalla form.
Dopo
aver definito l’uno o l’altro campo, in base alle esigenze della propria
applicazione, occorre mettere, nel valore di default di tale campo il nome
dell’agente che verrà richiamato in automatico da Notes. Ad esempio
"testQueryOpenAgent"
e naturalmente,
fra la lista degli agenti disponibili, ne andrà creato uno con pari
nome.
Fate
attenzione però al fatto che l’agente sia realmente disponibile,
infatti nel caso in cui non lo fosse Notes non sarebbe in grado di comporre
la maschera e di renderla disponibile lato browser, generando un errore
di form non disponibile lato web browser e Invalid Document Identifier
a livello di console di Notes.
|
Figura
1 - Messaggio di errore nella esecuzione di un
agente
visualizzato nella finestra del server
|
Figura
2 - Messaggio di errore nella esecuzione di un
agente
visualizzato nella finestra del browser
Questo
modo di scrivere un agente, da mandare in esecuzione prima della visualizzazione
della form o al suo salvataggio, è sicuramente stato uno stratagemma
inventato nei tempi in cui si iniziava ad utilizzare Notes in ambito Internet.
Ne è prova il fatto che, all’interno dei manuali delle ultime versioni,
non si fa menzione di tale campo, fra la lista dei campi speciali.
Tale
tecnica è stata sostituita, dalla versione 4.6.x, ma in modo più
marcato dalla 5.x, con l’utilizzo di due eventi presenti all’interno della
lista degli eventi del form. Tali eventi sono: WebQueryOpen
e WebQuerySave.
Se
provate a posizionare Domino Designer su tali eventi, noterete che Notes
proporrà di default due @command:
@Command([ToolsRunMacro];
"<...>")
In
tali @command andranno inseriti il nome degli agenti da eseguire, quindi,
nel nostro caso:
@Command([ToolsRunMacro];
"testQueryOpenAgent")
Nel
database d’esempio allegato al corso, troverete due form, con al loro interno
le due diverse implementazioni di OpenAgent e SaveAgent.
Vediamo
ora come devono essere scritti gli agenti, all’interno di Lotus Notes.
|
Figura
3 - Caratteristiche dell’agente
Che tipo di agenti
possiamo scrivere
Notes
ci permette diverse modalità di scrittura, che si sono evolute col
passare del tempo.
-
Formula.
Rappresenta una semplice formula, come potrebbe essere l’apertura di una
nuova form. Nel nostro caso però tale tipo di agente risulta alquanto
difficile da utilizzare.
-
Simple
action(s). Rappresenta un’operazione più complessa, come ad esempio
l’inoltro di una mail o l’esecuzione di un altro agente.
-
LotusScript.
Questa è la modalità classica di scrittura di un agente,
prima dell’avvento di Java, cioè fino alla versione 4.5.x. Essendo
però le classi Java di Notes derivate direttamente dalla classi
di LotusScript è ragionevole affermare che tutto quello che possiamo
fare in LotusScript, possiamo rifarlo ora con un gente Java.
-
Imported
Java. È la prima modalità di utilizzo di un agente Java in
Notes. Consiste nella scrittura, con un qualsiasi programma, dell’agente
all’esterno di Notes e nell’importazione del relativo .class file all’interno
del database. Questo modo di scrivere gli agenti previene, almeno in prima
istanza, la possibilità da parte di un altro programmatore di riutilizzare
il codice che è stato utilizzato per il proprio lavoro, dato che
non vi è traccia del sorgente all’interno del database.
-
Java.
Dalla versione 5.x di Notes è possibile scrivere, direttamente all’interno
del database, l’agente in linguaggio Java. Sarà poi Notes a compilare
il sorgente e a renderlo disponibile all’applicazione. In questo modo il
database diventa autosufficiente e non occorre, come nel caso dell’Imported
Java, ricordarsi di fare un backup dei sorgenti dell’applicazione, oltre
che del file .nsf stesso.
Al fine
di comprendere meglio come poter scrivere del codice Java, che interfaccia
una form, utilizzerò la possibilità di scrivere internamente
all’agente il relativo codice Java.
Per
chi non disponesse di una versione 5.x di Notes, sarà comunque possibile
scrivere un agente esterno a Notes stesso, compilarlo, avendo cura di includere
nel CLASSPATH il file Notes.jar, presente all’interno della directory di
Notes, ed importarlo come Imported Java. Per il resto lo sviluppo rimane
identico, occorre infatti derivare dalle stesse classi e scrivere lo stesso
codice.
|
Figura
4 - Configurazione server
Scriviamo il primo
agente Java
Il
primo particolare importante da sapere, quando si scrive un agente Java,
è da quale classe si deve necessariamente derivare. Tale classe
è: AgentBase.
Se
provate ad estrarre e a decompilare le classi Notes, contenute nel file
Notes.jar, noterete che la classe AgentBase è derivata direttamente
da Thread. Notes si limita semplicemente ad implementare dei metodi aggiuntivi
che andrà poi a gestire l’Agent Manager, prima di eseguire l’agente
vero e proprio.
Un
altro particolare interessante è dato dal fatto che, ogni agente
è inserito all’interno di una propria area di memoria e non può,
per dei vincoli di sicurezza, dialogare con altri agenti. Questo tipo di
architettura è stata pensata per evitare che agenti “maliziosi”
potessero interagire con altri compromettendone l’esecuzione.
Una
volta effettuata la derivazione da AgentBase occorre poi implementare il
metodo
public
void NotesMain()
sarà
poi cura dell’Agent Manager richiamare tale metodo al momento giusto e
con i giusti oggetti pronti per poter essere interrogati ed utilizzati.
Un
altro particolare importante da sapere, prima di partire, è che,
lo stream di output System.out in realtà punta alla console di Notes.
Quindi un comando come:
System.out.println("OpenAgent");
non
farà altro che produrre una riga all’interno del log di Notes. Attenzione
però a non abusare di questo comando in quanto, la scrittura all’interno
del log, rallenta abbastanza l’esecuzione dell’agente stesso, e si può
rivelare una grave perdita di performance.
Vediamo
a questo punto un piccolo esempio che sfrutta tutti i punti descritti finora:
import
lotus.domino.*;
public
class JavaAgent extends AgentBase {
public
void NotesMain() {
System.out.println("OpenAgent");
}
}
Come
si può notare è stata inserita la direttiva import delle
classi lotus.domino.* per fare in modo che il compilatore Java potesse,
in modo corretto, ereditare dalle classi Notes l’agente corrente.
Il
nome della classe è comunque implementabile a discrezione del programmatore.
JavaAgent è semplicemente un default che Notes propone e che può
essere sostituito in qualsiasi momento.
|
Figura
5 - Abilitazione utente
È
inoltre interessante notare che, nel caso che la classe sia implementata
interamente in Notes, non occorre fare delle modifiche all’environment,
come il ritocco del CLASSPATH, in quanto la corretta impostazione viene
fatta direttamente da Notes, al momento della compilazione della classe.
Vediamo
ora come possiamo iniziare a leggere e scrivere dei valori, prima che la
form venga visualizzata.
Valori
di default
La
prima operazione che faremo ora sarà quella di dare un default ad
un campo.
Per
poter effettuare tale operazione ci serve accedere al documento corrente,
cioè a quel documento che Notes sta preparando per mandare poi al
browser, che ne gestirà l’inserimento dati.
Per
arrivare a tale documento occorre, prima di tutto, accedere alla sessione
correntemente attiva all’interno di Notes, tramite il metodo getSession()
che troviamo implementato all’interno della classe base del nostro agente.
Dalla sessione occorre poi accedere all’oggetto AgentContext che gestisce
l’agente correntemente in esecuzione e da tale oggetto possiamo poi accedere
al Document corrente, tramite il metodo getDocumentContext() della classe
AgentContext.
Una
volta che si è raggiunto il documento corrente è poi molto
semplice manipolarlo per poter fare delle personalizzazioni.
Se
volessimo, ad esempio, dare un valore di default ad un campo, contenuto
all’interno di una form, della quale l’agente corrente è il WebOpenAgent,
non dovremo fare altro che scrivere le seguenti righe:
try
{
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
Document doc = agentContext.getDocumentContext();
// Assegno il valore di default al campo cNome
doc.replaceItemValue("cNome","prova");
}
catch(Exception e) {
e.printStackTrace();
}
Le
prime tre righe sono ovvie, in quanto implementano il concetto appena spiegato,
la parte interessante è data dalla riga successiva, che assegna
al campo cNome il valore “Prova” in maniera statica, gestendo così
un default su campo.
In
realtà questo meccanismo è importante per capire come è
semplice accedere ai campi di una form prima che vengano visualizzati.
Potevamo
infatti leggere tali valori da una connessione JDBC, ed utilizzare la form
come maschera di modifica dati di un record di database.
Vediamo
ora com’è possibile gestire, con questa tecnica una visualizzazione
condizionale dei valori di una form.
|
Figura
6 - Esecuzione corretta degli agenti
Visualizzazione
condizionale
Le
form Notes hanno la caratteristica di poter avere delle parti condizionabili,
in base al valore di un campo, o di un’espressione. Sfruttiamo a nostro
vantaggio questa caratteristica, inserendo un nuovo campo, all’interno
della form, e chiamandolo abilita.
Aggiungiamo
ora due nuovi campi, su due righe differenti, e poniamo il primo campo
non visualizzato se abilita contiene il valore “S” ed il secondo non visualizzato
se il valore di abilita contiene il valore “N”.
A
questo punto, sempre dalle proprietà del campo abilita, evitiamo
che il campo venga visualizzato lato web, selezionando l’opzione Hide paragraph
from Web browsers.
A
questo punto, all’interno dell’agente proviamo ad aggiungere la seguente
riga:
doc.replaceItemValue("abilita","S");
In
questo modo forziamo un valore di default a “S” per il campo abilita. Ne
consegue che, il browser, visualizzerà solamente il secondo campo,
nascondendo il primo, in quanto il motore di composizione della form, dopo
aver eseguito il nostro agente, ha constatato la non visualizzabilità
della prima riga.
Questo
esempio, ci permette di capire come, tramite un semplice WebOpenAgent,
sia possibile dare dei default e condizionare la visualizzazione di una
form.
In
questo caso abbiamo limitato la visualizzazione ad una sola riga, se però
al posto della riga ci fosse stato un intero subform o più righe,
l’effetto non sarebbe cambiato.
|
|
Figura
7 - Valore di default
Autorizzazioni
Ultimo
particolare sul quale soffermarci, ma non il meno importante, è
dato dal tipo di autorizzazioni che si debbono avere, lato server, per
poter scrivere questo tipo di agenti.
Non
basta infatti crearli ed associarli ad una form, occorre anche autorizzare,
all’interno dell’ambiente di configurazione di Notes, l’utente che ha salvato
l’agente all’esecuzione degli agenti.
Per
poter fare questo occorre accedere alla parte di security del server e
porre, il nome dell’autore dell’agente, informazione che troviamo fra le
proprietà dell’agente stesso, nella lista di nomi che possono eseguire
agenti di tipo restricted.
Ci
possiamo accorgere del fatto che questa modifica debba essere fatta, quando
il browser restituisce l’errore 500 al momento dell’esecuzione di una form,
il cui WebOpenAgent sia stato salvato da un utente non abilitato.
|
Figura
8 - Visualizzazione condizionale
Conclusioni
In
questa seconda puntata è stato spiegato il modo con il quale è
possibile interagire con delle form Notes, al momento della loro creazione,
tramite un semplice agente. Nella prossima puntata vedremo anche degli
esempi di gestione del salvataggio dei dati tramite un WebSaveAgent e del
modo col quale è possibile evitare il salvataggio, in concomitanza
di particolari condizioni.
Il
database di esempio citato nell'articolo può essere scaricato qui
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.
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 |