It's very simple:
If I uncomment the red line, I get an exception at program end on the last line in Main.
Exception class: $C0000005 Message c0000005 ACCESS_VIOLATION
I think, XData sends a logging message but the logger does not more exists
Main
program sngAuth;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
sng.Logging in '..\..\allg\sng.Logging.pas',
sng.Utilities in '..\..\allg\sng.Utilities.pas',
sng.dmServer in '..\Allg\sng.dmServer.pas' {dmServer: TDataModule},
sng.dmDatabase in '..\Allg\sng.dmDatabase.pas' {dmDatabase: TDataModule},
sng.dbSession in '..\Allg\sng.dbSession.pas',
Auth.func.Impl in 'Auth.func.Impl.pas',
Auth.dmDatabase in 'Auth.dmDatabase.pas' {dmDatabaseAuth: TDataModule},
sng.dbSession.Impl in '..\Allg\sng.dbSession.Impl.pas',
sng.consts in '..\Allg\sng.consts.pas',
sng.Filesystem in '..\..\allg\sng.Filesystem.pas',
Auth.dmServer in 'Auth.dmServer.pas' {dmServerAuth: TDataModule},
MessageDialogs in '..\..\allg\MessageDialogs.pas',
sng.Server.Settings in '..\Allg\sng.Server.Settings.pas',
Auth.dbEntities in '..\..\entities\Auth.dbEntities.pas',
Auth.func in '..\..\interfaces\Auth.func.pas',
sng.types in '..\Allg\sng.types.pas';
begin
{$IFDEF DEBUG}
ReportMemoryLeaksOnShutdown := true;
writeln('-- DEBUG ON --');
{$ENDIF}
try
InitLogging( 'sngAuth', [ConsoleLogWriter], ParamStr(0));
Assert( Log <> nil);
Log.Info('create dmDatabase ...');
dmDatabase := TdmDatabaseAuth.Create(nil);
Log.Info('create dmServer ...');
dmServer := TdmServerAuth.Create(nil);
Sleep(1000);
dmServer.StartServer;
var cmd : string;
cmd := '';
repeat
writeln('');
writeln(' Programmende mit xxx <ENTER>: ');
writeln('');
readln(cmd);
until cmd = 'xxx';
dmServer.StopServer;
dmServer.Free;
dmDatabase.Free;
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
readln;
end;
end;
end.
dmServer
unit sng.dmServer;
// Basis Datenmodul für Kommunikation XData. Jeweilige Projekte davon ableiten.
interface
uses
System.SysUtils, System.Classes, System.Rtti, Data.DB,
Sparkle.HttpSys.Server, Sparkle.HttpServer.Context, Sparkle.HttpServer.Module,
Sparkle.Middleware.Cors, Sparkle.Middleware.Compress, Sparkle.Middleware.Logging,
XData.Server.Module, XData.Comp.ConnectionPool, XData.Comp.Server, XData.OpenAPI.Service,
Aurelius.Drivers.Interfaces,
sng.dmDatabase, Aurelius.Comp.Connection, Sparkle.Comp.JwtMiddleware, Sparkle.Comp.LoggingMiddleware, Sparkle.Comp.Server,
Sparkle.Comp.CorsMiddleware, Sparkle.Comp.HttpSysDispatcher, Sparkle.Comp.GenericMiddleware;
type
TdmServer = class(TDataModule)
SparkleHttpSysDispatcher: TSparkleHttpSysDispatcher;
XDataServer: TXDataServer;
XDataConnectionPool: TXDataConnectionPool;
XDataServerCORS: TSparkleCorsMiddleware;
XDataServerJWT: TSparkleJwtMiddleware;
XDataServerGeneric: TSparkleGenericMiddleware;
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
procedure XDataServerGenericMiddlewareCreate(Sender: TObject; var Middleware: IHttpServerMiddleware);
private
function GetActive: boolean;
public
property Active : boolean read GetActive;
procedure StartServer;
procedure StopServer;
end;
var
dmServer: TdmServer;
implementation
{%CLASSGROUP 'System.Classes.TPersistent'}
{$R *.dfm}
uses
sng.Server.Settings,
sng.Utilities,
sng.Logging;
procedure TdmServer.DataModuleCreate(Sender: TObject);
//var
// Logging: TLoggingMiddleware;
begin
XDataServer.BaseUrl := cBasisURL;
XDataConnectionPool.Connection := dmDatabase.AureliusConnection;
XDataServerJWT.Secret := constSophaKey32;
// Logging := TLoggingMiddleware.Create( XDataLogger);
// XDataServer.MiddlewareList.Add( Logging);
end;
procedure TdmServer.DataModuleDestroy(Sender: TObject);
begin
StopServer;
end;
function TdmServer.GetActive: boolean;
begin
result := SparkleHttpSysDispatcher.Active;
end;
procedure TdmServer.StartServer;
begin
RegisterOpenApiService;
SparkleHttpSysDispatcher.Start;
end;
procedure TdmServer.StopServer;
begin
SparkleHttpSysDispatcher.Stop;
end;
procedure TdmServer.XDataServerGenericMiddlewareCreate(Sender: TObject; var Middleware: IHttpServerMiddleware);
begin
Middleware := TLoggingMiddleware.Create( XDataLogger);
end;
end.
Logging
unit sng.Logging;
interface
uses
System.SysUtils,
System.Rtti,
Bcl.Logging,
Delphiprofi.FDK.Logging;
type
TSetOfLogger = set of ( ConsoleLogWriter, FileLogWriter);
TXDataLogger = class(TInterfacedObject, Bcl.Logging.ILogger)
procedure Error(const AValue: TValue); overload;
procedure Warning(const AValue: TValue);
procedure Info(const AValue: TValue); overload;
procedure Trace(const AValue: TValue);
procedure Debug(const AValue: TValue); overload;
end;
var
GlobalConsoleLogger : IWriteLog;
GlobalFileLogger : IWriteLog;
Log : ILog = nil;
XDataLogger : TXDataLogger;
procedure InitLogging( AProgName : string; AStandardLogger : TSetOfLogger; AFilename : string = '');
implementation
Uses
Delphiprofi.FDK.Logging.Consolelogger,
Delphiprofi.FDK.Logging.FileLogger;
procedure InitLogging( AProgName : string; AStandardLogger : TSetOfLogger; AFilename : string = '');
begin
// if (Log = nil) and (AStandardLogger <> []) then
begin
if ConsoleLogWriter in AStandardLogger then
GlobalConsoleLogger := TLogFactory.AddQueuedWriter(TConsoleLogWriter.Create);
if (FileLogWriter in AStandardLogger) and (AFilename <> '') then
GlobalFileLogger := TLogFactory.AddQueuedWriter(TFileLogWriter.Create(AFilename, true));
//Log := TLogFactory.GetLogger(NIL);
Log.Debug( '');
Log.Debug( AProgName + ': Start logging ...');
end;
end;
{ TXDataLogger }
procedure TXDataLogger.Debug(const AValue: TValue);
begin
Log.Debug( AValue.ToString);
end;
procedure TXDataLogger.Error(const AValue: TValue);
begin
Log.Error( AValue.ToString);
end;
procedure TXDataLogger.Info(const AValue: TValue);
begin
Log.Info( AValue.ToString);
end;
procedure TXDataLogger.Trace(const AValue: TValue);
begin
Log.Verbose( AValue.ToString);
end;
procedure TXDataLogger.Warning(const AValue: TValue);
begin
Log.Warn( AValue.ToString);
end;
initialization
Log := TLogFactory.GetLogger(NIL);
XDataLogger := TXDataLogger.Create;
finalization
//XDataLogger.Free;
end.