B4J Code Snippet [Server][WebSockets][WebApp] Browser Window Session Store

This is a code helper. It can be used to identify the browser window/tab and/or store attributes in session referencing that window/tab.

This can be helpful if you users use your app with multiple tabs opened in one browser (because multiple tabs in the same browser share the same session).

Place the code from below into a Standard Class (eg. BrowserWindowSessionStore):
B4X:
'Browser Window Session Store Class module
Sub Class_Globals
    Private bwWebSocket As WebSocket
    Private bwId As String
End Sub

'Initializes the Browser Window Session Store.
'If the browser window has an Id set it get that one otherwise it will generate a new id and set it in the browser window too.
Public Sub Initialize(WebSocketObject As WebSocket)
    bwWebSocket = WebSocketObject
    bwId = GetBrowserWindowId
    If bwId.Length = 0 Then
        bwId = GenerateId 
        SetBrowserWindowId
    End If
End Sub

'Initializes the Browser Window Session Store with a specific id and set in the browser window too.
Public Sub Initialize2(WebSocketObject As WebSocket, Id As String)
    bwWebSocket = WebSocketObject
    bwId = Id
    SetBrowserWindowId
End Sub

'Generates an unique identifier
Private Sub GenerateId() As String 'ignore
' If you want to use and UUID then uncomment the 2 lines from below. It makes use of JavaObject library
'    Dim jo As JavaObject
'    Return jo.InitializeStatic("java.util.UUID").RunMethod("randomUUID", Null)

' If you use UUID (from above) then comment out the line below.
    Return Rnd(10, 99) & DateTime.now & Rnd(100, 999)
End Sub

'Sets the Id in the browser window
Private Sub SetBrowserWindowId()
    bwWebSocket.Eval("window.name = arguments[0];", Array(bwId))
    bwWebSocket.Flush
End Sub

'Get the Id from the browser window
Private Sub GetBrowserWindowId() As String
    Dim browserWindowId As Future = bwWebSocket.EvalWithResult("return window.name;", Null) 'ignore
    Return browserWindowId.Value
End Sub

'Returns the browser window Id from this class
Public Sub getId() As String
    Return bwId
End Sub

'Returns the value tied to the attribute with the specified name.
Public Sub GetAttribute(Name As String) As Object
    Return bwWebSocket.Session.GetAttribute(bwId & "_" & Name)
End Sub

'Returns the value tied To the attribute with the specified Name.
'Returns the DefaultValue If no value exists.
Public Sub GetAttribute2(Name As String, DefaultValue As Object) As Object
    Return bwWebSocket.Session.GetAttribute2(bwId & "_" & Name, DefaultValue)
End Sub

'Returns a List with all the attribute names.
Public Sub GetAttributesNames() As List
    Dim result As List
    result.Initialize()
    For Each attribute As String In bwWebSocket.Session.GetAttributesNames
        If attribute.Length > bwId.Length And attribute.SubString2(0, bwId.Length) = bwId Then
            result.Add(attribute.SubString(bwId.Length + 1))
        End If
    Next
    Return result
End Sub

'Tests whether there is a value tied to the given name.
Public Sub HasAttribute(Name As String) As Boolean
    Return bwWebSocket.Session.HasAttribute(bwId & "_" & Name)
End Sub

'Removes the attribute with the given name.
Public Sub RemoveAttribute(Name As String)
    bwWebSocket.Session.RemoveAttribute(bwId & "_" & Name)
End Sub

'Adds an attribute to the session. If there is an existing value with the same name then it will be replaced.
Public Sub SetAttribute(Name As String, Value As Object)
    bwWebSocket.Session.SetAttribute(bwId & "_" & Name, Value)
End Sub

'Invalidates this browser window session store.
'If you chose to preserve attributes in session they will continue to exist in session, otherwise they will be removed.
Public Sub Invalidate(PreserveAttributesInSession As Boolean)
    If PreserveAttributesInSession = False Then
        For Each attribute As String In bwWebSocket.Session.GetAttributesNames
            If attribute.Length > bwId.Length And attribute.SubString2(0, bwId.Length) = bwId Then
                bwWebSocket.Session.RemoveAttribute(attribute)
            End If
        Next         
    End If
    bwId = Null
    bwWebSocket = Null
End Sub

Now in you WebSocket class:
1. Declare the BrowserWindow in Class_Globals:
B4X:
Sub Class_Globals
  Private BrowserWindow as BrowserWindowSessionStore
End Sub

2. In the WebSocket_Connected:
B4X:
Private Sub WebSocket_Connected(WebSocket1 As WebSocket)
  BrowserWindow.Initialize(WebSocket1)
  Log(BrowserWindow.Id & " Connected")
End Sub

3. In the WebSocket_Disconnected:
B4X:
Private Sub WebSocket_Disconnected()
  Log(BrowserWindow.Id & " Disconnected")
  ' this sub will be fired when the browser window navigates to another page
  ' so we want to preserve this browser window attributes in session so we can reload them in another Server WebSocket class instance
  ' if you do not need to preserve the attributes (the user logs out) call BrowserWindow.Invalidate(False)
  BrowserWindow.Invalidate(True)
End Sub


This was usefull to me so maybe it's usefull to others !
 
Last edited:

mindful

Active Member
Licensed User
As a general rule it is better not to catch exceptions in libraries or code snippets. Most of this code will never raise an error and if it will raise an error then it means that the connection has broken and catching it will not help anyway.

You are absolutely right ;) I removed all the error handling. Thanks !
 
Top