You are not logged in.
After few hours debugging... yes, you are right! :-)
I destroyed TSQLModel before TSQLRestServer which used it!
But why at FastMM I had no error? It was set to full debug mode. This is magic ;-)
ps. I use ScaleMM3 (not stable version 2).
ps. SynScaleMM is ready/stable and I can use it?
thx for support
best regards
I wrote a REST server. Everything works fine, but the performance in the threads is low. I changed the memory manager from FastMM to ScaleMM and now performance is high, but I have a new problem. When I close the application I get the AV:

Error raise this code (after press F8):

Callstack:
mORMot.JSONObject(TClass($649B740),-1,[cpWrite])
mORMot.TJSONSerializer.WriteObject($649B700,[woFullExpand])
mORMot.TJSONSerializer.WriteObject($649BC00,[woFullExpand])
SynCommons.TTextWriter.Add((105495552, False, #0, $649BC00, $649BC00 {':ź'#0#0'·I'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'ŕąI'#6'ŕ–Ş'#3'”yj'#0#0#0#0#0'PŞ2'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0}, $649BC00, '|:ź', $649BC00, TClass($649BC00), '?', '?'#$009F'??', $649BC00, $649BC00, $649BC00, $649BC00, $649BC00, $649BC00, $649BC00, 105495552, 7),twOnSameLine)
SynCommons.TTextWriter.Add('%.Destroy -> %',(...),twOnSameLine)
SynLog.TSynLog.LogInternal(sllInfo,'%.Destroy -> %',(...),nil)
SynLog.TSynLog.Log(sllInfo,'%.Destroy -> %',(...),nil)
mORMot.TSQLRest.Destroybest regards
Thx! :-)
Class TSQLRestServer has three methods of registering services:
function ServiceRegister(aImplementationClass: TInterfacedClass; const aInterfaces: array of PTypeInfo;
aInstanceCreation: TServiceInstanceImplementation=sicSingle): TServiceFactoryServer; overload; virtual;
function ServiceRegister(aSharedImplementation: TInterfacedObject; const aInterfaces: array of PTypeInfo): TServiceFactoryServer; overload; virtual;
function ServiceRegister(aClient: TSQLRest; const aInterfaces: array of PTypeInfo; aInstanceCreation: TServiceInstanceImplementation=sicSingle;
const aContractExpected: RawUTF8=''): boolean; overload; virtual;But only one of these methods allows specify a parameter: aContractExpected
Is possible to add aContractExpected parameter to second method too (with aSharedImplementation: TInterfacedObject parameter)?
In this way:
function ServiceRegister(aSharedImplementation: TInterfacedObject; const aInterfaces: array of PTypeInfo;
const aContractExpected: RawUTF8=''): TServiceFactoryServer; overload; virtual;best regards
Oh, sorry, you are right. Thanks for reply :-)
function TServiceBase.MakeSomething : string;
var
IP : string;
begin
IP := FindIniNameValue(Pointer(ServiceContext.Request.Call.InHead),'REMOTEIP: ');
end;Hi,
I need in service method (interface-based service) get client IP. How to do it?
IServiceBase = interface(IInvokable)
function MakeSomething : string;
end;
TServiceBase = class(TInterfacedObject, IServiceBase)
public
function MakeSomething : string;
end;
[...]
ServiceRegister(fServiceBase, [TypeInfo(IServiceBase)]);
[...]
function TServiceBase.MakeSomething : string;
begin
[...] <------------ how get client IP in this place?
end;best regards
The examples show how to register in server a class that implements the ICalculator interface.
ICalculator = interface(IInvokable)
['{E7014BA0-007E-4DCB-9C34-4A8CCB2BF9C3}']
function Suma(A, B : Integer): Integer;
function GetName : string;
end;
TCalculator = class(TInterfacedObject, ICalculator)
public
function Suma(A, B : Integer): Integer;
function GetName : string;
end;And now the registration and use:
var
aModel: TSQLModel;
begin
aModel := TSQLModel.Create([],ROOT_NAME);
try
with TSQLRestServerDB.Create(aModel,ChangeFileExt(paramstr(0),'.db'),true) do
try
ServiceRegister(TServiceCalculator,[TypeInfo(ICalculator)],sicShared);
ExportServerNamedPipe(APPLICATION_NAME);
readln;
finally
Free;
end;
finally
aModel.Free;
end;
end.But I would like to register interface on the server, not a object/class. So this:
var
aModel: TSQLModel;
liCalculator : ICalculator;
begin
aModel := TSQLModel.Create([],ROOT_NAME);
try
with TSQLRestServerDB.Create(aModel,ChangeFileExt(paramstr(0),'.db'),true) do
try
liCalculator := GetImplementorOfInterface(ICalculator); <----- get interface implementation
ServiceRegister(liCalculator,[TypeInfo(ICalculator)],sicShared); <--------- register instance of interface!
ExportServerNamedPipe(APPLICATION_NAME);
readln;
finally
Free;
end;
finally
aModel.Free;
end;
end.In my code I operate mainly on interfaces, I don't want to mix object access and interface access. In addition, I would like to have separated implementation of interfaces, because I can easily swap between the implementations (on configuration level).
Is this possible? Can you add this functionality? :-)
thx
Hi,
I rebuilt example 14 (with a calculator) to work on the numbers of type Double (from Integer).
ICalculator = interface(IInvokable)
['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
function Add(n1,n2: Double): Double;
end;
[...]
TServiceCalculator = class(TInterfacedObject, ICalculator)
public
function Add(n1,n2: Double): Double;
end;Then now I get error in server (SynCommons.GetExtended):
Breakpoint on GetExtended:

After Step Over (F8):

Big thx Arnaud! :-)
And?
How create TSQLHTTPServer with empty "aServers" parameter in constructor?
I need it.
I know. But I need create TSQLHttpServer WITHOUT TSQLRestServer(s) parameter in constructor (mORMmot forcing me to do this).
You did not understand me, my english is crooked, sorry :-)
When I execute this line:
server := TSQLHttpServer.Create('808', [], '+', useHttpApi, 8); I get exception from TSQLHttpServer constructor:
if ErrMsg<>'' then
raise EModelException.CreateUTF8('%.Create(% ): %',[self,ServersRoot,ErrMsg]);where ErrMsg is 'No TSQLRestServer'
And I need to create a HTTP server without TSQLRestServer (rest server I will add later).
When I modify TSQLHttpServer constructor (wrong, I know, but temporary, for test only):
constructor TSQLHttpServer.Create(const aPort: AnsiString;
const aServers: array of TSQLRestServer; const aDomainName: AnsiString;
aHttpServerKind: TSQLHttpServerOptions; ServerThreadPoolCount: Integer;
aHttpServerSecurity: TSQLHttpServerSecurity; const aAdditionalURL: AnsiString;
const aQueueName: SynUnicode);
var i,j: integer;
ServersRoot: RawUTF8;
ErrMsg: RawUTF8;
begin
[...]
if high(aServers)<0 then
ErrMsg := 'No TSQLRestServer' else
for i := 0 to high(aServers) do
if (aServers[i]=nil) or (aServers[i].Model=nil) then
ErrMsg := 'Invalid TSQLRestServer';
if ErrMsg='' then
for i := 0 to high(aServers) do
with aServers[i].Model do begin
ServersRoot := ServersRoot+' '+Root;
for j := i+1 to high(aServers) do
if aServers[j].Model.URIMatch(Root) then
ErrMsg:= FormatUTF8('Duplicated Root URI: % and %',[Root,aServers[j].Model.Root]);
end;
ErrMsg := ''; <<<----- my modification, to miss exception
if ErrMsg<>'' then
raise EModelException.CreateUTF8('%.Create(% ): %',[self,ServersRoot,ErrMsg]);then everything works fine, as I expected.
Hi,
Is it possible to create instances of the TSQLHttpServer without having to enter TSQLRestServer instance?
I would like in one place the code to create a HTTP server and in other places (controlled by the configuration) add a REST servers.
TssHTTPServer = class(TSQLHttpServer)
public
constructor Create(aHTTPPort: Integer);
end;
constructor TssHTTPServer.Create(aHTTPPort: Integer);
begin
inherited Create(aHTTPPort.ToString, [], '+', useHttpApi, 8); // [] <----- I want to create HTTP server without SQLRestServers
end;
var
httpserver : TssHTTPServer;
begin
httpserver := TssHTTPServer.Create(808);
SomeRestServer := GetServerFromRepo;
httpserver.AddServer(SomeRestServer);At this moment the order is reversed, I must first have a REST server and then create HTTP server :-(
best regards
Hello,
You wrote in docs:
"The Server will search for any class inheriting from TSQLAuthGroup and TSQLAuthUser in its Model. By
default, you can use plain TSQLAuthGroup and TSQLAuthUser classes - and if none is defined in the
model, and authentication is enabled, those mandatory classes will be added. But you can inherit from
TSQLAuthGroup and TSQLAuthUser, and define e.g. your own fields, for any custom purpose at Group
or User level."
TSQLAuthUser class contains published properties:
LogonName property: RawUTF8
DisplayName property: RawUTF8
PasswordHashHexa property: RawUTF8
GroupRights property: TSQLAuthGroup
Date: TSQLRawBlobIf I want to have my own table with users I should inherit from TSQLAuthUser, but it will make the original field will be in my class. Is it possible to delete these fields from the model?
I would like to my TMySQLAuthUser class had only those fields which I'll define.
--
best regards
Hi,
When I turn off the server (off-line) and when I call from the client the service registration method:
CalcClient: TSQLHttpClientWinHTTP;
[...]
CalcClient.ServiceRegister ([TypeInfo (ICalculator)], sicShared);
then mORMot mapping connection error to HTML_NOTIMPLEMENTED connection (code 501), why?

At a later stage this error is resolved as:
'TServiceFactoryClient.Create (): ICalculator TSQLRestRoutingREST routing interface or not supported by server:'
by this code in TServiceFactoryClient.Create(...) method:
if not InternalInvoke(SERVICE_PSEUDO_METHOD[imContract],'',@RemoteContract,@Error) then
raise EServiceException.CreateUTF8('%.Create(): I% interface or % routing not '+
'supported by server%',[self,fInterfaceURI,fRest.ServicesRouting,Error]);Why not "connection error"?
--
best regard
Jacek
Thx :-)
Hi,
I'm trying to use CrossPlatform client and encountered a problem when I need to define Connection Timeout.
When I do not set Connection Timeout on Android then the connection to the server off (eg. when server is down) lasts nearly seven minutes! During this time an application is not responding (is suspended). I found a place where it should be set Connection Timeout.
In unit SynCrossPlatformSpecific.pas, in procedure TIndyHttpConnectionClass.URI():
fConnection.ConnectTimeout := MY_CONNECTION_TIMEOUT_VALUE; //in this place I add my code
if Call.Verb='GET' then // allow 404 as valid Call.OutStatus
fConnection.Get(fURL+Call.Url,OutStr,[HTML_SUCCESS,HTML_NOTFOUND]) else
if Call.Verb='POST' then
fConnection.Post(fURL+Call.Url,InStr,OutStr) else
if Call.Verb='PUT' then
fConnection.Put(fURL+Call.Url,InStr) else
if Call.Verb='DELETE' then
fConnection.Delete(fURL+Call.Url) else
raise Exception.CreateFmt('Indy does not know method %s',[Call.Verb]);This setting causes the application returns control at the specified time.
Is possible to add properties to these settings at TSQLRestClientURI? And then pass them along with other parameters by TSQLRestURIParams? Or in any other similar manner?
Another option is to provide your own implementation TAbstractHttpConnection class, by indicating the type of class in any other way than by the following function:
function HttpConnectionClass: TAbstractHttpConnectionClass;
begin
result := TMyHttpConnectionClass;
end;Maybe it would be good to put this function in the TSQLRestClientHTTP class?
TSQLRestClientHTTP = class
[...]
public
function HttpConnectionClass: TAbstractHttpConnectionClass; virtual;
end; Or pass it as a procedural type?
type
TAbstractHttpConnectionClassFunction = function HttpConnectionClass: TAbstractHttpConnectionClass;
TSQLRestClientHTTP = class
private
fHttpConnectionClassFunction : TAbstractHttpConnectionClassFunction;
[...]
public
property HttpConnectionClassFunction : TAbstractHttpConnectionClassFunction write fHttpConnectionClassFunction;
end;The same applies to the Read Timeout parameter.
best regards
Jacek
Hi,
http://blog.synopse.info/post/2012/09/0 … laboration
"On the mORMot roadmap, we added a new upcoming feature, to implement one-way callbacks from the server.
[...]
Some callback interface may be registered via a new EventRegister() method - similar to ServiceRegister() - on both TSQLRestClient and TSQLRestServer sides.
In fact, a callback / event can be seen as a service, but in the reverse order: from server to client."
That was two years ago (september 2012).
Is there a chance that this functionality will soon appear?
kind regards
Jacek