Autor Thema: klassischer Artikel für Domino/Websphere Integration von B. Balaban  (Gelesen 3776 mal)

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Hi,

schon ein wenig älter, aber Bob Balaban ist wirklich ein sorgfältiger Autor.
Grundsätzlich hat sich nicht viel geändert.
Natürlich würde ich in der Praxis niemals von einem Servlet auf Domino-Backend Klassen zugreifen. Dafür ist schließlich der Business Layer da  ;)
Grundsätzlich anders ist das dann aber auch nicht.
Vieles erinnert an die Diskussionen hier in den letzten Tagen.

Erinnert mich an gestern.
Zitat
Actually, the fact that you have to do this init/term sequence on all threads turns out to affect the entire coding pattern for using Domino objects. The reason for this is that you can't cache any Domino objects across the init/term boundary. As a result, you have to re-acquire a Session and all other object instances each time your servlet or EJB entry point is called. This requirement (which I hope IBM will fix in a future release of WebSphere Application Server) might severely limit the scalability of your application.

Ketzerische Frage: Hat Bob das 2-Domino-Threads pattern, das wir gestern hier erarbeitet haben gesehen?
Theoretisch kann man nämlich sehr wohl Domino-Objekte in Servlet Instanzvariablen speichern (wenn man nämlich einfach in Servlet.init() kein stermTread() macht und das in Servlet.destroy() verlagert . Servlet init() wird einmal beim allerersten Aufruf des Servlets durchlaufen und Servelt.destroy genau einmal beim runterfahren.
Da die doGet() und doPost() Methoden des Servlets nur lesend auf die (Domino-)Instanzvariablen zugreifen ist das auch Thread-Safe.  :-X

hab den Artikel-Link vergessen: http://www.advisor.com/article/balab03
« Letzte Änderung: 30.07.03 - 23:37:16 von Axel_Janssen »
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

Glombi

  • Gast
Hallo Axel,
kannst Du das mit dem
"Natürlich würde ich in der Praxis niemals von einem Servlet auf Domino-Backend Klassen zugreifen. Dafür ist schließlich der Business Layer da "
näher erläutern? Wie sähe das in der Praxis aus?

Aber nur wenn's nicht zuviel Mühe macht (und ich kein Projekt auf's Auge gedrückt bekomme  ;D  )

Andreas
« Letzte Änderung: 30.07.03 - 21:39:57 von Glombi »

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Das vermutlichste OO-design-Prinzip ist wohl separation of concern. Jede Klasse/Komponente einer Anwendung soll sich auf einen speziellen Aufgabenbereich konzentrieren (hohe Kohäsion).

In J2EE Anwendungen hat man die 3 klassischen Schichten: Präsentation, Business-Logik (komisches Wort: das was die Anwendung eigentlich macht (auch komisch)) und Persistenz.
Zugriff auf Lotus gehört eigentlich in den Persistenz-Layer (Datenbank). Deshalb hat es im Servlet (Präsentation) nichts zu suchen.
Servlets haben dabei im Präsentations-Layer nur eine Teilfunktion (entgegennahme von User-Requests, aber das nur am Rande und bei bestimmten Web-Frameworks stimmt das so nicht).

In einer normal designten Anwendung würde das Servlet die User-Eingaben entgegennehmen und diese Ergebnisse dann irgendwelchen Business-Objekte weiterleiten, die dann Persistenz-Objekten sagen, was sie wie in LoNo abspeichern sollen. Die Business-Methoden würden dann Ergebnisse an JSPs weitergeben, die die Ergebnisse dem User präsentieren.

Ein solches Separation-of-concerns Konzept ist nicht irgendein akademischer Schwachsinn, sondern bringt wirkliche Vorteile:
- bessere Übersichtlichkeit (Veränderung, Erweiterung, Fehlersuche leichter).
- Testbarkeit von Einzelmodulen.

In meinen Swing-Applets sind z.B. alle Notes-Zugriffe in einer Klasse NotesConnection. Falls irgendwas mit der LoNo Kommunikation aus dem Applet nicht läuft, weiß ich immer wo ich suchen muß.
Außerdem kann ich diese Klasse leicht testen und debuggen, ohne extra das Applet anschmeissen zu müssen.
Ein weiterer Vorteil ist, daß ich so leichter LotusNotes durch ein anderes Persistenz-Systeml wie RDBMS oder xml ersetzen kann.  (Persistenz ist dauerhaftes Abspeichern von Daten in ein Medium. Ein Programm erzeugt ja auch dauernd Daten, jedoch sind die futsch, wenn das Programm stoppt.)

... Martin Fowler hat mal sinngemäß gesagt: :
debuggen in nicht OO-Systemen besteht zeitmäßig 95% aus Fehlersuche und 5% aus Fehlerbehebung. OO ist auch dazu da, um diese 95% zu verringern.
« Letzte Änderung: 30.07.03 - 23:36:04 von Axel_Janssen »
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Hallo Axel!

Sei vorsichtig mit den was du da über die Servlets sagst, ich habe es probiert, und du kommst mit dem recyceln in Teufelsküche wenn du es so machst.  Ein einfaches Beispiel. Wir haben ein Servlet, dass im Hintergrund egal jetzt ob direkt oder über  einen Business Layer  auf ein und das selbe Notesdokument zugreift. Sprich nach jedem Webzugriff wird das Dokument recycelt. Session und Database bleiben bestehen. Das funktioniert super solange du ein Servlet mit nur einem Thread hast. Aber sobald die Last am Server steigt werden vom Application Server mehr Threads für das Servlet generiert. Thread1 holt das Dokument z.B aus einer View. Thread2 macht kurz darauf das selbe und bekommt exakt das selbe Objekt. Thread1 ist fertig und recycelt das Objekt. Thread 2 crasht dann wenn er auf das Objekt zugreifen will, da es ja bereits recycelt ist. Ausserdem ist  der Performancegewinn im wirklichen Leben nicht so schlimm. Wenn du Zeit hast teste mal unsere Webseite www.artweger.at Sie ist komplett mit JSP aufgebaut, die sämtliche Daten aus einer Domino Datenbank zieht. Das heisst es gibt kein Bild und keinen Text, der nicht im Hintergrund von Domino kommt. Ausnahme manche Daten werden direkt aus dem ERP System besorgt. Wenn ich lokal auf die Seiten zugreife, habe ich Seitenaufbauzeiten von unter 1 Sekunde.  Bei Zugriffen über das Netz ist die Zeit die für das Erstellen der Session und der Database benötigt wird minimal im Vergleich wie lange das Übertragen der Bilder dauert.

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Hallo Ralf,

d.h. du erzeugst bei jedem Servlet-Zugriff ein neues (Notes-)Session und ein neues (Notes-)Database-Objekt (sowie neue View Objekte, Collections, Docs, etc)?

D.h. das bei Servlets Domino-Objekt-Caching über mehrere Zugriffe nicht möglich ist? Warum auch immer.
Ist es dann vielleicht nicht doch sinnvoller evtl. drüber nachzudenken, ob die Corba-Klassen nicht doch der sinnvollere Weg sind? Da ist das nämlich möglich. Müßte man sich natürlich in der realen Umgebung messen und ich habe auch grundsätzlich Performance-mässige Bedenken bzgl. aller Remote-Frameworks (EJB, WebServices, CORBA).

Gruß Axel
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Thread1 holt das Dokument z.B aus einer View. Thread2 macht kurz darauf das selbe und bekommt exakt das selbe Objekt. Thread1 ist fertig und recycelt das Objekt. Thread 2 crasht dann wenn er auf das Objekt zugreifen will, da es ja bereits recycelt ist.

Hallo Ralf,

"exakt das selbe Objekt" stimmt mich nachdenklich. Das ist möglicherweise der Punkt. Die Documents sind vermutlich als Collection im Database-Object. Das Database-Objekt ist ja - wie man an den Initialisierungszeiten-Messungen sieht - ein sehr großes Objekt-. Wenn jetzt -wie es meine Idee war - das Database-Object zwischen verschiedenen (User-)Threads in doPost() und doGet() geshared wird, dann wird das wahrscheinlich die Ursache sein.

In Single-User Swing Anwendungen tritt diese Situation einfach nicht auf. Da kann das Database-Objekt von verschiedenen Aufrufen geshared werden.
Meine Swing-App funktioniert ja so:
+ Initialisierung:
-> hole Session, Database, View. Speichere diese in Instanzvariablen.
+ Aufruf 1: hole Collection, hole Documents, recycle Collection
+ Aufruf 2: hole Collection, hole Documents, recycle Collection.
+ [...]
+ Aufruf 2: hole Collection, hole Documents, recycle Collection.
-> recycle Session (und damit alles andere)

Das ist sauber.
Bei Multi-User Servlets greifen aber mehrere User synchron auf die gleichen Document-Objekte zu, wenn das Database-Objekt geshared wird.
Wird das Database bei jedem User-Thread (doXXX) neu erzeugt, wird nicht auf den gleichen Document-Objects gearbeitet, bei gesharter Database aber schon.

hoffe ich habe mich einigermaßen klar ausgedrückt

Gruß Axel
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Die Performance des direkten Zugriffs verglichen mit dem Corba Zugriff ist trotz des Caching der Session und des Database Objekts viel besser. Habe es anhand unserer Homepage überprüft. Zumindest auf unserer Maschine ist Corba sehr langsam. Wenn du zu anderen Ergebnissen kommst, wäre ich natürlich sehr daran interessiert.


Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Objekte, die über die gleiche NotesSession geholt werden, sind in der Tat identisch. Objekte, die über verschiedene NotesSessions geholt werden nicht.
Hier ist der Beweis:

Code
/*
 * ExploreNotesObjectSharing.java
 *
 * Created on 31. Juli 2003, 09:38
 */

package de.aja.db;

import lotus.domino.*;
/**
 *
 * @author  Axel
 */
public class ExploreNotesObjectSharing {
    
    /** Creates a new instance of ExploreNotesObjectSharing */
    public ExploreNotesObjectSharing() {
    }
    
    public static void main (String [] args) {
            
            NotesThread.sinitThread();
            // shared Objects. 
            try {
            // 1. Shared View
            Session nSessionShared = NotesFactory.createSessionWithFullAccess("kennwort"); 
            Database nDbShared = nSessionShared.getDatabase ("localhost", "test.nsf");
            View nViewShared = nDbShared.getView("V_MP");
            Document docSharedA = nViewShared.getFirstDocument();
            Document docSharedB = nViewShared.getFirstDocument(); 
           
            System.out.println("shared view");
            System.out.println("docSharedA.equals(docSharedB))"+ docSharedA.equals (docSharedB) );
            System.out.println("docSharedA.hashCode()" + docSharedA.hashCode());
            System.out.println("docSharedB.hashCode()" + docSharedB.hashCode());
            
            // 2. 1 level up: Shared Database
            View nViewSharedB = nDbShared.getView("V_MP");
            Document docSharedC = nViewSharedB.getFirstDocument();
            System.out.println("shared Database");
            System.out.println("docSharedA.equals(docSharedC))"+ docSharedA.equals (docSharedC) );
            System.out.println("docSharedA.hashCode()" + docSharedA.hashCode());
            System.out.println("docSharedC.hashCode()" + docSharedC.hashCode());
            
            // 3. 1 level up: Shared Session
            
            Database nDbSharedB = nSessionShared.getDatabase ("localhost", "test.nsf");
            View nViewSharedC = nDbShared.getView("V_MP");
            Document docSharedD = nViewSharedC.getFirstDocument();
            System.out.println("shared Session");
            System.out.println("docSharedA.equals(docSharedD))"+ docSharedA.equals (docSharedD) );
            System.out.println("docSharedA.hashCode()" + docSharedA.hashCode());
            System.out.println("docSharedD.hashCode()" + docSharedD.hashCode());
            
            
            // 4. Share nothing
           Session nSessionNonSharedA = NotesFactory.createSessionWithFullAccess("kennwort"); 
            Database nDbNonSharedA = nSessionNonSharedA.getDatabase ("localhost", "test.nsf");
            View nViewNonSharedA = nDbNonSharedA.getView("V_MP");
            Document docNonSharedA = nViewNonSharedA.getFirstDocument();
            
            Session nSessionNonSharedB = NotesFactory.createSessionWithFullAccess("kennwort"); 
            Database nDbNonSharedB = nSessionNonSharedB.getDatabase ("localhost", "test.nsf");
            View nViewNonSharedB = nDbNonSharedB.getView("V_MP");
            Document docNonSharedB = nViewNonSharedB.getFirstDocument();
            
            System.out.println("Share nothing");
            System.out.println("docNonSharedA.equals(docNonSharedB))"+ docNonSharedA.equals (docNonSharedB) );
            System.out.println("docNonSharedA.hashCode()" + docNonSharedA.hashCode());
            System.out.println("docNonSharedB.hashCode()" + docNonSharedB.hashCode());
            nSessionShared.recycle();
            nSessionNonSharedA.recycle();
            nSessionNonSharedB.recycle();
            
            } catch (Exception e) {e.printStackTrace(); }
            NotesThread.sinitThread();
        
    }
    
}

output:
Code
shared view
docSharedA.equals(docSharedB))true
docSharedA.hashCode()27379847
docSharedB.hashCode()27379847
shared Database
docSharedA.equals(docSharedC))true
docSharedA.hashCode()27379847
docSharedC.hashCode()27379847
shared Session
docSharedA.equals(docSharedD))true
docSharedA.hashCode()27379847
docSharedD.hashCode()27379847
Share nothing
docNonSharedA.equals(docNonSharedB))false
docNonSharedA.hashCode()7615385
docNonSharedB.hashCode()15184449
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz