Principles
When running client/server applications with an object server, almost all function calls are passed to the server, which returns the result to the client. In principal, client/server applications run the same way as local or file server applications. Nevertheless, there are some differences.
When opening property handles on client side, each client property handle gets a pendent on server side. When a function call is sent to server, all modified data instances on client side are collected and passed to the server in order to update data in appropriate property handles on server side. This is necessary for reacting properly on events handled in context classes on server side.
One more decision that has to be taken into account when writing client server applications is where to execute complex functionality.
While required actions are performed on server side, events and modifications are collected in order to pass those to client after finishing the function. Thus, the client can be updated and event handlers on client side may be called. Passing a function call to the server, will send all modifications to the server first, but no client events. Returning back the response from the server sends also modifications (including property handle states as selected instance) and events collected on server side. Since events are cached and optimized wile executing the required function, only events relevant for the application will be returned to the client. When returning back data, property handle states and events, data and property handle states are synchronized before calling event handlers.
Since data is updated in all property handles before calling event handlers, data available for event handlers may differ for local applications, which may influence the behavior of the application. In order to avoid this, data related event handling should be called on server side, only. Since all local and file server applications are client and server at the same time, one may run event handlers in context classes only, when ObjectSpace::isServer() returns true. In this case, context class event handlers will run on server side, only, and do nothing on client side (except the client is server at the same time).
When handling events on client side, the submit further server requests, events returned from server while handling an event are queued and and the event queue will be processed from beginning. After detecting 10 event collections returned from server, event handling on client side stops in order to avoid infinitive recursion. Hence, client event handlers should communicate as less as possible with the server.
int32 doBeforeDataStore::MyClass()
{
if ( database().isServer() ) { // run for local applications or on serverside
... do what is necessary
}
}
There are different ways of calling complex functions from within an application:
- Directly calling an application function
- Calling a context class action (generic function call)
- Running an OSI function (expression)
When calling a function directly, it always is executed where it is called, e.g. calling the function on server side (e.g. from an event handler) executes the function on server side. In order to call a complex function on client side, which should be run on server side, one may provide an OSI interface for the function and call it via executeExpression().
Context class actions or generic function calls are always executed on callers side and there is no work around. Anyhow, one may delegate the complex function to be executed in the context class action again via OSI interface to the server.
Running OSI functions or expressions by calling executeExpression() allows running an OSI function/expression on client side but also on server side.