AnsiString/RoAnsiString/read stream error and more

I’ve read all topics about it. But i’ve wasted days now and have no idea whats the problem.

  1. There is a huge client/server project made with Delphi XE2 and RO 7.0.75.1117
  2. I have to migrate it to Delphi 11.1 and RO 10.0.0.1537
  3. First i have to create the new server. This one has to be replaced first.
  4. Server has to work with the old clients. Later on step by step clients will be replaced.
    What i did:
    Open the existing RODL with new RO Version an generate Intf and Invk. All Ansistring Stuff has been replaced with ROAnsiString and Legacy __Message.Read(‘CustomMessage’, System.TypeInfo(ROAnsiString), l_CustomMessage, [paAsAnsiString]); This looked good to me. I had a lot to change on the EventWriter side on the server.
    Now: Most is working. But particularly with events and more specific when the parameter ROAnsiString is direct in the function i’ve get those read stream errors on the client side. But not if the String is inside a TROComplex type. Even the client has been compiled with Delphi 11.1 and new Interface. Whats wrong here? With the “old” server everything is fine. Also with the new Client. Have you got an idea about. In my opinion the problem is on the server side.

One example of one eventsink function:

Rodl definition:

</Interfaces>
</EventSink>
<EventSink Name="VideoCommandV3" UID="{CB4EC84F-C790-4F6C-87EE-EA3EA0CC0ED1}">
<Interfaces>
<Interface Name="Default" UID="{A3AE0B50-CE5A-43E4-83B9-74597114D048}">
<Operations>
</Operation>
<Operation Name="ArchiveSwitch" UID="{073EA618-D22E-4699-96F6-99F53F7FAE73}">
<Parameters>
<Parameter Name="Camera" DataType="Integer" Flag="In" />
<Parameter Name="Date" DataType="DateTime" Flag="In" />
<Parameter Name="Workstation" DataType="AnsiString" Flag="In" />
<Parameter Name="CustomMessage" DataType="AnsiString" Flag="In" />
</Parameters>
</Operation>

old interface:

{ IVideoCommandV3 }
  IVideoCommandV3 = interface
    ['{A3AE0B50-CE5A-43E4-83B9-74597114D048}']
    procedure ArchiveSwitch(const Camera: Integer; const Date: DateTime; const Workstation: AnsiString; const CustomMessage: AnsiString);
procedure TVideoCommandV3_Invoker.Invoke_ArchiveSwitch(__EventReceiver : TROEventReceiver; const __Message : IROMessage; const __Target : IUnknown);
var
  Camera: Integer;
  Date: DateTime;
  Workstation: AnsiString;
  CustomMessage: AnsiString;
begin

    __Message.Read('Camera', System.TypeInfo(Integer), Camera, []);
    __Message.Read('Date', System.TypeInfo(DateTime), Date, []);
    __Message.Read('Workstation', System.TypeInfo(AnsiString), Workstation, []);
    __Message.Read('CustomMessage', System.TypeInfo(AnsiString), CustomMessage, []);

    (__Target as IVideoCommandV3).ArchiveSwitch(Camera, Date, Workstation, CustomMessage);
end;

new interface:

  IVideoCommandV3 = interface(IROEventSink)
  ['{A3AE0B50-CE5A-43E4-83B9-74597114D048}']
    procedure ArchiveSwitch(const Camera: Integer; const Date: DateTime; const Workstation: ROAnsiString; const CustomMessage: ROAnsiString);
procedure TVideoCommandV3_Invoker.Invoke_ArchiveSwitch(__EventReceiver: TROEventReceiver; const __Message: IROMessage; const __Target: IUnknown);
var
  l_Camera: Integer;
  l_Date: DateTime;
  l_Workstation: ROAnsiString;
  l_CustomMessage: ROAnsiString;
begin

  __Message.Read('Camera', System.TypeInfo(Integer), l_Camera, []);
  __Message.Read('Date', System.TypeInfo(DateTime), l_Date, [paIsDateTime]);
  __Message.Read('Workstation', System.TypeInfo(ROAnsiString), l_Workstation, [paAsAnsiString]);
  __Message.Read('CustomMessage', System.TypeInfo(ROAnsiString), l_CustomMessage, [paAsAnsiString]);
  (__Target as IVideoCommandV3).ArchiveSwitch(l_Camera, l_Date, l_Workstation, l_CustomMessage);

end;

old event call:

procedure TServerDataModule.PVisArchiveSwitch(camera: Integer; date: TDateTime; workstation: String; CustomMessage : String);
var
  ev3 : IVideoCommandV3_Writer;
begin
  ev3 := (ROEventRepository as IVideoCommandV3_Writer);
  ev3.SessionList.Clear;
  ev3.ExcludeSessionList := false;
  ev3.ArchiveSwitch(EmptyGUID, camera, date, workstation, CustomMessage);
end;

new event call:

procedure TServerDataModule.PVisArchiveSwitch(camera: Integer; date: TDateTime; workstation: ROAnsiString; CustomMessage : ROAnsiString);
begin
  RoEventRepository.GetWriter<IVideoCommandV3>(EmptyGUID).Event.ArchiveSwitch(camera, date, workstation, CustomMessage);
end;

With this call i get a stream read (length) error on client side. At both (old XE2/old RO and new Delphi 11 new RO) clients. Fired with the XE2 Server (old RO) in both clients o.k. What did i miss here?
Any help is highly appreciated. I could send you the old and new interface and the rodl if this is helpul.

Hi,

I see one issue here:
you said that you have RODL-based server, but this call is related to CodeFirst-based server:

if you still have .RODL after updating, you should use old code for events:

procedure TServerDataModule.PVisArchiveSwitch(camera: Integer; date: TDateTime; workstation: String; CustomMessage : String);
var
  ev3 : IVideoCommandV3_Writer;
begin
  ev3 := (ROEventRepository as IVideoCommandV3_Writer);
  ev3.SessionList.Clear;
  ev3.ExcludeSessionList := false;
  ev3.ArchiveSwitch(EmptyGUID, camera, date, workstation, CustomMessage);
end;

Oh my goodness. Its working like this!
A question: why is it working to 99% the other (code first) way? Is it a bug or a feature?
Another question: If i would migrate the server to code first - will the old clients still work?

Thank you very much. I should have asked earlier…

Hi,

afair, only event processing is differ, other [user] code is compatible between RODL and CodeFirst modes.
Check our samples that send event to clients like SuperHTTP Chat sample (Delphi) or SuperTCP Chat sample (Delphi)

it doesn’t matter for client-side what server type is used. so you can migrate to CodeFirst w/o any issues, except you have to update code that send events