Nur ein Tab / Browser in einer JEE / JSF Server Sitzung


Nur ein Tab / Browser in einer Server Sitzung Ein häufiges Problem in webbasierten Serveranwendungen ist es, dass nicht geklärt werden kann, ob der Nutzer mehrere Tabs geöffnet hat und ggf. die Sitzungsdaten eines Vorgangs mit mehreren Tabs gleichzeitig verändert. Beim Zugriff von verschiedenen Browsern oder im privaten Fenster sind die Sitzungen auf dem Server getrennt und es kann mit Sperren auf den Businesobjekten gearbeitet werden. Um sicher zu gehen, dass ein Nutzer nicht mit mehreren Fenstern / Tabs in einer Sitzung arbeitet, muss Java Script zur Hilfe genommen werden. In Kombination mit den Remote Commands von JSF / Primefaces hat man das Handwerkszeug, um sicherzustellen, dass der Nutzer nur einen Tab je Sitzung verwendet. Um dies zu realisieren, werden zwei Attribute in einer JSF Session Bean benötigt. Das eine Attribut ist eine eindeutige Nummer für den aktuell gültigen Tab. Das andere ein Flag, dass Kennzeichnet, ob der Tab geschlossen wurde. Da bei einem Reload einer Seite der Tab geschlossen (unload) wird und danach sich direkt wierder öffnet, ist ein Java Skript Listener für „beforeunload“ nicht ausreichend. Das Vorgehen: Beim Erzeugen des Tabs wird eine eindeutige Nummer erzeugt und im „sessionStorage“ des Browser abgelegt.

function defineTabId() {
    var iSessionTabId = sessionStorage.getItem("onlyOneTabId");
    if (iSessionTabId == null) {
        iSessionTabId = Math.floor(Math.random() * 1000000);
        sessionStorage.setItem("onlyOneTabId", iSessionTabId);
    } 
    console.log("iSessionTabId: " + sessionStorage.getItem("onlyOneTabId"));
}

Des Weiteren wird diese Nummer an den Server über ein Remote Command übermittelt (in onload der Seite). Wenn für die Sitzung noch kein Tab übergeben wurde, wird die Nummer gespeichert und der Request ist OK. Entspricht die Nummer der aktuellen Nummer ist der Request ebenfalls. Nur bei Abweichungen wird über einen Redirect zu einer Fehlerseite gesprungen. Für das Schließen von Fenstern wird eine JavaScript Funktion registriert (window.addEventListener(‘beforeunload’ …) die wiederum ein Remote Command aufruft, das der Serversitzung mitteilt, dass der Tab geschlossen wurde.

window.addEventListener('beforeunload', function () {    
    call the remote command here
    // Cancel the event
    // e.preventDefault(); // If you prevent default behavior in Mozilla Firefox prompt will always be shown
    // kein return value, sonst zeigt Chrome immer ein PupUp
    // e.returnValue = null;
});

Das Schließen wird über ein Remote Command, das den Status im Server ändert, gesendet. Ist das geschlossen Flag auf dem Server für die Sitzung gesetzt, wird der nächste Request ohne Vergleich der Nummer zugelassen. Bei einem normalen Seitenwechsel, ist der Folgerequest im selben Tab und somit bleibt die ID unverändert. Wenn der Nutzer aber den Tab schließt und in einem zweiten Tab des gleichen Browser die Anwendung wieder startet, wird eine Nummer generiert. Somit wird das vom Nutzer erwartete Verhalten beim Schließen eines Tabs realisiert.

Anmerkung: Seit 2023 sollte man besser eine Lösung mit @ClientWindowScoped aus Jakarta 10 JF anstreben.

Du hast Fragen oder Anmerkungen? Kontakt: arndt@schoenb.de