LotusScript in XPages (1): Basics

LotusScript in XPages

Dies ist der erste Teil des Artikels „LotusScript in XPages“. Der zweite Teil befindet sich hier.

 

Wäre es nicht schön, wenn man in XPages direkt mit Lotus Script arbeiten könnte? Wenn es einen Weg gäbe, mit der sich Lotus Script-Code direkt in der XPage einbetten liesse, und wie folgt zu verwenden wäre?

Prinzipiell ist das möglich, aber der hier dargestellte Weg ist eher als Workaround anzusehen und wird das Alpha-Stadium wohl eher nicht verlassen. Aber es lässt sich anhand dieser Anleitung zeigen, wie man XPages flexibel erweitern und weitere Interpreter-Sprachen der XPages-Engine hinzufügen kann.

Was mit der hier vorgestellten Lösung jedoch möglich ist, kann man in dieser kleinen Beispiel-XPage sehen:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

   <xp:label id="label1">
      <xp:this.value>
         <![CDATA[#{lotusscript:returnValue=-1 }]]>
      </xp:this.value>
   </xp:label>
   <xp:br/>
   <xp:br/>
   <xp:label id="label2">
      <xp:this.value><![CDATA[${lotusscript:
         Dim session as New NotesSession
         Dim db as NotesDatabase
         Set db = session.CurrentDatabase

         returnValue = db.AllDocuments.getFirstDocument.UniversalID
      }]]></xp:this.value>
   </xp:label>
</xp:view>

In der XPage kann der neue Tag „lotusscript:“ verwendet und beliebiger LotusScript-Code direkt in die XPage eingebettet werden. Das Ergebnis im Browser sieht dann wie folgt aus:

Soviel vorab, nun zu erst einmal zu den Basics…

Grundlagen: Method-Bindings & Value-Bindings

Um einen neuen Tag für XPages bereitzustellen, müssen zu aller erst Bindings für Methoden- und für Werte-Zuweisungen erstellt werden. Die beiden Binding-Arten unterscheiden sich – grob formuliert* – wie folgt: Value-Bindings werden überall dort verwendet, wo ein Wert einer Komponente zugewiesen wird und (wie der Name erahnen lässt) eine value-Eigenschaft exitsiert. Dies ist bei praktisch allen UIKomponenten der Fall. Method-Bindings hingegen kommen bei der Zuweisung bei samtlichen Events ins Spiel: Der SSJS-Code eines BeforePageLoad-Events wird mit einem Method-Binding gesetzt, oder der Code bei Button-Events usw.

Die Value-Binding-Klasse, die für die hier geschilderten Zwecke benötigt wird, sieht wie folgt aus:

package ch.hasselba.xpages.jsf.el;

import com.ibm.xsp.binding.ValueBindingEx;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyNotFoundException;

public class LSValueBinding extends ValueBindingEx {
    private String data;

    public LSValueBinding(String data) {
        this.data = data;
    }

    @Override
    public Object getValue(FacesContext context)
        throws EvaluationException, PropertyNotFoundException {
            return LSExecutor.execLotusScriptCode( this.data );
    }

    @Override
    public void setValue(FacesContext context, Object obj)
       throws EvaluationException, PropertyNotFoundException {}

    @Override
    public boolean isReadOnly(FacesContext context)
        throws EvaluationException, PropertyNotFoundException {
            return true;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Class getType(FacesContext context)
        throws EvaluationException, PropertyNotFoundException {
            return Object.class;
    }
}

Das Value-Binding erweitert die Klasse com.ibm.xsp.binding.ValueBindingEx und überschreibt deren Eigenschaften, wo es nötig ist. Im Konstruktor der Klasse findet die Wertezuweisung statt; es wird hier der Teil, der in der XPage nach dem „lotusscript:“ folgt, übergeben. Auch mehrzeiliger Code in der XPage wird als einfacher String durchgereicht, getrennt durch Zeilenumbrüche.

Um an den Wert des Bindings zu gelangen, wird während der Verarbeitung durch das JSF Framework die Methode getValue() aufgerufen; dies ist die Stelle, an der die Daten des Value-Bindings verarbeitet werden, und wie man hier sehen kann, findet der Aufruf des LotusScript-Codes genau an dieser Stelle statt.

Das notwendige Method-Binding ist so ähnlich aufgebaut:

package ch.hasselba.xpages.jsf.el;

import com.ibm.xsp.binding.MethodBindingEx;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.MethodNotFoundException;

public class LSMethodBinding extends MethodBindingEx {
    private String data;

    public LSMethodBinding () {
        super();
    }

    public LSMethodBinding (String expr) {
        super();
        this.data = expr;
    }

    @Override
    public Object invoke(FacesContext context, Object[] obj)
        throws EvaluationException, MethodNotFoundException {
            return LSExecutor.execLotusScriptCode( this.data );
    }
    @SuppressWarnings("unchecked")
    @Override
    public Class getType(FacesContext context)
        throws MethodNotFoundException {
            return null;
    }
}

Hier wird wie Klasse com.ibm.xsp.binding.MethodBindingEx erweitert und – wenn nötig – überschrieben. Anders als beim Value-Binding erfolgt der „Abruf“ der Daten eines Method-Bindings durch das JSF Framework nicht durch getValue(), sondern durch die Methode invoke(). Hierbei können theoretisch noch Parameter übergeben werden, die für die Verarbeitung relevant sein könnten. In diesem Fall kann dies aber getrost ignoriert werden.

Zu guter Letzt müssen die beiden Bindings in eine BindingFactory-Klasse zusammen geführt und mit dem „lotusscript„-Tag verbunden werden:

package ch.hasselba.xpages.jsf.el;

import com.ibm.xsp.util.ValueBindingUtil;
import com.ibm.xsp.binding.BindingFactory;
import javax.faces.application.Application;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;

public class LSBindingFactory implements BindingFactory {

    public String getPrefix() {
        return "lotusscript";
    }

    @SuppressWarnings("unchecked")
    public MethodBinding createMethodBinding(
         Application app, String expr, Class[] obj) {
        String script = ValueBindingUtil.parseSimpleExpression(expr);
        return new LSMethodBinding(script);
    }

    public ValueBinding createValueBinding(Application app, String expr) {
        String script = ValueBindingUtil.parseSimpleExpression( expr );
        return new LSValueBinding(script);
    }
}

Die Klasse erweitert com.ibm.xsp.binding.BindingFactory und ist die „Weiterleitung“ innerhalb des JSF-Frameworks: Die Methode getPrefix() liefert den String zurück, für den diese BindingFactory zuständig ist; es ist praktisch jeder Bezeichner verwendbar, nur id und javascript sind bereits belegt.

Während der Verarbeitung der Bindings sucht das JSF-Framework zur Laufzeit nach der passenden Factory. Dabei werden alle bekannten Factories nach dem passenden Prefix durchsucht, weshalb die BindingFactory dem Framework noch bekannt gemacht werden muss, um verwendet werden zu können.

Im zweiten Teil wird eine Quick-n-Dirty-Variante gezeigt, die BindingFactory bekannt zu machen und der LotusScript-Wrapper wird vorgestellt.

*: Anmerkung:

Aus Sicht der JSF-Spezifikation ist der Unterschied zwischen Value-Binding und Method-Binding etwas komplexer, als hier dargestellt.

Dieser Beitrag wurde unter Allgemein, Expression Language, Extensibility API, Java, JSF, Lotus Script, XPages, XSP abgelegt und mit , , , , , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

2 Kommentare zu LotusScript in XPages (1): Basics

  1. Pingback: LotusScript in XPages (2): LotusScript-Wrapper | blog@hasselba.ch

  2. Pingback: LotusScript in XPages (3): Quick-n-Dirty-Aktivierung | blog@hasselba.ch

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.