Ah, XPages. Das ist gut. Dann kann man SSJS nutzen (und damit ja auch Java-Code).
Hier ein Beispiel einer einfachen anonymen Funktion, die den übergebenen String zurück liefert:
1. Die anonyme Funktion
function(param : string){
return param;
}
2. Die Funktion in einen String packen, und Klammern darum setzen:
var code = "(function(param : string){ return param; })";
3. Jetzt den eval ausführen und das Ergebnis direkt erneut ausführen mit einem passenden Parameter
Nur als Hinweis: Es gibt neben den Standard-Java Libraries auch Tools wie z.B. den Runtime Compiler von OpenHTF https://github.com/OpenHFT/Java-Runtime-Compiler (https://github.com/OpenHFT/Java-Runtime-Compiler).
In SSJS ist die Nutzung von Java-Code von Haus aus vorgesehen. SSJS sind Strings, die von der JVM zur Laufzeit interpretiert werden, dass muss man also nicht nochmal neu erfinden. Der Vorteil von SSJS ist, dass Du sämtliche Classloader-Problematiken umgehst, und sofort Zugriff auf die Domino-Umgebung/NSF-Klassen hast, da quietscht es sonst manchmal ganz gewaltig. Auch wenn es um "dynamische Parameter" geht, ist Javascript aufgrund seiner - nennen wir es in diesem Fall "Flexibilität" - von Vorteil.
So kannst Du Dir also eine SSJS - Funktion aufbauen, die direkt auf deinen Java-Code zugreift. Um Java-Klassen wie z.B. Apache-POI aufzurufen, kannst Du diese ja direkt einbinden.
Mit dieser anonymen SSJS-Funktion würde der Name und die aus Java stammende Nano-Time direkt zurück gegeben:
function(name : string){
return "Hello " + name + "! - " +java.lang.System.nanoTime() ;
}
Ich baue mir immer simple Java-Klassen als Wrapper, die letztlich nur die Parameter aufnehmen, und der "echte" Code wird dann in Java ausgeführt. Keine Lust, alles von Java nach SSJS zu portieren, ist aber natürlich machbar.
In Javascript kann ich eine Funktion zur Laufzeit in einer Variable "parken" (so funktionieren die ganzen Callbacks). Wie ich diese befülle (also auch zur Laufzeit geladener Code aus einem Notes-Dokument) ist meine Entscheidung (=> http://hasselba.ch/blog/?p=832 (http://hasselba.ch/blog/?p=832)).
Das vorige Beispiel des Evals kann man auch wie folgt abändern:
Wenn du dir den Datentyp von myCode anschaust, wirst du feststellen, dass es vom Typ JSFunction (oder so ähnlich) ist.
In Javascript ist es dann möglich, die Variable mit zwei Klammern auszuführen:
Und per Definition kann ich auch beliebig viele Parameter übergeben, da gibt es keine Begrenzungen. Wenn ich also sowas aufrufe, führt es nicht zu Problemen während der Laufzeit (keine Defintion der Parameter notwendig; man kann die weglassen oder einfach welche ergänzen):
Um das noch ein wenig zu konkretisieren:
In deinem REST-Service hast du SSJS Code, der den eigentlichen auszuführenden Code aus einem Konfigurations-Dokument o.ä. lädt, mit eval() in eine Funktion umwandelt und diese dann mit den notwendigen Parametern ausführt. Also grob so etwas:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex">
<xe:restService pathInfo="/foo">
<xe:this.service>
<xe:customRestService>
<xe:this.doGet><![CDATA[#{javascript:
function ladeCode(codeId:string) : string {
// hier wird der Code geladen
return geladenerCode;
}
var code = ladeCode( 'CodeID' );
var func = eval( '(' + code + ')' );
return func( 'bar' )
}]]></xe:this.doGet>
</xe:customRestService>
</xe:this.service>
</xe:restService>
</xp:view>
In dem Code-Dokument ist dann einfach eine anonyme(!) Funktion hinterlegt, z.B. so etwas:
function(foo:string){
return foo;
}
In dieser anonymen Funktion kannst Du dann deine Java-Klassen aufrufen:
function(excelSheetName: string, docId: string){
return com.example.ExcelGenerator( excelSheetName, docId ) ;
}