Session Storage

Each client session, upon connection, gets its own private data store synchronized with the service application. This feature is called session storage, and you can use it to make different data available to different users connected to the same service instance. This can prove especially useful in collaboration scenarios, as it provides a means to ensure that collaboration participants do not gain access to sensitive data intended only for the host.

The data is stored as key/value pairs; the repository supports the full range of unicode characters, including extended characters like emojis.

For other storage options, see application state and resource manager.

How-to

Write a value

Writing a key/value pair to session storage is essentially the same across all APIs. However, the method takes different parameters on the client and on the service.

On the client

APIs:

SessionStorage.setValue | HTML5 | Android
PWSessionStorage.setKey | iOS

To write to session storage, you call setValue (labeled setKey in iOS), which simply requires the key to set, and the value to assign to this key.

On the client, the setValue method accepts a third, optional parameter, suppressHandlers, which is set to "false" by default. You would only need to set it to "true" if you created a change handler for the value (as discussed further down this page), but do not want the write operation to trigger this handler.

Each client can only interact with the specific data store that the service provides for it.

In the example below, we are setting an entry whose key is labeled "secret" and contains the string value "Only I know". We explicitly set the third parameter to "false" to illustrate the complete syntax, but this is optional.

HTML5

pureweb.getClient().getSessionStorage().setValue('secret', 'Only I know', false);

iOS (Obj-C)

PWSessionStorage* storage = [[PWFramework sharedInstance].client getSessionStorage];
[storage setKey: secret toValue: "Only I know" withSuppression: false];

Android

framework.getWebClient().getSessionStorage().setValue("secret", "Only I know", false);

On the service

APIs:

SessionStorageManager.setValue | C++ | .Net | Java

SessionStorageManager.setValueForAllSessions | C++ | .Net | Java

On the service, you also use setValue to write a key/value pair to session storage. However, because the service can access the data stores for each connected client, there are differences:

  • The sessionId is a required parameter for service-side methods, as it is necessary to specify to which data store an operation applies.
  • A service-only method, setValueForAllSessions, can be used to write an entry in the data stores for all clients connected to the same service instance, thereby making the entry accessible to every participant in a collaboration setting.

By default, calling setValue on the service will not update the session storage on the client if the value is idempotent.

You can change this behavior by explicitly setting a fourth parameter to setValue (called forceResponse or forceUpdate) to "true".

In the example below, we are setting an entry whose key is labeled "secret" and contains the string value "Only I know". We explicitly set the fourth parameter to "false" to illustrate the complete syntax, but this is optional.

C++

//Setting a value for a single session
stateManager->SessionStorageManager().SetValue(sessionId, "secret", "Only I know", false);

//Setting the same value for all sessions at once
stateManager->SessionStorageManager().SetValueForAllSessions("secret", "Only I know");

.Net

//Setting a value for a single session
stateManager.SessionStorageManager.SetValue(sessionId, "secret", "Only I know", false);				

//Setting the same value for all sessions at once
stateManager.SessionStorageManager.SetValueForAllSessions("secret", "Only I know");

Java

//Setting a value for a single session
stateManager.getSessionStorageManager().setValue(sessionId, "secret", "Only I know", false);

//Setting the same value for all sessions at once
stateManager.getSessionStorageManager().setValueForAllSessions("secret", "Only I know");


Read a previously set value

APIs:

SessionStorage.getValue | HTML5 | iOS | Android

SessionStorageManager.GetValue | C++ | .Net | Java

To read a previously set value, you simply call getValue, passing as a parameter the key for which you want to know the value.

In the snippets below, we are getting the value for the key labeled "secret", which we stored in the previous example.

On the client

HTML5

pureweb.getClient().getSessionStorage().getValue('secret'));				

iOS (Obj-C)

PWSessionStorage* storage = [[PWFramework sharedInstance].client getSessionStorage];
[storage getValue:secret];

Android

framework.getWebClient().getSessionStorage().getValue("secret");

On the service

Just like setValue, on the service the getValue method requires the session ID.

C++

stateManager->SessionStorageManager().GetValue(sessionId, "secret");

.Net

stateManager.SessionStorageManager.GetValue(sessionId, "secret");			

Java

stateManager.getSessionStorageManager().getValue(sessionId, "secret");


Set up change handlers

Change handlers allow the application to respond when a change occurs to the value of a particular key within session storage.

To set up a change handler, you first register this handler, then define the handling function.

If you set up a change handler for a value, but do not want this handler to trigger in certain situations, you can use the suppressHandlers parameter for the client-side setValue method.

Register the handler

APIs:

SessionStorageManager.addValueChangedHandler | C++ | .Net | Java

SessionStorage.addValueChangedHandler | HTML5 | Android
PWSessionStorage.addValueChangedHandler | iOS

Registering the change handler consists of a single line of code, where you specify which key to watch for changes, and associate the handling function.

Once the handlers are no longer needed, you can unregister them using removeValueChangedHandler and removeAllValueChangedHandlers.

In the sample code below, we register a change handler so that whenever the value for the "secret" key changes, the application will execute a developer-defined function labeled OnSecretChanged.

On the client

HTML5

pureweb.getClient().getSessionStorage().addValueChangedHandler("secret", OnSecretChanged);

iOS (Obj-C)

[self.storage addValueChangedHandler:secret target:self action:@selector(OnSecretChanged:)];

Android

framework.getWebClient().getSessionStorage().addValueChangedHandler(secret, new EventHandler<SessionStorageChangedEventArgs>());

On the service

C++

stateManager->SessionStorageManager().AddValueChangedHandler(sessionId, "secret", Bind(this, &MyApp::OnSecretChanged));

.Net

stateManager.SessionStorageManager.AddValueChangedHandler(sessionId, "secret", OnSecretChanged);

Java

stateManager.getSessionStorageManager().addValueChangedHandler(sessionId, "secret", new OnSecretChanged);

Define the handler

The change handler itself (the function that will be triggered when the value in session storage changes) provides a SessionStorageChangedEventArgs object as argument. This object contains information about the change that triggered the event, including its type (such as insertion or deletion), the key that changed and the new value.

On the client

HTML5

OnSecretChanged = function(args){
    // Do something useful
};						

iOS (Obj-C)

-(void)OnSecretChanged:(PWSessionStorageChangedEventArgs*) args {
    // Do something useful
}

Android

private class OnSecretChanged implements EventHandler<SessionStorageChangedEventArgs>
{
    public void invoke(Object sender, SessionStorageChangedEventArgs args)
    {
         // Do something useful
    }
}

On the service

C++

void MyApp::OnSecretChanged(SessionStorageChangedEventArgs args)
{
    // Do something useful
}

.Net

private void OnSecretChanged(Object source, SessionStorageChangedEventArgs args)
{
    // Do something useful
}

Java

private class OnSecretChanged implements EventHandler<SessionStorageChangedEventArgs>
{
    public void invoke(Object source, SessionStorageChangedEventArgs args) 
    {
        // Do something useful
    }
}


Keep track of sessions

While working with session storage, your service may need to know which client sessions are connected at any point in time. You can do this by capturing connection events.

You may also need to determine which is the host session in a collaboration scenario. You can do this by comparing session IDs.

Listening for connection events

APIs:

SessionManager | C++ | .Net | Java
SessionEventArgs | C++ | .Net | Java

To keep track of which client sessions are connected, you would register listeners for session connection and disconnection events on the service. These events are raised by the service-side SessionManager class.

The events are called SessionConnected and SessionDisconnected (in C++ and .Net), and in Java the corresponding methods are addSessionConnectedHandler and addSessionDisconnectedHandler.

The event handler provides a SessionEventArgs object, which you can query to get ID of the client which just connected (or disconnected).

C++

sessionManager->SessionConnected() += Bind(this, &MyApp::OnSessionConnected);

void MyApp::OnSessionConnected(ISessionManager& sessionManager, SessionEventArgs&)
{
    // Do something useful once connected
}				

.Net

sessionManager.SessionConnected += new EventHandler(OnSessionConnected);

private void OnSessionConnected(object sender, SessionEventArgs args)
{
    // Do something useful once connected
}

Java

sessionManager.addSessionConnectedHandler(new SessionConnectedHandler());

private class SessionConnectedHandler implements EventHandler<SessionEventArgs>
{
    public void invoke(Object source, SessionEventArgs args)
    {
        // Do something useful once connected.
        
	 // Can get the session ID from the arguments, if needed:
        UUID sessionId = args.getSessionId();
    }
}

Comparing session IDs

APIs:

CollaborationManager.getOwnerSession() | HTML5 | Android
PWCollaborationManager.ownerSession() | iOS

CollaborationManager.getSessionId() | HTML5 | Android
PWCollaborationManager.sessionId() | iOS

You may want to implement logic in your client so that it behaves differently when the user is the host, and to do this you need to be able to determine whether a connected user is the session owner.

To do this, you can compare session IDs. The necessary methods for getting the IDs can be found in the client-side CollaborationManager class.

First, you would use getOwnerSession to obtain the ID of the host, then use getSessionId to obtain the ID of the collaboration session. Finally, compare the two identifiers; if they are equal, the user is the host, and if they are different, the user is a participant.

HTML

pureweb.getFramework().getCollaborationManager().getOwnerSession() === pureweb.getClient().getSessionId()

iOS (Obj-C)

[[PWFramework sharedInstance].collaborationManager ownerSession] == [[PWFramework sharedInstance].collaborationManager sessionId]

Android

framework.getCollaborationManager().getOwnerSession() == framework.getWebClient.getSessionId()