LotusScript in XPages
Dies ist der zweite Teil des Artikels „LotusScript in XPages“. Der erste Teil befindet sich hier.
Der LotusScript-Wrapper
Um dynamischen LotusScript-Code auszuführen, bietet sich die Execute()-Funktion an: Mit der Funktion lässt sich fast der gesamte Umfang der LotusScript-eigenen Backendfunktionalität nutzen, also auch Scriptlibraries einbinden uvm.
Leider steht diese Methode jedoch nicht in Java direkt zur Verfügung (im Gegensatz zur Session.evaluate()-Methode für @Formelsprache), so dass nur der Umweg bleibt, die Funktion durch Aufruf eines LotusScript-Agenten zu verwenden, und das Ergebnis an die XPage zurück zu liefern. Dabei wird der auszuführende LotusScript-Code und das Ergebnis der Operation über ein temporäres NotesDokument via DocumentContext hin- und hergereicht.
Hier die Klasse „LSExceutor“, die die nötigen Hilfsfunktionen bereitstellt:
package ch.hasselba.xpages.jsf.el; import javax.faces.context.FacesContext; import java.util.Vector; import lotus.domino.Agent; import lotus.domino.Database; import lotus.domino.Document; public class LSExecutor { private final static String agentName = "(LSExecutor)"; private final static String fieldLSResult = "LSResult"; private final static String fieldLSCode = "LSCode"; public static Vector execLotusScriptCode( final String lscode ){ try{ Database curDB = (Database) getVariableValue("database"); Document doc = curDB.createDocument(); String hlp = lscode.replace( "\n", "\t" ); doc.appendItemValue( fieldLSCode, hlp ); Agent agent = curDB.getAgent( agentName ); agent.runWithDocumentContext( doc ); return doc.getItemValue( fieldLSResult ); }catch(Exception e){ e.printStackTrace(); } return null; } public static Object getVariableValue(String varName) { FacesContext context = FacesContext.getCurrentInstance(); return context.getApplication().getVariableResolver(). resolveVariable(context, varName); } }
Die statische Methode execLotusScriptCode() wird in den Bindings verwendet, die in Teil 1 beschrieben wurden. Durch den Umstand, dass die runWithDocumentContext()-Methode auf das Ende der Agentenausführung wartet, ist eine sequentielle Verarbeitung gewährleistet.
Der Agent ist ebenfalls recht einfach aufgebaut:
%REM Agent LSExecutor Created Apr 6, 2012 by Sven Hasselbach/Sven Hasselbach Description: LSExecutor agent is a mapper for executing LotusScript code from XPages %END REM Option Public Option Declare Const fieldLSCode = "LSCode" Const fieldLSResult = "LSResult" Dim returnValue Sub Initialize Dim session As New NotesSession Dim doc As NotesDocument Dim lsCode, tmp , ret Set doc = session.Documentcontext lsCode = doc.Getitemvalue( fieldLSCode ) tmp = Evaluate( | @ReplaceSubstring( "| & _ lsCode(0) & |"; @Char(9) ; @Char(10) ) | ) ret = Execute( tmp(0) ) doc.Replaceitemvalue fieldLSResult , returnValue End Sub
Um auf das Ergebnis der Berechnung zurückgreifen zu können, muss eine globale Variable verwendet werden, da die Execute()-Funktion selbst keine Rückgabemöglichkeit bietet (siehe Domino Designer Hilfe). In diesem Fall ist es „returnValue“, dessen Wert in das via DocumentContext übergebene Dokument geschrieben wird. Entsprechend muss der LotusScript-Code angepasst sein, siehe dazu auch die Beispiele am Anfang des 1. Teils des Artikels. Hier zeigt sich eine Schwachstelle: Es können keine Objekte zwischen Java und LotusScript übergeben werden; ein Zugriff auf z.B. den FacesContext ist in LotusScript nicht möglich. Soll eine DocumentCollection zurück geliefert werden, muss dieses als Array von DocumentUniversalIds geschehen usw.
Der Agent muss im Namen des Benutzers laufen, daher muss der „Run as Web user“-Haken gesetzt sein:
Im dritten Teil wird eine Quick-n-Dirty-Variante gezeigt, die BindingFactory bekannt zu machen.
Anmerkung:
An dieser Stelle sei nocheinmal ausdrücklich darauf hingewiesen, das der hier gezeigte Code sich maximal im „Alpha“-Status befindet.
Pingback: LotusScript in XPages (1): Basics | blog@hasselba.ch
Pingback: LotusScript in XPages (3): Quick-n-Dirty-Aktivierung | blog@hasselba.ch