Lotus Notes / Domino Sonstiges > Java und .NET mit Notes/Domino
Mit java eine SessionFactory für Notes implementieren
sudsaat:
Hallo community,
für eine komponentenbasierte Entwicklung bin ich gerade dabei ein technisches Konzept zu erarbeiten. Mitunter ist eine Notes-Komponente, die den Zugriff auf Domino kapselt ein Thema.
Mein Ansatz (denke da liegt mein Fehler) ist folgender:
1. Konfiguration der Komponente über ein property-file
--- Code: ---# WeberT: properties for the domino-access component.
# generally set the type of access. Following types are available
# IIOP - using CORBA to access domino-server.
# local - using locally installed notes-client to access domino-server
domino.access.type=IIOP oder local
domino.access.host=serverIP oder HostName
domino.access.user=vollständiger benutzer
domino.access.password=passwort
--- Ende Code ---
2. Eine "generische" Factory entscheidet, welche Factory (Corba oder local) die Komponente verwendet
--- Code: ---import java.util.ResourceBundle;
import lotus.domino.Session;
public class GenericDominoFactory {
// WeberT: the name of the property-file
private static final String DOMINO_FACTORY_RESOURCE_NAME = "dominofactory";
// WeberT: the key to get access-type from property-file
private static final String DOMINO_ACCESS_TYPE_KEY = "domino.access.type";
// WeberT: this are the available access-types
private static final String DOMINO_ACCESS_IIOP = "IIOP";
private static final String DOMINO_ACCESS_LOCAL = "LOCAL";
private static DominoFactory factory;
private GenericDominoFactory() {
}
public static Session getDominoSession() {
if (factory==null) {
ResourceBundle resources = ResourceBundle.getBundle(DOMINO_FACTORY_RESOURCE_NAME);
String accessType = resources.getString(DOMINO_ACCESS_TYPE_KEY);
if (accessType.equalsIgnoreCase(DOMINO_ACCESS_IIOP)) {
factory = new RemoteCorbaDominoFactory();
} else if (accessType.equalsIgnoreCase(DOMINO_ACCESS_LOCAL)) {
factory = new LocalDominoFactory();
} else {
System.out.println("DOMINO: no valid access-type was given, please check " + DOMINO_FACTORY_RESOURCE_NAME + ".properties for key " + DOMINO_ACCESS_TYPE_KEY);
}
}
return factory!=null ? factory.getDominoSession() : null;
}
}
--- Ende Code ---
3. Die beiden konkreten Factories folgen dem Interface "DominoFactory"
--- Code: ---import lotus.domino.Session;
public interface DominoFactory {
public abstract Session getDominoSession();
}
--- Ende Code ---
4a. Entweder übernimmt die Corba-Implementierung das Erzeugen einer Session
--- Code: ---import java.util.ResourceBundle;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.Session;
public class RemoteCorbaDominoFactory implements DominoFactory {
private static final String DOMINO_FACTORY_RESOURCE_NAME = "dominofactory";
private static final String DOMINO_HOST_KEY = "domino.access.host";
private static final String DOMINO_USER_KEY = "domino.access.user";
private static final String DOMINO_PASSWORD_KEY = "domino.access.password";
@Override
public Session getDominoSession() {
ResourceBundle resources = ResourceBundle.getBundle(DOMINO_FACTORY_RESOURCE_NAME);
Session session = null;
try {
session = NotesFactory.createSession( resources.getString(DOMINO_HOST_KEY),
resources.getString(DOMINO_USER_KEY),
resources.getString(DOMINO_PASSWORD_KEY));
} catch (NotesException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return session;
}
}
--- Ende Code ---
..anschließend kann ich die session verwenden und muss nur an "recycle" aller erzeugten Objekte und der Session selbst kümmern.
4b. Oder die Local-Implementierung erzeugt die Session
--- Code: ---import java.util.ResourceBundle;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.NotesThread;
import lotus.domino.Session;
public class LocalDominoFactory implements DominoFactory {
@Override
public Session getDominoSession() {
NotesThread.sinitThread();
Session session = null;
try {
session = NotesFactory.createSession();
} catch (NotesException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// NotesThread.stermThread();
return session;
}
}
--- Ende Code ---
Neben dem Problem, dass ich eigentlich gerne die Session über die überladene static-Methode NotesFactory.createSession((String)null, user, pwd) erzeugen würde (da bekomme ich user is not a server?!? - dazu habe ich aber einen weiteren Thread hier eröffnet), stehe ich vor der Problematik, wie ich das mit dem stermThread() am besten handhabe.
Wenn ich das bereits in der Implementierung aufrufe, erhalte ich logischerweise später die Meldung:
Object has been removed or recycled
wenn ich es nicht aufrufe, besteht die Gefahr, dass Notes crashed.
Meine Vermutung ist, dass mein Ansatz für Notes nicht praktikabel ist?
Welche Ansätze gibt es, um eine solche Komponente zu entwickeln (einen globalen Thread der die Session aufrecht hält? Einen finally-Block? etc...).
Bin für jeglichen Input dankbar.
Grüße Thomas :-)
Ralf_M_Petter:
Hallo Thomas!
So wie du willst, wirst du das nicht hinbekommen. Das Notesthread.sinitThread und NotesThread.stermThread muss in jedem Thread extra gemacht werden. Das heisst, wenn du dein generiertes Session Objekt in einem anderen Thread verwenden willst, dann muss auch dieser Thread erst initialisiert werden und wieder deinitialisiert werden.
Ich verwende ein anderes Modell das einige Vorteile hat.
Ich habe einen Threadpool generiert, in dem x Threads automatisch für Domino initialisiert und eine Session erstellt werden. Wenn ich nun Code habe der Domino verwendet packe ich den in einen Runnableblock und übergebe in dem Threadpool. Zur Übergabe des RunnableObjekts gibt es eine Methode für Asynchrone Ausführung und auch Warten bis der Block abgeschlossen ist.
Der grosse Vorteil ist, dass in allen Thread die Session immer schon bereit steht und auch zuverlässig von dem Threadpool recycelt wird. Das heisst, wenn ich in einem Runnableblock mal auf das Recyceln vergesse, dann ist nichts verhaut, da die Session am Ende der Ausführung automatisch recycelt wird. Man kann den Threadpool natürlich auch so programmieren, dass er nicht nur das Session Objekt vorhält, sondern auch noch andere Objekte schon voraus generiert, wie Datenbanken oder View Objekte.
Wenn meine Anwendung beendet wird, ruft sie eine Methode des Threadpools auf, die alle Threads ordnungsgemäß beendet.
Grüße
Ralf
sudsaat:
Hallo Ralf,
das habe ich mir schon gedacht das ich irgendwie auf dem Holzweg bin.
Dein Ansatz klingt sehr gut, hast du da eventuell ein code-snippet auf dem ich aufbauen könnte parat? Gerade der Pool mit der asynchronen Ausführung würde mich interessieren.
Vielen Dank.
Grüße Thomas :-)
Ralf_M_Petter:
Kann leider keinen Code posten, da der Code für meinen Arbeitsgeber entwickelt wurde. Ist jetzt etwas zu viel Arbeit es hier nachzuprogrammieren. Ausserdem wenn ich es nocheinmal machen müsste würde ich es mit dem Concurrent Framework probieren, dass ja mittlerweile verfügbar ist.
Für einen ersten Einstieg in das Concurrent Framework von Java lies dir mal http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html#terminated%28%29 durch oder du kaufst dir gleich das Buch über Concurrency in Java http://www.amazon.de/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1291122897&sr=8-1
Grüße
Ralf
sudsaat:
Hi Ralf,
das mit dem Code posten ist kein Problem - kann ich nachvollziehen :-)
Das mit dem Concurrent-Framework ist eine gute Idee - auf die bin ich noch gar nicht gekommen.
Werde mich mal daran versuchen, wobei meine Hürde eher Domino als Java ist ;-)
Vielen Dank für dein Feedback, hat sehr geholfen!
Grüße Thomas :-)
Navigation
[0] Themen-Index
[#] Nächste Seite
Zur normalen Ansicht wechseln