Offline Application Flow (Magic xpa 2.x)
Applications with Offline programs have a slightly modified startup and execution sequence for allowing offline startup, while also supporting connected startup. This section describes the changes in the execution flow.
On startup, the client will always attempt to connect to the server, and depending on internet connectivity, the Main Program will be executed accordingly:
-
If the client can connect to the server, the Main Program will run both on the server and on the client, so a context will be opened on the server ready to serve future requests.
-
If the client cannot connect to the server, the Main Program will run only on the client, without opening a context on the server. In future server access, the client will try again to connect to the server as detailed below.
When closing the application:
-
If the application was connected to the server, it accesses the server to close the context.
-
If there is no connection to the server, but there is no server logic in the Main Program’s Task Suffix logic unit, then the application will be closed on the client without showing an error. In this case, the context on the server will remain open until the context inactivity timeout is reached.
Note that if the Main Program is defined with the Open task window task property set to Yes, the MDI window will open even if there is no connection to the server. This allows you to run your Offline programs or to wait for the connection to resume and start non-Offline programs. If you want to disable this behavior, you can raise the Exit System event in the Unavailable Server event handler in the Main Program.
In Offline tasks, as opposed to non-Offline tasks, the Task Prefix logic unit executes on the client. Therefore, it can contain client-side logic.
The following limitations apply to Offline tasks:
-
The Tree control is not supported in an Offline task.
-
Frames forms are not supported in an Offline task.
-
Server data sources cannot be used in an Offline task.
-
Server-side operations and expressions cannot be used in an Offline task.
-
Only Offline programs can be used in an Offline program’s subform.
-
Offline programs cannot be used in a non-Offline program’s subform.
-
Offline tasks can only have Offline Rich Client subtasks.
-
When testing offline capabilities in the Studio, the server needs to run in Background deployment mode. If the application was started on the client without server access, and the access to the server then resumes, the application will not be able to access the server when the server is running in Online deployment mode.
Since Offline programs are client programs that can work when disconnected, they cannot access the server directly. This means that they cannot call server programs or use server functions. However, it is often necessary to allow Offline programs to initiate a call to server programs (for example, to periodically synchronize data).
Calling server programs from Offline programs can be achieved by raising an event in an Offline program that has a handler in the Main Program. In this Main Program event handler, it is possible to perform the necessary server actions.
Using the above technique enables the client to start the application without server access, and to access the server later on. In this case, the client will try to connect to the server and, if successful, a context will be opened on the server and the server logic will be executed.
Note: When closing the Offline program, a called non-Offline program might not be closed automatically.
If a network error occurs during server calls, or if the server is unable to complete the request, the behavior will be as described in the following section.
Note: When performing server access following initial startup, the client will not try to retrieve updated metadata (such as environment files and Offline programs) from the server. If changes were made to the metadata, causing the client metadata to be older than the server metadata, the server access will fail and the behavior will be as described in the following section.
When server access fails for any reason, the client will perform the following error recovery sequence:
-
The user will be prompted to retry or abort the operation. The client will retry the operation as many times as the user requests. This dialog box can be disabled by evaluating the ClientSessionSet() function with the EnableCommunicationDialogs key parameter and a value of 'FALSE'LOG. When this dialog box is disabled, or when the user selects Abort, the execution will continue to step two.
-
All non-Offline programs running on the client will be terminated.
-
The Unavailable Server event will be raised. This event lets you write logic to be executed when server access errors occur.
-
The ServerLastAccessStatus() function will return an error code. This function returns zero if the last access to the server was successfully completed or a non-zero value if an error occurs. You can use this function to show detailed information about steps to take if a network error occurs, or to execute different logic in such a scenario.
It is best practice to condition any access to the server, including access to the resources, with ServerLastAccessStatus()=0.This condition ensures that the access to the server will be made only if the client successfully accessed the server on the last attempt. If the client failed to connect to the server, then by having this condition, the client will not try (and fail) to reconnect to the server.
-
The flow will continue from the last Offline program running, starting from the next action following the server action that failed. This allows the user to continue working and to try to call the server later on.
By default, when the application starts it connects to the server. You can set the application to start without accessing the server by setting he ConnectOnStartup execution property to N. This is useful when the client does not need to access the server upon startup; for example, when the synchronization process is done manually by the user or on a weekly basis. If you always need to call the sync program on startup, then skipping the connection to the server on startup will not be useful.
Note: When setting the ConnectOnStartup execution property to N and the client is not connected to the server on startup, the ServerLastAccessStatus() function will return a value different than 0, so you can condition your server access logic as advised above. The client will connect to the server on startup only after the metadata was changed, and in that case, will also run your server access logic.