Möglichkeiten für MultiSession mit Tomcat (Parallele Nutzung der WebApp)

tobyG

Grünschnabel
Hallo

welche Möglichkeiten habe ich mehrere Sessions zu bekommen wenn ich Parallel die gleiche Web-Anwendung mit einer eigenen Session verwenden muss/möchte.

Werden 2 Browser verwendet, so funktioniert dies.

Aktuell ist jede Session über alle Browserfenster verfügbar/einheitlich.

Konzepte:
* Dies kann man durch unterschiedliche URL lösen -> jedoch ist die Basis URL nicht immer identisch.
* SubDomain verwenden
* ....

Bisher habe ich noch kein Glück bei der Umsetzung.
Kann wer helfen, Tipps geben, Code Snippets?

Verwendet wird Tomcat 6/7, Java 1.6+ und Servlets und GWT

Auch allgemeine Tipps wäre gut.

danke
gruß
 

chriweis

Grünschnabel
Sessions basieren in der Regel auf Cookies. Das funktionieren so, dass der Browser automatisch für deine Seite (den Host) eine Session-ID verwaltet und die immer bei jedem Request an den Host als HTTP-Header mit schickt. Der Browser verwaltet aber nur eine Session-ID je Host, also kannst du keine zwei Sessions von einem Browser aus haben. Soweit so bekannt.
Was du machen willst ist vermutlich, die Session-IDs anders zu verwalten. Also zum Beispiel eine Session-ID pro Tab.
Wenn du (Browser-übergreifend) mehrere "Sessions" erlauben möchtest, sind Cookies als Session-Diskriminatoren also ungeeignet.

Du musst dem Server auf anderem Wege eine Session-ID zukommen lassen. Das geht zum Beispiel per HTTP-Header (wie bei den Cookies). Mit GWT kannst du AFAIR bei Requests eigene Header setzen. Wenn du das konsequent machst, kannst du damit eigene Session-IDs realisieren.
Eine andere Möglichkeit ist es, die Session-ID per Parameter zu übergeben. Ist in GWT auch einfach.

Probleme gibt es dann auf der Serverseite. Tomcat "schenkt" dir ja einen bequemen, sorgenfreien Session-Mechanismus. Der basiert aber auf der Session-ID aus dem HTTP-Header (der von dem Cookie), den kannst du also nicht verwenden (ohne böse zu hacken). Das gilt allerdings nur für den Standard-Session-Manager. Du kannst bei Tomcat nämlich auch einen eigenen Session-Manager erstellen und konfigurieren. Der könnte dann deine HTTP-Header auswerten oder andere Request-Parameter.
Um das bequeme Session-Management weiter zu verwenden und volle Kompatibilität mit anderen Web-Frameworks zu erreichen wäre das wohl der beste Weg. Damit bindest du dich aber an Tomcat oder irgendeine Runtime, bei der du eigene Session-Manager erstellen kannst. Nicht schön.

Fazit: Schöne Möglichkeiten für mehrere Sessions aus einem Browser per Cookies gibt es nicht. Dafür war das Session-per-Cookie-Konzept nie gedacht (Problem liegt an den Cookies). Es gibt einige Frameworks, die das eigenständig zu realisieren versuchen. Lustig ist aber, dass Tomcat so einen Framework aber eigentlich schon eingebaut hat - siehe den folgenden Tipp.

Tipp: Versuch mal, bei deinem Tomcat Session-Handling die Nutzung von Cookies zu deaktivieren. Damit zwingst du dich dazu, das Session-Handling per Parameter, also per URL-Rewriting zu realisieren. Radikal, aber wirksam. Du musst dazu die Session-ID an deinen GWT-Client übertragen und dort bei jedem Aufruf als Parameter anhängen.
Dazu den kurzen Beitrag hier: http://www.oreillynet.com/onjava/blog/2007/02/gwt_tip_no_cookies_support.html
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

ich schließe mich der Meinung von chriweis an
- "Schöne Möglichkeiten für mehrere Sessions aus einem Browser per Cookies gibt es nicht. "
:)

Eine konkrete Variante, die AFAIK, ganz passabel funktioniert ist innerhalb der HTTP Session eine weitere "logische" Session zu definieren - sprich du bastelst dir, wie chriweis bereits angedeutet hat, eine weitere Verwaltungsschicht über die HTTP Session.

Dazu musst du in der Lage sein Requests aus den verschiedenen Browser-Tabs voneinander zu unterscheiden. Dazu bietet es sich an in die Seite für jeden Browser-Tab eine UUID zu generieren.
Diese gilt dann als Identifier für den entsprechenden Tab und wird dann bei jedem Request aus einem
Tab mitgeschickt. Auf dem Server kannst du nun innerhalb der einen HTTP Session unterschiedlichen Zustand zu den einzelnen Browser Tabs ablegen.

Auf dieser Basis lässt sich der von dir angedeutete use case realisieren.

Siehe auch:
http://www.laliluna.de/articles/ideas/window-id-concept.html

Doch Vorsicht: Diese Art von Ansätzen bricht jedoch mit den Konzepten, welche die Anwender aus dem Web gewohnt sind - das kann dann auch mal zu Verwirrung führen... -> Beispiel logout: Meldet der Benutzer sich aus allen Tabs dann ab oder nur aus dem einen wo er auf loggout geklickt hat?
Desweiteren haben einige Web-Frameworks Probleme mit diesem Konzept - hier muss man dann ggf. ein paar Erweiterungen einbauen.

Tipp: Versuch mal, bei deinem Tomcat Session-Handling die Nutzung von Cookies zu deaktivieren.
Damit zwingst du dich dazu, das Session-Handling per Parameter, also per URL-Rewriting zu realisieren. Radikal, aber wirksam. Du musst dazu die Session-ID an deinen GWT-Client übertragen und dort bei jedem Aufruf als Parameter anhängen.
Der Tipp ist nicht schlecht :) - bringt aber dann auch den Aufwand mit sich, dass alle URLs (auch die von der Anwendung generierten) der Anwendung explizit mit einem Session Id-Parameter annotiert werden müssen (was je nach gegebener Anwendungsarchitektur mehr oder weniger aufwändiger ist ;-) )

Gruß Tom
 

chriweis

Grünschnabel
Der Tipp mit dem Session-Handling über dem Session-Handling "Huckepack-Sessions" ist das, was man dann manchmal als Frameworks im Netz findet.
Dabei wird eine "HTTP-Session" für die Abbildung mehrerer "User-Sessions" verwendet. Man muss aber die Trennung der "User-Sessions" selbst verwalten und Sessions können sich gegenseitig sehr einfach beeinflussen; das Logout per HttpSession#inalidate() ist zum Beispiel keine gute Idee mehr ;-)

Bei diesen Huckepack-Sessions sollte man auf der UI-Seite immer einen Parameter mit schicken und muss auf der Server-Seite immer schön aufpassen, dass man in der momentanen "User-Session" nicht in andere "User-Session" rein pfuscht.

Beim Ausschalten der Cookies muss man auf der UI-Seite den Parameter mit schicken. Die Trennung der Sessions übernimmt dann wieder der Servlet-Container. Dabei ändert sich insbesondere dein bisheriges Session-Management nicht. Du musst nur an der UI-Seite alle Aufrufe anpassen. In den Servlets musst du nur dafür sorgen, dass deine GWT-App die Session-ID übergeben bekommt; dafür musst du dir beispielsweise per HttpServletRequest#getSession() die Session holen und dort per HttpSession#getId() die ID ermitteln, die sollte dann irgendwie zum GWT-Client.

Beide Möglichkeiten sind gangbare Alternativen. Ich favorisiere bei solchen Entscheidungen immer die Nutzung von Standards und fokussiere die "Usability of Code"; mit dem Ausschalten der Cookies nutzt du die Standard-Mechanismen des Servlet-Containers zur Session-Integrity ohne Cookies (üblicher Weise per URL-Rewriting) und Server-Seitig bleibt dein Code zur Session-Verwaltung gleich.
Insbesondere die Kompatiblität mit anderen Web-Frameworks bleibt absolut gewahrt.

Fazit: Es kommt darauf an, was du mit den mehreren Session erreichen willst. Wenn der gleiche Benutzer angemeldet sein soll, aber mit unterschiedlichen Workflows, dann sind Huckepack-Sessions ein probates Mittel. Wenn der Benutzer mit unterschiedlichen Rechten arbeiten soll, sollte auch eine strikte Trennung der Rechte durch eigene HttpSessions erfolgen, also sollten die Cookies deaktiviert werden.
 

tobyG

Grünschnabel
Hallo

erstmal danke für die schnellen und ausführlichen Antworten.

Erstmal zu den genauen Anforderungen, Hürden usw.

Es ist kein Portal an dem es ein Login/Logout gibt, daher entfällt das Problem.
Es handelt sich um eine Anwendung die im Webbrowser arbeitet und parallel mehrere Instanzen/Vorgänge erlauben und unabhängig voneinander handeln soll. (Dies war in dotNet bereits so)

Dabei kommen zu Beginn Servlets und dann GWT/GXT zum Einsatz. Die gleiche Webanwendung kann auch ein Word öffnen, in diesem WebDialoge aufgerufen werden, welche im gleichen Context/Server-Session arbeiten müssen.
Ein Dialog kann aber auch einen weiteren Dialog/Popup öffnet, welcher im gleichen Context arbeiten muss.

An Servlet Containern werden alle großen unterstützt, wie Tomcat, WebSphere, WebLogic,...

Daher gehe ich davon aus, hier einen eigenen Session Manager zu schreiben viel zu Aufwendig und fehleranfällig ist. Da hier bei jedem Versionswechsel/Update der Hersteller eine potentieller Fehler lauern kann. Falls bei jedem überhaupt eigene Session Manager implementierbar wären.

Welche Lösung würde es für das Szenario geben? Und wie könnte man die am Besten mit GWT/GXT umsetzen, so dass der Code am Wenigsten zu verändern ist und wartbar bleibt?
Ich denke die Lösung mit der ID durchschleifen wäre die Lösung. Aber aktuell frage ich mich, wie man das am elegantesten macht, da ich vermeiden möchte jede Schnittstelle anzupassen.

Code Snippets oder direkte Klassennamen wären auch hilfreich, dass ich hierzu googlen kann. Oder gibt es ein GWT Sample Projekt wo man anschauen kann?

danke
gruß