Re: [Hbci4java-help] [Bug 84] Probleme, wenn Threads nicht selbst erzeugt werden (bei Tomcat etc .)
Brought to you by:
kleiner77
|
From: <ro...@we...> - 2009-02-24 13:00:55
|
> -----Ursprüngliche Nachricht----- > Von: "HBCI4Java (Stefan Palme)" <hbc...@ka...> > Gesendet: 18.02.09 00:02:15 > An: ro...@we... > CC: hbci4java-help <hbc...@li...> > Betreff: Re: [Bug 84] Probleme, wenn Threads nicht selbst erzeugt werden (bei Tomcat etc .) > Hi, > > > > ich antworte mal direkt per Mail, denn 'ne Diskussion im Bugzilla > > > halte ich nicht für soo sinnvoll :) > > > > Das ist Ansichtssache, im Bugtracker könnten evtl. auch andere > > mitdiskutieren, wie in einem Diskussionsforum. Fänd ich gar nicht so > > blöd. > > Aber ich bin da ganz flexibel :) > > Wenn überhaupt dann Mailing-Liste. Diskussionen im BugTracker werden > die wenigsten überhaupt wahrnehmen, wenn ein bestimmter Bug sie nicht > selbst betrifft :) Zunächst: Sorry für meine späte Antwort, aber meine letzten Tage waren ziemlich hektisch. Aber mittlerweile ist das Leben wieder unter Kontrolle :) > Ich starte mal ein CC an die Liste, die Diskussion begann bei > diesem Bug: > https://bugzilla.kapott.org/show_bug.cgi?id=84 Alles klar, ich hab mich mittlerweile auch in die Liste eingetragen. Ist vermutlich wirklich besser geeignet als der Bugtracker. Ich hatte die Liste noch gar nicht so mit Bewusstsein wahrgenommen ... > > Ansonsten muss ich gestehen, dass mir noch gar nicht in den Sinn > > gekommen ist, dass ein Anwendungsprogramm die Möglichkeit hat/haben > > könnte, eine eigene HBCIPassportFactory oder einen eigenen > > HBCIPassport zu implementieren. Mir ist derzeit auch nicht klar, warum > > bzw. wann das nötig sein sollte, aber vielleicht gibt es derartige > > Situationen. > > Diese Erweiterbarkeit ist eines der am häufigsten verwendeten > "Special-Features" von HBCI4Java. > > [...] > > Mit etwas Fleiß könnte ich eine ganze Menge derartiger Beispiele > aufzählen, was der Grund dafür ist, dass ich bestimmte Features > von HBCI4Java auch weiterhin nicht fest in der Lib verdrahten will, > sondern über einen Factory- oder Plugin-Mechanismus dynamisch > erweiterbar halten will. Achso. Das ist gut zu wissen. Ich hätte nicht damit gerechnet, dass die entsprechenden Erweiterungsmöglichkeiten tatsächlich so rege eingesetzt werden, jetzt leuchtet mir auch ein, warum der Erweiterbarkeit an dieser Stelle so viel Aufmerksamkeit zuteil wird. Evtl. wäre ein Dokument nützlich, dass genau das beschreibt, was du hier in dieser Mail beschreiben hast. Dann versteht man besser, warum alles so ist, wie es ist. Es gibt zwar schon viel und auch gut verständliche Doku, aber die beschreibt eigentlich nie, warum die Architektur der Library so ist, wie sie ist, und wie es dazu gekommen ist. > Ich gebe Dir natürlich insofern Recht, dass solche Sachen wie > die HBCI-Datentypen (numerisch, alphanumerisch, binary, ...) > nicht über eine von außen erweiterbare Factory instanziiert werden > müssen, denn wenn das notwendig wäre, würde man mit eigenen > Implementierungen wohl mehr Schaden anrichten als alles andere > (im Moment wäre aber sogar das möglich - aber das ist nur ein > Nebeneffekt des Software-Designs an dieser Stelle und keine "Absicht"). Klar, das ergibt sich aus dem Design quasi von alleine. > > Ich hatte mir das ganze bisher eher so vorgestellt, dass alle > > Factories, Passports, der Kernel etc. von HBCI4Java bereitgestellt > > werden, und vom Anwendungsprogramm nur > > konfiguriert/instantiiert/benutzt werden. > > Das scheint mir auch ausreichend zu sein, wenn mit den vorhandenen > > HBCI4Java-Klassen der HBCI-Standard abgedeckt wird. Falls jemand noch > > Lücken entdeckt, also etwas, was HBCI4Java können sollte, aber nicht > > kann, wäre es vermutlich besser, um eine Aufnahme des zusätzlichen > > Codes in das offizielle HBCI4Java-Repository zu bitten, anstatt im > > Anwendungsprogramm Teile der HBCI-Implementierung unterzubringen. > > Natürlich. Bei den Möglichkeiten zur Erweiterbarkeit ging es primär > auch nicht darum, HBCI4Java tatsächlich um HBCI-Funktionalitäten > erweitern zu können. Allerdings gebe ich zu, dass ich ursprünglich die > Vorstellung hatte, dass ich mit HBCI4Java nur das Framework und > einige Basis-GVs liefere und die oft zitierte "Community" z.B. weitere > Implementierungen von Geschäftsvorfällen beisteuert. > > Technisch wäre das bis zu einem gewissen Zeitpunkt möglich gewesen, > allerdings hatte wohl gerade niemand Zeit, sich damit zu > beschäftigen ;-) > > Diese "Erweiterungen" sollten auch nicht verstanden werden als > "im Anwendungsprogramm Teile der HBCI-Implementierung unterzubringen", > sondern vielmehr tatsächlich als "Aufsatz" auf HBCI4Java, der z.B. > Unterstützung für weitere Geschäftsvorfälle, alternative Speicher- > Medien für Passports (Datenbanken, RPC-Services...) usw. liefern. Achso. Das heißt dann also, dass man eine Kapselung hat, die man so beschreiben könnte: User <-> Anwendungsprogramm <-> HBCI4Java-Aufsatz <-> HBCI4Java <-> Banksysteme Warum auch nicht, ich würde nur behaupten, dass es immer eine Trennung zwischen dem Anwendungsprogramm und dem HBCI4Java-Aufsatz geben sollte. Dann wären die Verantwortlichkeiten weiterhin klar definiert. > (Ich vermute, dass z.B. in Hibiscus einige HBCI4Java-Klassen und/oder > -Methoden überschrieben wurden, um spezielle Funktionalitäten > einzubringen...) > > > ... > > Wenn man diese Kapselung so einhalten würde, bräuchte man -wenn ich > > das richtig verstanden habe- gar keine Factory, man könnte Objekte der > > einzelnen Klassen einfach normal instantiieren und nutzen. > > Das hätte aber genau den Nachteil, dass die HBCI4Java-Bibliothek > nur die Klassen benutzen kann, von denen sie zur Entwicklungszeit > bereits weiß. Sprich: eigene Passport-Speicher-Implementierungen, > eigene Hilfsklassen für Geschäftsvorfälle usw. wären nicht mehr > möglich. Nun, man müsste dann halt die HBCI4Java-Bibliothek selbst kompilieren, damit diese zur Compilezeit alle zusätzlichen Klassen kennen. Sollte meiner Meinung nach auch kein Problem darstellen, aber ich weiß nicht, ob die Autoren der vorhandenen Erweiterungen das auch so sehen. Ich persönlich sehe es nicht also sonderlich großes Problem an, zumal ja viele Entwicklungsumgebungen wie Eclipse auch mehrere Projekte gleichzeitig verwalten können. In dem Fall wäre es evtl. auch einfacher, die entstandenen Klassen HBCI4Java selbst zukommen zu lassen (damit auch andere was davon haben). Aber evtl. hätte das Nachteile, die mir noch nicht klar sind. > > Ganz grob so in diesem Stil: > > [pseudocode] > > // Pro Thread, vor der ersten Kommunikation mit der Bank > > HBCICore core = new HBCICore(locale, loglevel, shadelevel, callback, > > options); > > HBCIPassport passport = new HBCIPassport(passporttype, > > passportFilename); > > HBCIHandler handler = new HBCIHandler(core, passport, hbciVersion); > > // core, passport und handler sind jetzt normale Instanzen der > > Klassen, die zerstört werden können > > > > // irgendwann ... (nur für den aktuellen Thread) > > handler.close(); > > passport.close(); // Passportdatei wird natürlich geschrieben und > > geschlossen > > core.close(); // Nur die eigene Instanz des Core > > core = null; // RAM freischaufeln > > passport = null; // RAM freischaufeln > > handler = null; // RAM freischaufeln > > [/pseudocode] > > Das Problem dabei sind z.B. Anwendungen, die in einem Application- > Server laufen und HBCI-PIN/TAN via iTAN oder einem anderen Zweischritt- > Verfahren machen. > > Denn dabei MUSS der HBCI-Dialog zunächst gestartet werden. WÄHREND > der Dialog-Ausführung wird vom HBCI-Server nach einer bestimmten TAN > gefragt - diese Frage muss an den Nutzer weitergereicht werden. > > Dabei entsteht also ein neues Response (mit der Rückfrage nach der > richtigen TAN) sowie ein neuer Request (mit dem der Nutzer die > TAN liefert). Der neue Request des Nutzers muss die gelieferte TAN > natürlich für den "alten" HBCI-Dialog verwenden, so dass man hier > eine Kopplung im Sinne von "Sessions" braucht. > > Und damit wird es schon nicht mehr so einfach wie es in > Deinem Pseudocode aussieht ;-) Hmm, man kann das noch weiterspinnen, indem der User sogar zunächst danach gefragt wird, welchen TAN-Typ er verwenden möchte (es kann ja mehrere geben), danach würde dann z. B. bei iTANs der TAN-Index abgerufen werden, etc. Oder der User kann sogar interaktiv arbeiten, mit weiteren Zwischenschritten. Halt je nachdem, was im spezifischen Fall genau gewünscht ist. Sollte aber meiner Meinung nach kein Problem sein, weil ja eine Sitzungsverwaltung in dem Szenario ohnehin notwendig ist. Der Application-Server muss also für den User eine Session erzeugen, daraufhin kann der User im Rahmen dieser Sitzung mit dem Server arbeiten, und der Server kann jede Anfrage jedes Benutzers einer Sitzung zuordnen. Dadurch kann der Server dann auch z. B. für einen konkreten User eine Kommunikation mit der Bank durchführen. Letztlich können ja die erzeugten Objekte so lange im Arbeitsspeicher verbleiben, wie die Session des Users existiert. Das würde ich aber nicht als Verantwortlichkeit der Library ansehen, sondern als Verantwortlichkeit der Anwendung, die die Library nutzt. Die Library sollte ja möglichst flexibel einsetzbar sein, wobei ich es am saubersten finden würde, wenn die Library selbst möglichst wenig State enthält, und die Anwendung sich darum kümmert. Wenn man das nicht so macht, müsste die Library ja quasi eine eigene Sitzungsverwaltung machen. Das hätte dann aber wieder den Nachteil, dass der Application-Server ja evtl. noch viel mehr bereitstellt, als nur die Funktionalität der HBCI-Libray, daher wird dieser typischerweise eine eigene Sitzungsverwaltung brauchen. Man müsste also eine Sitzung aus Sicht der Library mit einer Sitzung aus Sicht des Servers miteinander verknüpfen, und das scheint mir recht umständlich. Da wäre es doch einfacher, wenn der Server die Sitzung verwaltet und den State enthält, und die Library möglichst wenig State enthält. Dabei würde ich aber davon ausgehen, dass der Server für alle User und alle Threads den gleichen Code verwenden will, daher können die Factories wohl auf jeden Fall alle global sein. Falls es tatsächlich gewünscht sein sollte, dass nicht alle Features für alle User zur Verfügung stehen, könnte der Server ja entscheiden, welcher User was genau darf. Dies ist ganz sicher nicht Sache der Library. > > ... Ich denke aber nicht, dass man Factories pro Thread verwalten > > müsste, das dürfte wohl nichts bringen. > > Das denke ich allerdings auch. Der aktuelle HBCI4Java-3-Code ist auch > so ausgelegt, dass Factories tatsächlich "global" sind und nicht pro > Thread oder HBCI-Session differenziert werden können. Full ACK von mir :) > > Falls man wirklich zusätzliche Passports oder dergleichen benötigt, > > kann man diese ja beim Programmstart an der Library registrieren. > > Danach könnten diese für alle Threads zur Verfügung stehen, die diesen > > Typ benötigen. Da ja jeder Passport-Typ einen eindeutigen Namen haben > > muss, sind ja Verwechslungen ausgeschlossen. > > So ist der derzeitige Stand der Dinge. Nur dass keine zusätzlichen > Klassen "registriert" werden (in engerem Sinne). Statt dessen hat > eine Anwendung einfach die Möglichkeit, die von HBCI4Java verwendete > Factory durch eine eigene Factory-Implementierung zu ersetzen (siehe > mein vorheriges Mail mit dem Code-Beispiel). Ja, das meine ich eigentlich - hab mich etwas unglücklich ausgedrückt ... > > Aber was meiner Meinung nach pro Thread verwaltet werden sollte: > > -> Einstellungen, die direkt die Usability betreffen (z. B. die zu > > verwendende Sprache/Locale) > > ACK. > > > -> Alle Einstellungen zur Kommunikation mit der Bank (BLZ, Host, Port, > > Filter, UPD, BPD, unterstützte Securitymechanismen, etc.) > > Sowieso. Die Verwendung von globalen Variablen zur Konfiguration > von Passports war design-technisch ein grober Fehler, an den man sich > über die Jahre wohl gewöhnt hat :) > > > -> Callback-Objekte > > Hier wäre schon wieder die Frage, ob das tatsächlich notwendig ist. > Man könnte einerseits natürlich pro HBCI-Session individuelle > Callback-Objekte registrieren. > > Andererseite könnte man jedem Callback-Aufruf ja auch einfach einen > Parameter "HBCISession session" mitgeben, der sämtliche session- > relevanten Daten enthält, so dass auch EIN Callback-Objekt in > verschiedenen HBCI-Sessions unterschiedlich agieren könnte. Hmm, hier ist wieder die Frage, wie und wo der State verwaltet wird. Meine Meinung ist ja die, dass die Anwendung den State verwalten sollte, und diese würde natürlich gerne jedes Objekt, das im Rahmen einer Session mit einem Benutzer angelegt wird, später wieder zerstören (spätestens, wenn die Session abgelaufen ist). Hierbei wäre es natürlich schön, wenn auch das Callback-Objekt immer einer bestimmten Session zugeordnet wäre, dann könnte man auch dieses zerstören, sobald die Session abgelaufen ist. Außerdem ist es ja immer kritisch, wenn ein Objekt von mehreren Sessions gleichzeitig verwendet wird, denn dann muss man sich immer über Synchronisierung Gedanken machen. Wenn jedes Objekt im Arbeitsspeicher immer einer bestimmten Session zugeordnet ist, hat man damit schon mal keine Probleme. Außerdem können so mehrere Threads gleichzeitig arbeiten, ohne dass es Performanceengpässe geben kann. Wenn eine Methode "synchronized" ist, müssen ja die Threads aufeinander warten, die (evtl. vorhandenen) mehreren CPUs bzw. Kerne können somit nicht so gut ausgereizt werden. Auch für Anwendungen, mit denen immer nur ein Anwender arbeitet, wäre das kein Nachteil, denn letztlich können die Objekte (z. B. das Callback-Objekt) ja auch einfach so lange bestehen bleiben, bis das Programm beendet wird. Falls tatsächlich gewünscht, könnte eine Anwendung ja auch einfach für jede Sitzung immer wieder eine Referenz auf das gleiche Callback-Objekt übergeben, und so tatsächlich immer wieder dieses eine Callback-Objekt benutzen, das wäre ja weiterhin möglich (nur müsste natürlich jeder Callback die HBCISession als Parameter mitbekommen). Aber ich könnte mir vorstellen, dass das eigentlich kaum genutzt wird, getrennte Objekte scheinen mir so viel schöner ... > Zumindest ist das der gegenwärtige Stand der Entwicklung... > > > Allgemein gesprochen, halte ich es für "vergebliche Liebesmühe", > > HBCI4Java daraufhin zu optimieren, dass man es durch eigenen Code > > erweitern kann, der dann von HBCI4Java genutzt wird, dies ist > > vermutlich wenig relevant... > > Siehe Anfang mein Mail - da irrst Du Dich :) Ja, ist mir mittlerweile klar geworden :) > > In der Praxis dürfte es viel eher nützlich sein, wenn mehrere > > Transaktionen mit mehreren verschiedenen Banken exakt parallel laufen > > können, ohne dass die Gefahr besteht, dass diese sich gegenseitig > > stören oder beeinflussen. > > Das ist ebenfalls ein wichtiger Punkt, der in HBCI4Java-2 schon > einigermaßen gut unterstützt wurde, allerdings leider erst > "nachträglich", was zu diversen Kompromisslösungen geführt hat > (Du hast das bereits gut erkannt).. > > HBCI4Java-3 wird an dieser Stelle wohl etwas sauberer sein... Das halte ich für sehr lohnenswert, weil dadurch manche Szenarien besser unterstützt werden, und es eigentlich für niemanden Nachteile gibt. Gibt es eigentlich schon eine Art "Roadmap" für die 3er Version, oder ist noch nicht klar, wie lange es ganz grob noch dauern wird? > Viele Grüße > -stefan- Viele Grüße, Rolf |