📜 ⬆️ ⬇️

DataSnap Callback usage example: data request from user during server method call

What is it and what is needed:

Working with Datasnap is to request data from the server and call server methods, for example:
- Request a list of products from the server (dataset)
- Create a new document
- Add positions to it
- Close the document

Sometimes when adding a position, it is necessary to make an additional choice, for example, to choose a consignment of goods or a cut.
')
This can be done by returning an error code (something like Prepare / Execute), so that the client requests the user and then tries the operation again.
Or give the server the opportunity to request the client directly during the operation all the data he needs.



What can be done:
The first option requires a list of error codes with appropriate processing.
The second option requires that the client register the callback functions that the server can call, and also each time the server is accessed, keep in mind that the server may demand something from the client (and this threatens to block if the request requires a response from the user). In order to avoid blocking with a single-threaded user interface, calls to the server should be made in a separate thread - then the call from the server can be synchronized with the main thread (which does not already wait for control to return from the original server method call). And also do not forget to inform the server client ID.

Call:
procedure TForm2.btnRegisterWareClick(Sender: TObject); begin TThread.CreateAnonymousThread( procedure() begin clmClient.ServerMethods1Client.RegisterWare(seWareID.Value, clmClient.DSClientCallbackChannelManager1.ManagerId) end).Start; end; 


The callback function itself:
  TmyCallback = class(TDBXCallback) protected FSelectedString: Integer; procedure SelectString(const Arg: TJSONValue); public function Execute(const Arg: TJSONValue): TJSONValue; override; end; { TmyCallback } function TmyCallback.Execute(const Arg: TJSONValue): TJSONValue; begin TThread.Synchronize(nil, procedure() //     -     begin SelectString(Arg); end); Result := TJSONNumber.Create(FSelectedString); end; procedure TmyCallback.SelectString(const Arg: TJSONValue); var strs: TStringList; enum: TJSONPairEnumerator; val, str: string; begin enum := TJSONObject(Arg).GetEnumerator; if Assigned(enum) then begin strs := TStringList.Create; try while enum.MoveNext do begin Val:= enum.Current.JsonString.Value; str := enum.Current.JsonValue.Value; strs.AddObject(str, TObject(val.ToInteger())); end; FSelectedString := TfrmSelectString.SelectString(strs); finally strs.Free; end; end; enum.Free; end; 

But what happens on the server:
 procedure TServerMethods1.RegisterWare(ID: Integer; ClientID: string); var Params, ParamsServ: TJSONObject; ResObj: TJSONValue; temp: TJSONValue; begin ResObj := nil; Params := TJSONObject.Create; Params.AddPair(TJSONPair.Create('1', ' 42')); Params.AddPair(TJSONPair.Create('2', ' 43')); Params.AddPair(TJSONPair.Create('3', ' 44')); ParamsServ := TJSONObject(Params.Clone); ServerContainer1.DSServer1.NotifyCallback(ClientID, 'SelectString', Params, ResObj); if Assigned(ResObj) then begin temp := ParamsServ.GetValue(ResObj.Value); if Assigned(temp) then Form1.QueueLogMsg(Format('RegisterWare %d   %s', [ID, temp.ToString])) else Form1.QueueLogMsg(Format('RegisterWare %d  ', [ID])); ResObj.Free; ParamsServ.Free; end else Form1.QueueLogMsg(Format('RegisterWare %d  ', [ID])); end; 

And finally, a reminder:
- Local procedure variables - not initialized
- Everything that you pass to a function - you can say goodbye to them and not release
- Everything that you get from the function must be released (after all, the ARC does not work here (although it is necessary to clarify for mobile phones))

With callbacks, you can do anything — send a ready-made dataset or SQL query, or the name of a directory from which the stored procedure returns a selection set to it.

Code: http://code.google.com/p/datasnap-callback-with-ui/source/browse/

This example was made by me to study the very technology of callbacks in Datasnap, in particular, exactly such a callback to the client during the server request
Since so far with the technology is not firmly determined, the next in the study of such a technique would be RealThinClient

Source: https://habr.com/ru/post/202688/


All Articles