
Verwendung von HBCI4Java in mehreren Threads
--------------------------------------------

Ab HBCI4Java 2.4.6 wurden einige interne Codeteile so geändert,
dass die Verwendung von HBCI4Java in mehreren Programm-Threads
besser (bzw. für einige Anwendungsfälle überhaupt erst) möglich ist.  
Dazu einige Anmerkungen:

Die folgenden Gedankengänge führten zum derzeitigen Design der
MultiThread-Schnittstellen in HBCI4Java. Falls jemand prinzipielle
Denkfehler entdeckt, die zu einem schlecht nutzbaren
MultiThread-Design führen, bzw. falls es Verbesserungsvorschläge/Wünsche
gibt, dann bitte einen entsprechenden Hinweis an mich senden.

Eine HBCI-Anwendung konnte natürlich auch bisher schon aus mehreren
Threads bestehen, solange immer nur *ein* Thread tatsächlich 
Funktionen von HBCI4Java benutzt hat. Neu ist die Möglichkeit,
in mehreren Threads gleichzeitig alle HBCI4Java-Funktionen zu benutzen
(also z.B. um Kontoauszüge mehrerer HBCI-Zugänge gleichzeitig
abzufragen). Mit dem Terminus "mehrere Threads" seien also mehrere
Threads gemeint, welche tatsächlich HBCI4Java-Funktionen ausführen.

Die HBCI4Java-Schnittstellen, die eine Anwendung tatsächlich benutzt,
lassen sich folgendermaßen unterteilen:

  * die HBCI-Kernel-Parameter, die mit HBCIUtils.{set,get}Param()
    gesetzt bzw. abgefragt werden können
  * HBCIPassport-Objekte
  * HBCIHandler-Objekte
  * HBCIJob-Objekte
  
Da ein HBCIPassport schon prinzipbedingt nicht gleichzeitig in 
mehreren Threads verwendet werden kann (für einen HBCI-Zugang
kann zu jedem Zeitpunkt nur genau *ein* HBCI-Dialog aktiv sein), ist für 
die Arbeit mit Passports (Abfrage von passport-internen Daten, 
Initialisieren von Passports usw.) keine separate Thread-Absicherung 
implementiert worden.

Analoges gilt für HBCIHandler, weil ein HBCIHandler-Objekt immer an
genau ein Passport-Objekt gekoppelt ist und somit auch nicht gleichzeitig
in mehreren Threads verwendet werden kann.

HBCIJob-Objekte werden durch Methoden des HBCIHandlers erzeugt und sind
(durch interne Datenstrukturen) ebenfalls an den jeweiligen HBCIHandler
(bzw. an das dazugehörige Passport) gebunden. Deshalb kann ein HBCIJob-
Objekt auch nur mit dem HBCIHandler-Objekt benutzt werden, mit dem es 
erzeugt wurde. Somit ist auch hier die gleichzeitige Verwendung eines 
HBCIJob-Objektes in mehreren Threads nicht möglich bzw. sinnvoll.

Die einzige(?) nach außen sichtbare Schnittstelle, die sich bisher nicht sauber
in mehreren Thread verwenden ließ, sind die Methoden zum Setzen und Auslesen
von HBCI-Kernel-Parametern (HBCIUtils.setParam() bzw. .getParam()). Die
Kernel-Parameter wurden bis jetzt in einer (aus Sicht von HBCI4Java) globalen
Datenstruktur verwaltet. Das wird natürlich problematisch, wenn HBCI4Java
in mehreren Threads verwendet wird und in jedem Thread eine andere 
Belegung der HBCI-Kernel-Parameter benötigt wird (z.B. beim Anlegen eines
Passport-Objektes, Setzen von unterschiedlichen Log-Levels pro Thread usw.).

Um kompatibel zur bisherigen Funktionalität zu bleiben (Single-Thread-Anwendungen
bzw. Anwendungen mit nur einem Thread, der tatsächlich HBCI4Java-Funktionen
aufruft) und um gleichzeitig eine bessere MultiThread-Unterstützung zu realisieren,
wurde folgendes umgesetzt:

Eine Anwendung, welche in mehreren Threads gleichzeitig HBCI4Java-Funktionen 
benutzen will, muss jeden dieser HBCI4Java-fähigen Threads in eine separate
ThreadGroup(!) einbetten. Der HBCI4Java-Kernel verwaltet alle relevanten 
Datenstrukturen so, dass es für jede ThreadGroup einen separaten Satz dieser 
Daten gibt (und nicht für jeden Thread!). Die Zuordnung der "richtigen" Daten
zum aktuellen Thread wird von HBCI4Java automatisch vorgenommen, als
Kriterium für die Auswahl der richtigen "Datenmenge" wird die ThreadGroup
des aktuellen Threads benutzt (Thread.currentThread().getThreadGroup()). 

"Alte" Anwendungen, die schon immer aus mehreren Threads bestanden,
wobei jedoch immer nur einer tatsächlich HBCI4Java-Funktionen aufgerufen hat,
haben i.d.R. alle Threads in der gleichen ThreadGroup eingebettet. Das hat
zur Folge, dass HBCI4Java in diesem Fall auch nur genau *einen* Satz Daten
(Kernel-Parameter und einige interne Datenstrukturen) verwaltet, was exakt
dem Verhalten des "alten" HBCI4Java (ohne explizite MultiThread-Unterstützung)
entspricht.

"Neue" Anwendungen, die tatsächlich mehrere HBCI4Java-Aktionen parallel ausführen
wollen, müssen dafür jeweils separate ThreadGroups anlegen. Im ersten Thread,
der in einer neuen ThreadGroup gestartet wird, muss HBCI4Java über die Existenz
dieser ThreadGroup informiert werden. Dazu muss die Methode HBCIUtils.initThread()
aufgerufen werden. 

In einer solchen ThreadGroup können beliebig viele Threads enthalten sein, wobei
aber zu jedem Zeitpunkt nur *einer* HBCI4Java-Funktionen benutzen darf. Das ist z.B.
dann sinnvoll, wenn es sich um eine Java-Swing-Anwendung handelt, bei der ein
Thread für die eigentliche Durchführung der HBCI-Aktionen und ein anderer für
die Aktualisierung des GUI zuständig ist.

Zur Zeit werden nur die HBCI-Kernel-Parameter sowie einige interne Datenstrukturen
ThreadGroup-weise getrennt. Neu ist, dass jetzt auch die Callback-Objekt für
jede ThreadGroup separat festgelegt werden können (aber nicht müssen).
Die Frage ist, ob es evtl. mehr Daten gibt, für die eine solche Trennung 
sinnvoll wäre. 

Für jegliche Anmerkungen/Fragen/Wünsche stehe ich wie immer zur Verfügung

-Stefan-
hbci4java@kapott.org
