The ContextWrapper is a static class on either the client or the AppServer. It does not store any session values and as a static class cannot be serialized to the AppServer. All the ContextWrapper is doing is providing simplified access to the ContextDataset (dsContext).
The ContextDataset is referenced via the SessionManager property ContextDataset. It is initially created on the client. The default way of doing this is through the ContextDatasetFactory. The ContextDataset has two tables.
eSessionContext: With explicit fields for default tables.
eContextProperties: With generic key/value pairs.
The structure of the ContextDataset is not glued into the framework too much. The whole concept of the Contex DatasetFactory and the fact that the SessionManager only needs a handle is designed to allow users to extend or replace the ContextDataset. In those cases, users would prefer a more structured storage for specific session properties than what the generic name/value list supports. This can be done through a custom implementation of IContextDatasetFactory and using it as a Service instead of the ContextDatasetFactory (for more info on Services see: Services and the Service Container). The datasets of custom IContextDatasetFactory implementations must include eSessionContext and eContextProperties.
In the context of the Client and AppServer, the ContextDataset is first instantiated on the Client. The ContexDataset is then passed to the AppServer in every AppServer call as a DATASET-HANDLE parameter. The Appserver returns the dataset to the client. On the AppServer there is no need to use the ContextDatasetFactory as the ServiceInterface assigns the SessionManager:ContextDataset handle to the instance retrieved from the AppServer. Thus, the ContextWrapper can provide access to the session properties via its methods and properties.
The ContextDataset is serialized between Client and AppServer as a dataset and not in JSON or XML. The ABL default serialization for ProDatasets is the most efficient way of passing a dataset between Client and AppServer and back.
If calls on the backend to other backend components are made through the ServiceAdapter and not the ServiceInterface, the ContextDataset is lost. This is because the ServiceAdapter sends the ContextDataset, currently owned by the client, to the ServiceInterface which would assign the handle of the copy of the ContextDataset to SessionManager:ContextDataset. After returning to the ServiceAdapter this handle is no longer valid. Thus, the ContextDataset which would be send back to the client would be lost. A ContextDataset that is passed to service interface procedures (i.e. OERA/support/proSI*.p) are always explicitly deleted by those procedures.
For this reason, code on the backend needs to call though the ServiceInterface!
The ContextDataset is not passed between client and server for REST-calls. Instead, it is stored in the SmartDB for each session. The data is being stored in the SmartContextStore table, more specifically in its ContextDataset field. SmartContextStore.ContextDataset is a CLOB field, it holds the ContextDataset as a JSON string. The SmartContextStore record is identified by SmartContextStore.SessionID = client-principal:session-id (not the jsessionid).
Customers should ensure records for expired sessions will be removed from the SmartContextStore database table.
The transfer of the ContextDataset between SessionManager and DB is done by the ServerSessionActivator if the dataset is held by a client or RestServerSessionActivator if it held by the store. Both are registered as services despite not implementing any interfaces (ServiceTypeName = ServiceClassName). This is because there are no methods to be called on them. Instead, they subscribe to the ServiceInterfaces Activated and Deactivated events. They use the sessions current-request-info attribute to get the handle of the current client-principal to restore/store the ContextDataset. If there is no SmartContextStore from which to restore, the SessionManager properties are instead populated with info from SmartUser and SmartLoginCompany and stored on the DB when the ServiceInterface is deactivated.
The ServiceInterface also has the events AfterActivated, BeforeDeactivated and AfterDeactivated for user-code that needs to act before or after the framework-code.