#1 2015-12-11 09:28:13

Wideyu
Member
Registered: 2010-08-25
Posts: 2

ServiceContext.Request become nil cause error

@ab

i m learning how to control mORMot, not sure any wrong with my code:

program Project1;

{$APPTYPE CONSOLE}

uses
  mORMot, mORMotSQLite3, SynSQLite3Static, System.SysUtils;

type
  IRemote = interface(IInvokable)
    ['{48FCB3D5-0992-48A4-ACFD-13FE652802FB}']
    function TestOK: TID;
    function TestError: TID;
  end;
  TRemote = class(TInterfacedObject, IRemote)
  private
    fClient: TSQLRestClientDB;
  public
    procedure AfterConstruction; override;
    function TestOK: TID;
    function TestError: TID;
  end;

var
  rServer, lServer: TSQLRestServerDB;
  rClient: TSQLRestClientDB;
  fRemote: IRemote;

procedure TRemote.AfterConstruction;
begin
  inherited;
  fClient := TSQLRestClientDB.Create(lServer);
end;

function TRemote.TestOK: TID;
var
  aContext: TSQLRestServerURIContext;
begin
  aContext := ServiceContext.Request;
  fClient.ServerTimeStampSynchronize;
  ServiceContext.Request := aContext;
  result := ServiceContext.Request.SessionUser;
end;

function TRemote.TestError: TID;
begin
  fClient.ServerTimeStampSynchronize;
  //ServiceContext.Request=nil here
  result := ServiceContext.Request.SessionUser;
end;

begin
  lServer := TSQLRestServerDB.Create(TSQLModel.Create([]), 'local.db3', false);
  lServer.CreateMissingTables();

  rServer := TSQLRestServerDB.Create(TSQLModel.Create([]), 'remote.db3', true);
  rServer.CreateMissingTables();
  rServer.ServiceRegister(TRemote,[TypeInfo(IRemote)],sicClientDriven);

  rClient := TSQLRestClientDB.Create(rServer);
  rClient.SetUser('User', 'synopse');
  rClient.ServiceRegisterClientDriven(TypeInfo(IRemote), fRemote);

  Writeln('TestOK result: ');
  Writeln(fRemote.TestOK);
  
  try
    Writeln('TestError result: ');
    Writeln(fRemote.TestError);
  except
    on E: Exception do
      writeln(E.Message);
  end;
  readln;
end.

console output

TestOK result:
3

TestError result:
TInterfacedObjectFakeClient.FakeCall(IRemote.TestError) failed: '{
"errorCode":500,
"error":
{"EAccessViolation":{"EAccessViolation":"Access violation at address 00660ADF in
 module 'Project1.exe'. Read of address 00000120"}}
}'

Last edited by Wideyu (2015-12-11 09:44:37)

Offline

#2 2015-12-11 11:16:10

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,666
Website

Re: ServiceContext.Request become nil cause error

I guess this is because you may be mixing things up.

fClient.ServerTimeStampSynchronize is also a client call, so the ServiceContext is reset when fClient.ServerTimeStampSynchronize finishes.

Some other points:
- Do not use TInterfacedObject and override AfterConstruction: use TInterfacedObjectWithCustomCreate or TInterfacedObjectAutoCreateFields, and override the virtual Create constructor;
- You are using a global variable to locale the main server, this is not SOLID at all.

To make proper IoC:
- Use ServiceContext.Request.Server to access the server instance directly;
- Define some server-side SOA services, then inherit your TRemote service from TInjectableObject, and all needed services as published interface properties: any interface published property would be automatically injected when the TRemote instance would be created.

Offline

#3 2015-12-11 11:50:51

Wideyu
Member
Registered: 2010-08-25
Posts: 2

Re: ServiceContext.Request become nil cause error

Thanks for proper points and IoC. But Need some pratice to understand TInterfacedObjectWithCustomCreate or TInterfaceObjectAutoCreateFields and TInjectableObject tongue

Indeed fClient used as a proxy to fetch data from lServer, to feed TRemote@rServer to the rClient. I m confused why fClient clear the rServer's serviceContext?

Offline

#4 2015-12-11 15:06:19

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,666
Website

Re: ServiceContext.Request become nil cause error

Yes it does, since you are running a client operation within another client operation, and the context comes from a shared threadvar....

Offline

Board footer

Powered by FluxBB