You are not logged in.
Hi guys,
I would like some suggestions on how best to access ORM inside a service that is not registred with main server ...
In my case I need to disable external access to the ORM so I have a TSQLRestServerFullMemory server created and started with MVC application.
//A "Dummy" server to avoid UI access to ORM
FDummyServer := TSQLRestServerFullMemory.Create(TSQLModel.Create([],'test'),False);
FDummyServer.ServiceRegister(TMyService,[TypeInfo(IMyService)],sicShared);
inherited Start(FDummyServer,TypeInfo(ITestApplication));
fMainRunner := TMVCRunOnRestServer.Create(Self);
FHTTPServer := TSQLHttpServer.Create('8080',FDummyServer,useHttpApiRegisteringURI);
FHTTPServer.RootRedirectToURI('test/default');
FDummyServer.RootRedirectGet := 'test/default';
//My real server with access to ORM
FInternalRestModel := TSQLRestServerDB.Create(CreateModel,ChangeFileExt(ExeVersion.ProgramFileName,'.db'), False);
FInternalRestModel.DB.Synchronous := smNormal;
FInternalRestModel.DB.LockingMode := lmExclusive;
FInternalRestModel.CreateMissingTables;
And this interface.
IMyService = interface(IInvokable)
['{E956F65D-7FAE-4BDD-9210-111E088284F5}']
function MyResponse(const MyString: RawUTF8): RawUTF8;
end;
TMyService = class(TInjectableObjectRest, IMyService)
function MyResponse(const MyString: RawUTF8): RawUTF8;
end;
...
function TMyService.MyResponse(const MyString: RawUTF8): RawUTF8;
begin
...
Self.Server <- Point to "Dummy" server TSQLRestServerFullMemory
I need access to FInternalRestModel (TSQLRestServerDB)
end;
How to access the real server inside this services without breaking some framework design principle?
Last edited by macfly (2019-04-29 22:30:44)
Offline
For sicShared, the easiest is to just use ServiceRegister() and provide a TMyService instance with its dependencies injected, instead of just specifying the TMyService class and letting the framework create the instance.
Online
Thanks ab!
Offline
Just to take the doubt...
Since TSQLRestServer classes are not implemented with injectable interfaces, I need to create a intermediary class, for this, rigth?
Or is there a direct way?
Intermediary class to inject the restserver:
IMyRestInject = interface(IInvokable)
['{XYZ...}']
function GetRestModel : TSQLRestServerDB;
property RestModel : TSQLRestServerDB read GetRestModel;
end;
TMyRestInject = class(TInterfacedObject, IMyRest)
protected
FRestModel : TSQLRestServerDB;
public
constructor Create(ARestModel : TSQLRestServerDB);
function GetRestModel : TSQLRestServerDB;
end;
TMyService = class(TInjectableObjectRest, IMyService)
private
FRest: IMyRestInject;
public
function MyResponse(const MyString: RawUTF8): RawUTF8;
published
property Rest: IMyRestInject read FRest write FRest;
end;
function TMyService.MyResponse(const MyString: RawUTF8): RawUTF8;
begin
Result := Self.Rest.RestModel.DB.FileName; //uses injected restserver
end;
Application Startup
...
FModel := CreateModel;
FInternalRestModel := TSQLRestServerDB.Create(FModel,ChangeFileExt(ExeVersion.ProgramFileName,'.db'), False);
FInternalRestModel.DB.Synchronous := smNormal;
FInternalRestModel.DB.LockingMode := lmExclusive;
FInternalRestModel.CreateMissingTables;
FDummyServer := TSQLRestServerFullMemory.Create(TSQLModel.Create([],'test'),False);
//Created to inject FInternalRestModel
AMyRestInject := TMyRestInject.Create(FInternalRestModel);
AMyService := TMyService.CreateInjected([],[],[AMyRestInject ]);
FDummyServer.ServiceRegister(AMyService,[TypeInfo(IMyService)]);
Last edited by macfly (2019-04-30 19:18:52)
Offline
You are confusing interfaces and class injection.
If you inject a TSQLRestServerDB via a constructor parameter, no need to use interface injection.
No need to create an intermediate class anyway, in your use case.
Interface injection is a good idea only if you define your sub-services as dependencies, and want to mock/stub them, or use a remote service.
Online
You're right.
This code became redundant.
The idea would be to put all the dependencies in this interface ..
But instantiating directly is actually better and simpler.
Thanks
Offline