Showing posts with label Expeditor. Show all posts
Showing posts with label Expeditor. Show all posts

Saturday, February 16, 2013

Lotusscript Code aus Java plugin aufrufen

In bestehenden Notesanwendungen steckt jede Menge Lotusscript Code der über viele Jahre aufwendig entwickelt wurde, deshalb möchte man bei der Entwicklung von Plugins nicht das Rad neu erfinden, sondern bestehenden Code auch aus Eclipse plugins aufrufen. Wie dies geht möchte ich heute gerne zeigen:

Als erstes muss man die Notes API (com.ibm.notes.java.api und com.ibm.java.ui) dem Plugin als Abhängigkeit hinzufügen.

Als Beispiel habe ich eine scriptlibrary mit einer Funktion getUmsatz mit den Parametern Kundennummer und Jahr hergenommen. In der Funktion der Scriptlibrary werden aufwendige Datenbankzugriffe und Berechnungen durchgeführt, die wir in java nicht nachprogrammieren wollen.

Da man von Java nicht direkt auf die Library zugreifen kann, braucht man als erstes einen kleinen Agent der als Brücke zwischen dem Plugin und der Scriptlibrary fungiert.



Option Public
Option Declare
Use "UmsatzScriptLibrary"
Sub Initialize
 Dim ses As New NotesSession
 Dim context As NotesDocument
 Set context=ses.Documentcontext
 Call context.Replaceitemvalue("umsatz", getUmsatz(context.Getitemvalue("kundenNummer")(0), context.getItemValue("jahr")(0)))
 Print context.Getitemvalue("umsatz")(0)
 context.save True,false
End Sub


Der Agent macht nichts anderes, als dass er ein in Memory Dokument über den Dokumentcontext holt. Die Aufrufparameter für die getUmsatz Funktion ausliest und das Ergebnis der Funktion in der Variable Umsatz speichert. Natürlich konnte man den Agent auch dahingehend erweitern, dass in dem in Memory Dokument auch ein Parameter für die auzurufende Funktion mitgegeben wird und er dann die richtige Funktion aus der Scriptlibrary aufruft.

Wichtig bei dem Agent ist, dass man das Ziel auf "None" setzt. Sonst funktioniert der Zugriff auf das übergebene Dokument nicht zuverlässig.


Der Javateil ist etwas aufwendiger:


public static void berechneKundenUmsatz(String kundenNummer, int jahr) {
  try {
   // Starte den Zugriff auf den Workspace und erstelle ein
   // NotesAgentDataobjekt mit unserem Brückenagent.
   NotesUIWorkspace ws = new NotesUIWorkspace();
   NotesAgentData data = new NotesAgentData(new NotesDatabaseData("",
     "test.nsf"), "agent");
   // Füge die Aufrufparameter für die Scriptlibrary dem data Objekt
   // hinzu. Diese werden später im documentcontext als Items
   // verfügbar.
   data.addItem("kundenNummer", kundenNummer);
   data.addItem("jahr", new Integer(jahr).toString());
   // Erstelle ein Callback Objekt. die Methode done dieses Objekts
   // wird nach Ausführung des Brücken Agent aufgerufen.
   NotesDocumentDataCallback callBack = new NotesDocumentDataCallback() {
    @Override
    public void done(final NotesDocumentDataEvent event) {
     // Erstelle einen Notessessionjob in dem wir auf das
     // zurückgegebene Dokument zugreifen können.
     NotesSessionJob job = new NotesSessionJob(
       "verarbeite Ergebnis") {
      @Override
      protected IStatus runInNotesThread(Session session,
        IProgressMonitor arg1) throws NotesException {
       // Lade das Dokument, dass der Agent mit dem
       // Ergebnis befüllt hat.
       Document doc = event.getDocumentData()
         .open(session);
       // Speichere das Resultat in einer Finalen Variable,
       // dass wir es im UIThread weiterverwenden können.
       final double result = doc
         .getItemValueDouble("umsatz");
       // Mache irgendetwas im UI mit dem Resultat. In
       // unserem Beispiel eine Dialogbox anzeigen.
       Display.getDefault().asyncExec(new Runnable() {
        @Override
        public void run() {
         MessageBox box = new MessageBox(PlatformUI
           .getWorkbench()
           .getActiveWorkbenchWindow()
           .getShell());
         box.setMessage("Das Ergebnis ist: "
           + result);
         box.open();
        }
       });
       return Status.OK_STATUS;
      }
     };
     // starte den Notesjob
     job.schedule();
    }
   };
   // Führe den Agent mit dem data und callback Objekt aus. Der letzte
   // Parameter bedeutet, das der UIContext keine Rolle spielt. Das
   // heißt es ist egal auf welches Dokument im UI derzeit geöffnet
   // ist.
   ws.runAgent(data, callBack, false);
  } catch (NotesException e) {
   e.printStackTrace();
  }

 }
Das ist jetzt natürlich nur ein kleines Beispiel, bei dem der Aufwand vielleicht nicht dafür steht, aber in dem Lotusscript agent kann auch auf das UI zugegriffen werden. Das heißt der Agent kann Dialoge anzeigen und er kann auch mehrere Werte oder eine ganze Liste als Ergebnis zurückliefern. Damit kann man auch bei der Entwicklung von Plugins sehr leicht bestehenden Code wieder verwenden.

Friday, January 11, 2013

Neuer Artikel im Wiki über Plugin und Feature Deployment

Die IBM hat eine sehr gute Beschreibung (Managing features in the IBM Lotus Notes 8.5.x Client) über die verschiedenen Möglichkeiten der Installation von Features und Plugins im Lotus Notes Domino Wiki veröffentlicht. Ich war am Anfang sehr skeptisch bezüglich der Wikis aber in letzter Zeit wird wirklich sehr guter Content seitens der IBM veröffentlicht. Hoffentlich hält der positive Trend an.

Monday, October 22, 2012

Internationale Sonderzeichen in Lotus Notes plugins

Wenn man in seinem Javacode internationale Sonderzeichen wie z.B. Umlaute in String Literalen verwendet, kann es passieren dass nach dem Export des Plugins die Sonderzeichen falsch angezeigt werden. Dies passiert dadurch, dass beim Kompilieren von Plugins standardmäßig nicht UTF-8 sondern ein nicht Unicode fähiger Characterset verwendet wird. Man kann das Problem einfach lösen, in dem man in die build.properties seines Plugins den Eintrag "javacDefaultEncoding.. = UTF-8" ergänzt.

Eine Beispiel "build.properties" Datei sieht dann folgendermaßen aus:

source.. = src/
output.. = bin/
javacDefaultEncoding.. = UTF-8
bin.includes = META-INF/,\
               .,\
               plugin.xml,\
               icons/


Dann sollten String Literale in diesem Plugin richtig angezeigt werden.

Tuesday, May 22, 2012

Workspace Pfad mit Einstellungen für Plugins in Notes/Eclipse

Jedes Plugin in Notes/Eclipse kann Einstellungen haben, die bestimmte Funktionalitäten des Plugins steuern.

Diese Einstellungen werden in dem Pfad "workspace\.metadata\.plugins\org.eclipse.core.runtime\.settings" abgelegt. Für jedes Plugin, dass Einstellungen (Preferences) verwendet, wird ein eigenes Prefs File erstellt. Diese PrefsFiles können mit einem Texteditor problemlos editiert werden und sind als Schlüsselwort Wert Paare aufgebaut. Normalerweise ist es so, dass wenn man die Prefsdatei löscht, wird das File beim nächsten Laden des Plugins wieder mit Defaulteinstellungen erstellt. Das kann auch helfen, wenn in Lotus Notes irgendwas nicht so funktioniert wie es soll. Statt des Löschen des gesamten workspace Ordner kann man zielgerichtet einzelne Einstellung rauslöschen.

Monday, April 16, 2012

Den Öffnen Knopf im Lotus Notes Client erweitern

Die Dokumentation zu Expeditor ist ja eher unübersichtlich, daher hier eine kleine Anleitung wie man ein bestehendes Plugin erweitern muß, damit man im Launcher (Öffnen Knopf) eigene Einträge platzieren kann.

Die Voraussetzungen für diese Beschreibung ist, dass in Eclipse bereits die Targetplattform für Notes eingerichtet ist und sich Notes aus Eclipse heraus starten lässt. Entweder mittels Expeditor Toolkit oder der Beschreibung von Mikkel Heisterberg. 

Dann legen wir mit dem entsprechenden Assistenen in Eclipse ein neues Pluginprojekt an.

In diesem neuen Plugin müssen wir folgende zusätzliche Abhängigkeiten hinzufügen:
 
Diese sind notwendig, damit man das UI von Lotus Notes erweitern kann.

Danach kann man in seinem Plugin den Erweiterungspunkt "com.ibm.rcp.ui.launcherSet"erweitern.



Dann sollte man einen LaunchItemType anlegen. Ein LaunchItemType kann für mehrere LaunchItems zuständig sein. Die Klasse MyLaunchHandler müssen wir später noch selbst anlegen.


Jetzt können wir die von uns gewünschten LaunchItems anlegen. Zuerst "Test1"

Natürlich kann man wenn gewünscht auch noch Icons angeben.

und dann als Übung einfach noch ein zweites mit "Test2" anlegen.


Dann muss man die Klasse MyLaunchHandler erstellen. Normalerweise kann man das bequem über den Link "class*:" beim LaunchItemType machen. Aber die IBM hat obwohl Lotus Expeditor noch ziemlich neu ist schon ein ziemliches Chaos angerichtet und deshalb gibt es die Basisklasse LaunchItemContribution bereits in zwei verschiedenen Paketen. In der Extensionpointbeschreibung ist blöderweise die falsche angegeben. Aber kein Problem einfach über den Eclipse Assistenten eine neue Klasse erstellen.


Wichtig ist, dass der Name übereinstimmt mit dem Klassennamen den wir im Type angegeben haben. In Echt wird man das ganze natürlich in ein vernünftiges Paket packen. Weiters ist wichtig, dass man als Superclass die LauncherContributionItem Klasse aus com.ibm.rcp.ui.launcher und nicht die aus jfacex nimmt.

In die Neuerstellte Klasse muss dann nur noch eine Launchmethode eingefügt werden.

public void launch(int arg0) {
        super.launch(arg0);
        MessageBox msg = new           MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
        if (getId().equals("org.startmenuitem2")) {
            msg.setMessage("Es wurde Test2 ausgewählt");
        }
        if (getId().equals("org.startmenuitem1")) {
            msg.setMessage("Es wurde Test1 ausgewählt");
        }
        msg.open();
    }


Diese wird aufgerufen jedes Mal wenn ein Launchitem des von uns erstellten Typs aufgerufen wird. Anhand von getId() kann man dann abfragen welches item konkret der Benutzer aufgerufen hat. Wir zeigen dann mal die entsprechende Messagebox an. In meinen Plugins wird meist ein Assistent aufgerufen, der von Benutzern einige Eingaben erfordert und dann z.B. eine neuen Reiter mit einem Eclipse UI im Notes öffnet.

ad