Hi
I am trying to create a log visualizer in the client to see events of the server. I’m using Delphi and Remoting SDK.
What I am struggling now is in how to send real time data to client.
Is there any example of how to do it?
Does it slows down too much the server?
EvgenyK
(Evgeny Karpov)
October 29, 2024, 12:37pm
2
Hi,
you can examine these samples:
Hi
I verified the sample (HTTP Chat codefirst) and tried to implement a simple event/subscribe in our current infrastructure.
We already have codefirst Server/client implemented in production so we tried to implement just a simple method (tried to mimic sample’s login method).
We created an InMemorySessionManager and an EventRepository and hooked them up:
FEventRepository.SessionManager := FSessionManager;
FEventRepository.Message := FRoMessage; // server's FRoMessage
In our RoDataModule descendent, we coded RORemoteDataModuleCreate event to tell RO infra which session/event manager:
procedure TautenticacaoService.RORemoteDataModuleCreate(Sender: TObject);
begin
EventRepository := getServer.EventRepository;
SessionManager := getServer.SessionManager;
end;
When a client runs server’s code, it returns an “Abstract error” whenever we tried to get Session ou ClientID fields:
function TautenticacaoService.Login(
const aUserID: Unicodestring): Unicodestring;
var
ev: IRoEventWriter<IHTTPChatEvents>;
begin
Session.Values['UserID'] := aUserID;
result := GUIDToString(Session.SessionID); // ABSTRACT ERROR
FCS.Enter;
try
RegisterEventClient(ClientID, 'HTTPChatEvents'); // ABSTRACT ERROR
RegisterEventClient(ClientID, 'HTTPBroadCastEvents');
ev := (EventRepository.GetWriter<IHTTPChatEvents>(Session.SessionID));
ev.ExcludeSender := false; //para enviar para ele mesmo
ev.Event.OnSendMessage(aUserID, 'teste', false );
finally
FCS.Leave;
end;
end;
Should I have to set something else in order to make SessionManager work?
EvgenyK
(Evgeny Karpov)
December 10, 2024, 8:05am
4
Hi,
Can you create a simple testcase that reproduces this issue, pls?
you can attach it hare or drop email to support@
I created and zipped it but I couldn’t attach it here (it shows an error). I will send it to support. Could you, please, verify if you have received?
The error in the sample is here:
function TchatService.Login( aUserId: string ) : string;
var
ev: IRoEventWriter<IHTTPChatEvents>;
begin
Session.Values['UserID'] := aUserID;
result := GUIDToString(Session.SessionID);
FCS.Enter;
try
RegisterEventClient(ClientID, EID_HTTPChatEvents);
ev := (serverDataModule.EventRepository.GetWriter<IHTTPChatEvents>(Session.SessionID));
ev.ExcludeSender := false;
ev.Event.OnSendMessage(aUserID, 'teste', false ); // ABSTRACT ERROR
finally
FCS.Leave;
end;
end;
EvgenyK
(Evgeny Karpov)
December 11, 2024, 12:38pm
7
Hi,
as expected. TROEventRepository is base class that contains abstract methods that are implemented in descendants.
try to use TROInMemoryEventRepository instead:
fEventRepository := TROInMemoryEventRepository.Create(self);
Hi
Now it runs flawlessly but I don’t receive any messages.
At client, the code is:
TClientForm = class(TForm, IHttpChatEvents)
Message: TROBinMessage;
Channel: TROWinInetHTTPChannel;
RORemoteService: TRORemoteService;
Button1: TButton;
eventReceiver: TROEventReceiver;
mmMessages: TMemo;
procedure Button1Click(Sender: TObject);
private
procedure OnSendMessage(const aSenderUserID: Unicodestring; const aMessage: Unicodestring; const aIsPrivateMessage: Boolean);
{ Private declarations }
public
{ Public declarations }
end;
procedure TClientForm.Button1Click(Sender: TObject);
var
userId: string;
begin
EventReceiver.RegisterEventHandlers([EID_HTTPChatEvents], [Self]);
{ Starts polling }
EventReceiver.Active := TRUE;
userId := (RORemoteService as IchatService).Login('MARK');
showMessage(userId);
end;
and
procedure TClientForm.OnSendMessage(const aSenderUserID,
aMessage: Unicodestring; const aIsPrivateMessage: Boolean);
begin
mmMessages.Lines.Add(aMessage); //DON'T ACCESS HERE
end;
EvgenyK
(Evgeny Karpov)
December 11, 2024, 2:22pm
9
Hi,
You haven’t assigned EventRepository
for your service so events won’t be sent …
add
procedure TchatService.RORemoteDataModuleCreate(Sender: TObject);
begin
Self.EventRepository := ServerDataModule.eventRepository;
end;
30942.zip (222.8 KB)
Hi
My mistake! But even adding that, I don’t receive any messages.
Does the zip attached is a working sample?
I tried to compile it but it complains that there is no uRONullable in chatLibrary_intf
EvgenyK
(Evgeny Karpov)
December 11, 2024, 3:14pm
12
Hi,
what version of Remoting SDK are you using?
try to regenerate files from .RemoteRODL
I am using version 10.0.0.1585
I couldn’t generate it because I cannot build server exe in order to update the interface.
EvgenyK
(Evgeny Karpov)
December 11, 2024, 3:58pm
14
why you can’t build server-side?
Code-First server-side doesn’t require _Intf
for building.
you can replace constant EID* with it’s value like
RegisterEventClient(ClientID, 'HTTPChatEvents');
In order to use constant EID*, I had to use _intf at server function. Replacing them with its values, it worked and sent messages flawlessly.
Thanks
Just a small question: RO generates this constant
const EID_HTTPLogEvents: string = 'HTTPLogEvents';
in the interface file from where?
I have this event sink:
[ROEventSink]
IHTTPLogEvents = interface(IROEventSink)
['{75F9A466-518A-4B09-9DC4-9272B1EEFD95}']
procedure OnSendLog(const aMessage: UnicodeString );
end;
It generates ‘HTTPLogEvents’ constant from the name of the interface?
EvgenyK
(Evgeny Karpov)
December 16, 2024, 8:17am
17
Hi,
You can specify event sink as
[ROEventSink("myname")]
IHTTPLogEvents = interface(IROEventSink)
['{75F9A466-518A-4B09-9DC4-9272B1EEFD95}']
procedure OnSendLog(const aMessage: UnicodeString );
end;
in this case, it will be generates as EID_myname = 'myname';
otherwise, I
prefix will be removed and it will be generated as EID_HTTPLogEvents = 'HTTPLogEvents'
.
Great
Last question, in order to stop listening to all interfaces, could I use:
UnregisterEventClient(ClientID);
EvgenyK
(Evgeny Karpov)
December 16, 2024, 1:13pm
19
Hi,
yes
RegisterEventClient
and UnregisterEventClient
methods work in pair
Hi
Another small question: When someone is connected to a server (TInMemorySessionManager) and server is shutdown (without client disconnecting), server was showing an exception when it was freeing TInMemorySessionManager.
After adding this line, the server does not complain:
FSessionManager.ClearSessions(false);
So, two questions:
Is it OK to do that? we’re hooking this line to destroy event in the form that has TRoHttpServer.
Is there a way to send a message to clients just before that in order to clean up things there?
We tried to hook an eventSink and send a message just before destroying the server but the message never gets there:
procedure TServerHttp.desconectAllSessions();
var
ev: IRoEventWriter<IHTTPLogEvents>;
begin
inherited;
ev := (FEventRepository.GetWriter<IHTTPLogEvents>(EmptyGUID));
ev.Event.OnMandatoryClose( 'Server is closing...');
FSessionManager.ClearSessions(false);
end;