Jump to content

Recommended Posts

Posted

I need to start a TUniTimer in the ServerModule that will check the active sessions of the application and perform some processes in the database. But when I try to do as below I get an Access Violation error:

procedure TServerModule.CleanupTimerEvent(Sender: TObject);
var
   myQuery : TFDQuery;
begin
   myQuery := TFDQuery.Create(Self);
   myQuery.Connection := MainModule.SQLConnection; (here the Access Violation error occurs).
end;

This is just a simple example. In my real case I call a procedure and inside it I access the MainModule.SQLConnection.

What is the correct way to access it? After doing a lot of research here on the Forum, I have tried several approaches but without success.

Posted
On 3/10/2025 at 8:13 PM, fabiotj said:

I need to start a TUniTimer in the ServerModule ...

Goodmorning Fabio,

You have two problems here :

1. First is about Sessions :

- ServerModule has the control of all sessions

- You can not control one session with ServerModule

- So, the simple fact of writing things on ServerModule, that affect one session will cause an AV (acces violation) Like :

UniMainModule...

UniMainForm...

 

To better understand : 

You can not do this :

procedure TUniServerModule.UniGUIServerModuleCreate(Sender: TObject);
begin
  MainModule.UniMainModule.v1:=11;
 // Or UniMainForm...
end;

(v1 is declared on UniMainModule)

For doing this, we are asking to the server to Set a variable v1 on a session (but wich session ???) that is why the AV appears.

 

 

2. Second is about Timer :

- UniTimer is dedicated for Sessions  (MainForm, UniMainModule, ...)

- UniThreadTimer is dedicated for ServerModule. 

You have to lock and release it before using your procedures inside :

procedure TUniServerModule.UniThreadTimer1Timer(Sender: TObject);
begin
  UniThreadTimer1.Lock;
  try
  //==============
    Procedure_DoingSomeThings;
  //==============
  finally
    UniThreadTimer1.Release;
  end;
end;

 

  • Like 1
Posted

Thank you very much for the explanation.

ThreadTimer = OK.

But,

1) Can I have an exclusive FDConnection (although I know it is not indicated) in the ServerModule to perform a simple Query operation?

2) Or is there still a way to specify which section I want to use so that through it I can access the FDConnection of the MainModule?

    Something like: myQuery.Connection := EspecSession(SessionID).MainModule.SQLConneciton;

Posted

I managed to do it with a direct connection to the ServerModule. Thanks Eduardo.


If someone later reads this post and knows how to access a specific MainModule of a session or even how to access anything in a specific session, I would appreciate it because it could be useful in the future.

Posted
2 hours ago, fabiotj said:

 it could be useful in the future.

Sure, ... i think Websokets is a keyword.

I didn't play with it, but i already hear a such approach.

  • Upvote 1
Posted

Yes, 
I tried websocket before using the current method, but when I went to implement the dedicated websocekt server to run in conjunction with HyperServer I encountered many local problems to run as a Windows service etc... so due to urgency I gave up, but WebSocket really is very good, my project worked with it but not on HyperServer because it is Multi-Instance.

Posted
7 hours ago, fabiotj said:

Something like: myQuery.Connection := EspecSession(SessionID).MainModule.SQLConneciton;

The Classical method in Unigui for connection to a DB, is to connect on UniMainModule.OnCreate Event for each new session (using pooling).

Why are you trying to connect a second time from UniSeverModule and pointing to this UniMainModule connection ?

What is the pupose ?

Posted (edited)
8 hours ago, fabiotj said:

I managed to do it with a direct connection to the ServerModule. Thanks Eduardo.

Instead of putting the sqlConnection in the ServerModule  I do it in a separate DataModule that I reference from the ServerModule. That way I avoid cluttering the ServerModule with database handling functions. I also use this to handle incoming API requests.

e.g.
 

unit ServerModule;

interface

uses
  Classes, SysUtils, uniGUIServer, uniGUIMainModule, uniGUIApplication,  uIdCustomHTTPServer,
  uniGUITypes,  MainModule, uniThreadTimer, uniGuiServerUtils, SyncObjs;

type
  TUniServerModule = class(TUniGUIServerModule)
....
.....
end;

function UniServerModule: TUniServerModule;

implementation

{$R *.dfm}

uses
  UniGUIVars,
  uIdGlobal,
//My data module
  dData;

...
...

procedure TUniServerModule.TimerTimer(Sender: TObject);
begin
  Timer.Lock;
  try
//*** Call datamodule methods
    dmDB.CheckConnections;
  finally
    Timer.Release;
  end;
end;

function TUniServerModule.HandleHTTPPostRequest(var wPostBody: String; wIPAddress : String;
  var wRespText: String) : Integer;
begin
  Timer.Emanled := false;
  try
//*** Call datamodule methods
    Result := dmDB.HandlePostRequest(wPostBody, wIPAddress, wRespText);
  finally
    Timer.Enabled := True;
  end;
end;


procedure TUniServerModule.UniGUIServerModuleHTTPCommand(
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
  var Handled: Boolean);
var
  aParams : String;
  aStream : TStream;
  aPostBody : string;
  aHTML : String;
  aData : TStringList;
  aRespNo : Integer;
  aRespText : String;
  aIPAddress : String;
begin
  if (ARequestInfo.Command = 'GET') and (ARequestInfo.URI = '/') then
  begin
....
....
  end
  else if ARequestInfo.Command = 'POST' then
  begin
    aParams := UpperCase(ARequestInfo.URI);
    aStream := ARequestInfo.PostStream;
    if assigned(aStream) then
    begin
      aStream.Position := 0;
      aPostBody := ReadStringFromStream(aStream);
      aRespNo := HandleHTTPPostRequest(aPostBody, aIPAddress, aRespText);
      AResponseInfo.ResponseNo := aRespNo;
      AResponseInfo.FreeContentStream := True;
      AResponseInfo.ContentStream := TStringStream.Create(aPostBody);
      AResponseInfo.ContentLength := AResponseInfo.ContentStream.Size;
      AResponseInfo.ContentType := 'application/json';
      Handled := True;
    end
  end
end;

 

Edited by Norm
Typo
  • Thanks 1
  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...