Hallo zusammen,
ich habe unter Verwendung der Lotus C++ API eine Dynamic Link Library erstellt, deren (externe) Funktionen ich unter Java verwenden möchte. Hierzu habe ich mich der JNI (Java Native Interface) bedient. In einer eigenständigen Java-Anwendung (welche die Klasse NotesThread erweitert) funktioniert der Zugriff auf die nativen Funktionen einwandfrei. Wenn ich jedoch selbiges in einem Agenten tun möchte, so meldet mir Java, dass es die nativen Funktionen nicht finden könne.
Um das Verhalten zu demonstrieren, habe ich mal ein simples Beispiel angefertigt. Hier zunächst einmal der Code für die Dynamic Link Library und die dazugehörige Java Klasse, welche die externe Funktion der DLL implementiert und so unter Java verfügbar macht:
MyNativeMethod.h
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class de_dominoforum_MyNativeMethod */#ifndef _Included_de_dominoforum_MyNativeMethod#define _Included_de_dominoforum_MyNativeMethod#ifdef __cplusplusextern "C" {#endif/* * Class: de_dominoforum_MyNativeMethod * Method: Print * Signature: (Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_de_dominoforum_MyNativeMethod_Print (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif
MyNativeMethod.cpp
#include "MyNativeMethod.h"#include <iostream>using namespace std;JNIEXPORT void JNICALL Java_de_dominoforum_MyNativeMethod_Print(JNIEnv *env, jobject obj, jstring jStrDbTitle){ string strDbTitle( env->GetStringUTFChars(jStrDbTitle,NULL) ); cout << strDbTitle.c_str() << endl;}
MyNativeMethod.java
package de.dominoforum;/** * Die Klasse MyNativeMethod implementiert die native Methode Print, * welche in einer externen Dynamic Link Libary definiert ist. * Die Methode wurde unter Verwendung der Lotus C++ API realisiert * und tut nichts weiter, als den im ersten (und einzigen) Argument * mitgegebenen String auf der Konsole (Bildschirm) auszugeben. * * @author Leon */public class MyNativeMethod{ /** * Die Methode Print ist in der Dynamic Link Library MyNativeMethod.dll * definiert und tut nichts weiter, als den im ersten (und einzigen) * Argument mitgegebenen String auf der Konsole (Bildschirm) auszugeben. * * @param str Der String, welcher auf der Konsole ausgegeben * werden soll. */ public native void Print(String str); /** * Hier wird die Dynamic Link Library MyNativeMethod.dll geladen und * zwar noch vor der Instanziierung der Klasse. Die Dymanic Link * Library muss sich im CLASSPATH befinden. */ static { System.loadLibrary("MyNativeMethod"); }}
So weit so gut. Im Folgenden der Code, welcher eine eigenständige Java-Anwendung realisiert und die native Funktion einbindet. Dies funktioniert einwandfrei, d.h. der Titel des lokalen Adressbuchs (names.nsf) wird auf der Konsole (dem Bildschirm) ausgegeben.
ExtendedNotesThread.java
package de.dominoforum;import lotus.domino.*;/** * Die Klasse Main erweitert die Klasse NotesThread und bezieht eine * Notes-Session außerhalb einer Notes-Datenbank. Somit lassen sich * eigenständige Anwendungen realisieren, welche im Vergleich zu * einem klassischen Agenten nicht Teil einer Notes-Datenbank sind. * Ein weiterer Wichtiger Unterschied zum klassischen Agenten besteht * darin, dass die eigenständige Anwenung nicht zwingend unter der * Notes / Domino eigenen Java Runtime Engine ausgeührt werden muss, * sondern unter einer (gewöhnlichen) JRE von Sun Microsystems * ausgeführt werden kann. * * @author Leon */public class ExtendedNotesThread extends NotesThread{ /** * Die statische main-Methode erzeugt eine Instanz der Klasse * Main, welche die Klasse NotesThread erweitert. Dann wird * mittels der Methoden start() und join() die Methode runNotes * aufgerufen. * * @param args Kommandozeilenparameter - nicht in Verwendung */ public static void main(String[] args) { ExtendedNotesThread main = new ExtendedNotesThread(); main.start(); try { main.join(); } catch(InterruptedException e) { e.printStackTrace(); } } /** * In der Methode runNotes() wird eine Notes-Session erzeugt und * das lokale Adressbuch (names.nsf) geöffnet. Dann wird der Titel * des Adressbuchs an die native Methode Print der Klasse * MyNativeMethod übergeben, welche den Titel auf der Konsole * ausgeben soll. */ public void runNotes() { Session session; Database db; MyNativeMethod m = new MyNativeMethod(); try { session = NotesFactory.createSession(); db = session.getDatabase("", "names.nsf"); m.Print( db.getTitle() ); db.recycle(); session.recycle(); } catch(NotesException e) { e.printStackTrace(); } }}
Führt man die Anwendung aus, wird wie erwartet die native Funktion Print aus der Dymanic Link Library MyNativeMethod.dll aufgerufen und der Titel des lokalen Adressbuchs erscheint auf der Konsole.
Im Folgenden versuchen wir nun das selbe in einem Agenten:
JavaAgent.java
package de.dominoforum;import lotus.domino.*;/** * Die Klasse Main erweitert die Klasse AgentBase und bezieht von * ihr eine Notes-Session. Somit wird ein klassischer Agent * realisiert, welcher Teil einer Notes-Datenbank ist. Daher läuft * der Agent unter der Java Runtime Engine von Notes / Domino, wo * sich die Datenbank befindet. * * @author Leon */public class JavaAgent extends AgentBase{ /** * Die Methode NotesMain() bildet den Einstiegspunkt für den Agenten. * Es wird eine Session über die AgentBase bezogen. Im Folgenden wird * das lokale Notes-Adressbuch (names.nsf) geöffnet und der Titel des * Adressbuchs an die native Methode Print der Klasse MyNativeMethod * übergeben, welche des Titel auf der Konsole ausgeben soll. */ public void NotesMain() { Session session; Database db; MyNativeMethod m = new MyNativeMethod(); try { session = getSession(); db = session.getDatabase("", "names.nsf"); m.Print( db.getTitle() ); db.recycle(); session.recycle(); } catch(NotesException e) { e.printStackTrace(); } }}
Die dll muss sich dabei im Notes-Verzeichnis befinden, damit sie gefunden wird. Allerings bekomme ich trotzdem folgende Fehlermeldung:
java.lang.UnsatisfiedLinkError: Print
at de.dominoforum.JavaAgent.NotesMain(JavaAgent.java:33)
at lotus.domino.AgentBase.runNotes(AgentBase.java:161)
at lotus.domino.NotesThread.run(NotesThread.java:203)
Wieso wird auf einmal die externe Funktion Print in der Dynamic Link Library nicht mehr gefunden ?
Bitte um Hilfe ! Den kompletten Quellcode inkl. compilierter DLL habe ich dem Post einmal als zip-Archiv beigefügt.
MfG
Leon
PS: Gibt es in diesem Forum eigentlich auch Spoiler, mit denen sich bestimmt Bereiche im Post auf- und zuklappen lassen ? Dann würde ich den ganzen Code in Spoiler packen, um den Post nicht so auf zu blasen.