Online Status eines Benutzers abrufen

Hallo,

ich möchte gerne in meine Applikation den Online Status eines Benutzers abrufen.
In der DB zu speichern macht nur bedingt Sinn, da:

a) User kann Browser schließen, ohne sich auszuloggen -> wie bekommt meine Applikation nun mit, dass der User offline ist?

Wie kann ich das realisieren?
 
wer 'a' sagt, muss auch 'b' sagen ;)


Regelmäßig den Client an den Server melden lassen, dass er noch online ist, zB mit Websockets oder regelmäßigen normalen Http-Requests.
Wenn er sich meldet ist er online, sonst offline
 
Ok, das kann ich machen. Das einzige Problem das ich sehe:
-User schließt den Browser. Wie bekomme ich das dann mit?
 
User schließt den Browser. Wie bekomme ich das dann mit?
Das Prinzip ist: wenn sich der User eine Zeit lang nicht meldet, bekommt der Server das mit. Du kannst natürlich clientseitig auch noch versuchen, über ein JS-Event einen entsprechenden Logout-Request abzusetzen. Verlassen würde ich mich darauf aber nicht.
 
Ja, solang der User den Browser auf hat, ist das kein Problem.

Bzgl. dem Session Listener: wie mache ich hier eine Verbindung zum User Objekt selbst?
Klar könnte ich die Session ID dem User Objekt hinzufügen und sobald der Session Listener in die expired Methode geht, sucht er die Session Id bei einem User...

Aber:
- Session ID ist nicht aufsteigend, sodass theoretisch mehrere User die gleiche Session haben können
- User könnte sich mehrmals gleichzeitig in verschiedenen Browser einloggen und ich hätte kein 1:1 Mapping zum User mehr...

irgendwelche Ideen?
 
Ja, solang der User den Browser auf hat, ist das kein Problem.
Und wenn der User den Browser nicht auf hat, ist das auch kein Problem. Dann nämlich tut er sich schwer, sich beim Server zu melden.

Klar könnte ich die Session ID dem User Objekt hinzufügen
Wozu?!?

In dem Beispiel unter http://programmersought.com/article/724060146/ wird einfach der Benutzername als Attribut der Session gespeichert und einer Liste (im application scope) hinzugefügt bzw. von dieser entfernt.

Wenn Du mehrere Sessions parallel verwalten willst, brauchst Du lediglich statt einer Liste z. B. eine Map<String,Integer> zu verwenden, die die Anzahl Sessions mitzählt. Beim Anmelden wird der Eintrag mit einem Zähler von 1 eingerichtet bzw. der Zähler erhöht, beim Abmelden wird der Zähler verringert und, wenn er 0 erreicht hat, der Eintrag entfernt.
 
Ok, danke....

Aber wo und wann setze ich das:
Code:
String username = (String) session.getAttribute("username");// Remove the username from the online list
List onlineUserList = (List) application.getAttribut("onlineUserList");
 
Habe den Code mal testweise bei mir probiert.... Bekomme aber einen Compiler Fehler:
Warum? Wie kann ich das fixen?

Müsste das nicht:
List onlineUserList = (List) application.getAttribute("onlineUserList");

heißen?

12754
 
Habe nochmal ein paar Fragen:
1)
- Wie kann ich den Status erst setzen (sessionCreated Methode) ausführen, wenn der User sich einloggt?
-> Derzeit wird sessionCreated ja bereits ausgeführt, sobald der User die Webpage öffnet...

2) Ebenfalls möchte ich die destroy Methode ausführen, sobald der User sich ausloggt...
 
1) Genau - eine SessionBean habe ich bereits.... Das heißt aber, dass ich den Status in meiner Datenbank setze, sodass auch andere Clients übergreifend den Status sehen können, korrekt? Wenn ich den Status nur in der SessionBean setze, dann sieht ja nur der eingeloggte User den Status?
 
Was willst Du denn ständig mit Deiner DB? Ob wer online ist oder nicht, ist doch kein persistenter Zustand.

In Deiner SessionBean setzt Du einfach das Attribut username:
Java:
ExternalContext ec = FacesContext.getCurrentInstace().getExternalContext();
Principal principal = ec.getUserPrincipal();
if (principal != null) {
    HttpSession session = (HttpSession) ec.getSession(false);
    if (session != null) {
        session.setAttribute("username", principal.getName());
    }
}
Der HttpSessionBindingListener wird über diese Änderung informiert, holt sich über das Session-Attribut username den Benutzernamen und legt diesen in die anwendungsweit gültige Liste der Online-Benutzer (bzw. die Map mit Zähler).

Die sessionDestroyed-Methode des HttpSessionListeners wird beim Abmelden (oder Timeout) automatisch aufgerufen.
 
ok, danke...
Aber brauche ich zwingend Principal?

In:
session.setAttribute("username", MYVALUE);

-> In MYVALUE könnte ja auch einfach die ID von meinem User - Objekt dann stehen, oder?
 
danke....

Habe nochmal eine weitere Frage:
Nun würde ich den Online Status gerne in meiner JSF Seite abrufen....
Wie kann ich das machen?

1) Frage
Stelle mir sowas vor:
-> Wie fülle ich aber "event"
Java:
    public boolean checkOnlineStatus(ChatUser chatUser) {

        HttpSession session = event.getSession();

        // Get the login username
        ServletContext application = session.getServletContext();

        List onlineUserList = (List) application.getAttribute("onlineUserList");

        if (onlineUserList.contains(chatUser.getId()))
            return true;

        else

            return false;
    }
2) Frage
Ich will nicht nur true oder false zurückgeben. Ich möchte mind.
- Online
- Abwesend
- Offline

Wie kann ich das machen?
Könnte mir dann sowas vorstellen:
Java:
    public String checkOnlineStatus(ChatUser chatUser) {

        HttpSession session = event.getSession();

        // Get the login username
        ServletContext application = session.getServletContext();

        List onlineUserList = (List) application.getAttribute("onlineUserList");

        if (onlineUserList.contains(chatUser.getId())){

// Prüfen wann Client zuletzt aktiv war? Wie kann ich das prüfen?
// Wenn kleiner 5 min
 return "ONLINE",
else 
return "AWAY";
}
       
        else
return "OFFLINE";

            return false;
    }
Irgendeine Idee?
 
Wie fülle ich aber "event"
Gar nicht. Du kommst an die Liste über den FacesContext (bzw. ExternalContext) ran:
Java:
ExternalContext ec = FacesContext.getCurrentInstace().getExternalContext();
List onlineUserList = (List) ec.getApplicationMap().get("onlineUserList");
Wie kann ich das machen?
Erstens kannst Du in den Application Scope nicht nur Strings sondern auch andere (serialisierbare) Objekte ablegen. Im einfachsten Fall könntest Du statt einer List eine Map<String, Instant> verwenden, die einen Benutzernamen auf einen Zeitstempel abbildet, der den Zeipunkt der letzten Aktivität angibt. Bei jeder (relevanten) Aktivität musst Du dann den Zeitstempel aktualisieren. Damit kannst Du feststellen, wie lange die letzte Aktivität her war.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben