I have a custom DA server written in Delphi with some exposed methods. That is working fine. But i need to setup a timer inside the Windows Service itself that when fired calls one of the exposed methods. Is this possible? and if so, what’s the recommended way to do this?
Maybe a new service, acting as a client, separate to the DA server? A windows service with a timer & delay to call external method in the DA Service would be fairly easy to implement. HTH - Stu
If I understand right, you have DA server that implemented as Windows service and you need to invoke some of your service methods from the server in onTimer event?
If so, you could drop timer component on you TService form and in order to call service method from server you need to create service instance in onTimer event:
procedure TService1.Timer1Timer(Sender: TObject);
var fClassFactory: IROClassFactory;
ClientID : TGUID;
instance: IInterface;
begin
[...]
ClientID:=ROBinMessage.ClientID;
fClassFactory:=GetClassFactory('YourService');
fClassFactory.CreateInstance(ClientID, instance);
(instance as IYourService).YourMethod;
[...]
end;
In my case I am using PooledClassFactory, how to get an instance (previously created) from other service ??
When you call
fClassFactory.CreateInstance(ClientID, instance);
and fClassFactory is a TROPooledClassFactory object it returns to you first service instance fom the pool that is not used.
I didn´t find the method getPooledClassFactory to use with IROPooledClassFactory … But using IROClassFactory with getClassFactory worked even if my service is TROPooledClassFactory; ok?
I didn´t find the method getPooledClassFactory to use with IROPooledClassFactory … But using >IROClassFactory with getClassFactory worked even if my service is TROPooledClassFactory; ok?
Yes, it will works, cause all the types of class factories implement IROClassFactory interface.
Inside: (instance as IYourService).YourMethod; TRORemoteDataModule.fSession is nil and it create another session when using property Session.
Working with sessions in RO is inseparable linked with using of Login service. Read more Documentation | RemObjects Software . So you need to login first and after that read-only Session property will be assigned. I suppose that you do login from client and then want to call service method from server with saved clientId. In that case you should change:
ClientID:=ServerDataModule.Message.ClientID;
to ClientID of necessary client (get it from SessionManager)
And you should add at the beginning of every service method you want to call from server your workaround:
procedure TYourService.YourMethod;
var Session : TROSession;
begin
// use Session as local variable
Session := SessionManager.FindSession(ClientID);
…
end;
But you could also use Local channels in your case. Drop TROLocalServer and TROLocalChannel components on service form (TService1 for example), fill necessary properties and call service methods in such a way:
var log: ILoginService;
serv:IDataService;
usInfo: UserInfo;
begin
log:=CoLoginService.Create(ROMessage, ROLocalChannel1);
b:=log.Login(userId,Password,UsInfo);
serv:=CoDataService.Create(ROMessage, ROLocalChannel1);
serv.YourMethod;
end;
Not elegant, but worked for me… not tried to use local channel because using it I need to authenticate twice (one from client, and another from server) …
Not worked using JSONMessage Message.ClientID is returning another ClientID ! ... Now I am passing ClientID as parameter to my service method:
This is a quite tricky way, messages are being cloned during request processing to enforce thread safety. Actually the message component dropped to the server data module acts as a message settings storage and that instance is not actually used.
not tried to use local channel because using it I need to authenticate twice (one from client, and another from server) ...
Using the local channel seems to be the most straightforward solution for you. You need not to authenticate twice. Once you have a ClientID (aka SessionID) that is logged in you can save it and use for the communication via local channel. Just assign this ClientID to the message instance that is used with local channel.