DataSnap-like Client-Server JSON RESTful Services in Delphi 7-2010
By A.Bouchez on 2010, Sunday July 18, 17:44 - SQLite3 Framework - Permalink
You certainly knows about the new DataSnap Client-Server features, based on
JSON, introduced in Delphi 2010.
http://docwiki.embarcadero.com/RADStudi
… plications
We added such communication in our SQLite3 Framework, in a KISS (i.e. simple) way: no expert, no new unit or new class. Just add a published method Server-side, then use easy functions about JSON or URL-parameters to get the request encoded and decoded as expected, on Client-side.
We'll implement the same example as in the official Embarcadero docwiki page
above. Add two numbers. Very useful service, isn't it? ![]()
We'll first code the Server-side:
First the declaration of the class:
TSQLRestServerTest = class(TSQLRestServerDB)
published
function Sum(aRecord: TSQLRecord; aParameters: PUTF8Char;
const aSentData: RawUTF8; var aResp, aHead: RawUTF8): Integer;
end;
This method name will be used for the URL encoding, and will be called here with ModelRoot/Sum URL.
This method, like all Server-side methods, MUST have all these parameters, and follow the TSQLRestServerCallBack prototype:
type
TSQLRestServerCallBack = function(aRecord: TSQLRecord;
aParameters: PUTF8Char; const aSentData: RawUTF8;
var aResp, aHead: RawUTF8): Integer of object;
Then we implement this method:
function TSQLRestServerTest.Sum(aRecord: TSQLRecord; aParameters: PUTF8Char;
const aSentData: RawUTF8; var aResp, aHead: RawUTF8): Integer;
var a,b: Extended;
begin
if not UrlDecodeNeedParameters(aParameters,'A,B') then
begin
result := 404; // invalid Request
exit;
end;
while aParameters<>nil do
begin
UrlDecodeExtended(aParameters,'A=',a);
UrlDecodeExtended(aParameters,'B=',b,@aParameters);
end;
aResp := JSONEncodeResult([a+b]);
// same as : aResp := JSONEncode(['result',a+b],TempMemoryStream);
result := 200; // success
end;
Not difficult to follow, isn't?
OK, now the client-side:
function Sum(aClient: TSQLRestClientURI; a, b: double): double;
var err: integer;
begin
val(aClient.CallBackGetResult('sum',['a',a,'b',b]),Result,err);
end;
And... that's all!
You have to create the server instance, and the corresponding TSQLRestClientURI, with the same database model, just as usual...
Note that this Client-Server protocol uses JSON here, but you can serve any
kind of data, binary, HTML, whatever...
The usual protocols of our framework can be used: HTTP/1.1, Named Pipe, Windows
GDI messages, direct in-memory/in-process access.
Just to be noticed that the data transmitted is a valid JSON content, like this one:
{ "result":3.141592653}
So you can consume these services, implemented Server-Side in fast Delphi code, with any AJAX application Client-Side.
Of course, these services can be related to any table/class of our ORM framework, so you would be able to create easily any RESTful compatible requests on URL like ModelRoot/TableName/ID/MethodName. For example, here we return a BLOB field content as hexa:
function TSQLRestServerTest.DataAsHex(aRecord: TSQLRecordPeople; aParameters: PUTF8Char;
const aSentData: RawUTF8; var aResp, aHead: RawUTF8): Integer;
var aData: TSQLRawBlob;
begin
result := 404; // invalid Request
if (self=nil) or (aRecord=nil) or not aRecord.InheritsFrom(TSQLRecord) or
(aRecord.ID<0) then
exit; // we need a valid record and its ID
if not EngineRetrieveBlob(TSQLRecordPeople,aRecord.ID,
aRecord.FieldProp('Data'),aData) then
exit; // impossible to retrieve the Data BLOB field
aResp := JSONEncodeResult([SynCommons.BinToHex(aData)]);
// idem: aResp := JSONEncode(['result',BinToHex(aRecord.fData)],TempMemoryStream);
result := 200; // success
end;
Full source code is available in our
Source Code Repository.
It should work from Delphi 7 to Delphi 2010.
Your comments are welcome on our forum.