2015-12-01 18 views
5

Ich habe Probleme mit der Ausnahmebehandlung in meinem Datasnap REST Service (Delphi XE3, aber auch mit Delphi 10 Seattle). Ich habe im Laufe der Jahre ein halbes Dutzend Windows-Dienste geschrieben und schließe immer eine TApplicationEvents-Komponente ein, damit ich alle Anwendungsausnahmen im Windows-Ereignisprotokoll protokollieren kann.Ausnahmebehandlung in Delphi Datasnap REST Server

Dieses Verhalten tritt jedoch nicht mit einem Datasnap-Dienst auf. Das TApplicationEvents.OnException-Ereignis wird nie ausgelöst, daher nehme ich an, dass etwas anderes die Ausnahme ausnutzt und es behandelt, bevor es hier ankommt.

Die Ausnahme wird im Ergebnis der Web-Service-Methode angezeigt, was gut ist, weil ich damit auf der Client-Seite zumindest etwas anzeigen kann, aber ich möchte es auch vorher abfangen, damit ich es könnte verschiedene serverseitige Ausnahmen behandeln.

Der einzige konsistente Weg, den ich bisher geschafft habe, besteht darin, jede einzelne Methode in einen try..except Block zu wickeln und die Ausnahme in jeder Methode zu behandeln, bevor die Ausnahme erneut ausgelöst wird. Mit einem Web-Service von 20 Methoden und wachsend, wird dies nicht wirklich skalieren.

Ich habe auch versucht, die OnError, OnTrace und andere Ereignisse der einige der Datasnap Komponenten (TDSServer, TDSHTTPService, TDSTCPServerTransport, etc.) zu implementieren, aber diese scheinen auch nie gefeuert werden.

Hat irgendjemand so etwas gefunden, bitte?

+0

Verwandte (für Java): [So greifen Sie auf nicht abgefangene Ausnahmen in einer Java-Servlet-Webanwendung] (http://stackoverflow.com/questions/7410414/how-to-grab-uncaught-exceptions-in-a-java -servlet-web-application) Vielleicht ist eine ähnliche Lösung möglich. (Wenn in Datasnap ein globaler Anforderungsfiltermechanismus vorhanden ist) – mjn

Antwort

0

Tl; Dr: es ist nicht brauchbar implementiert (in 10.1 Berlin).

Ich stieß auf das gleiche Problem und nach Durchlesen vieler Quellen fand ich keine praktische Lösung.

So eine exemplarische (my) Stacktrace würde wie folgt aussehen:

MyClass::MyServerMethod() 
/* skipping some funny unimportant RTTI/TValue handling here */ 
System::Rtti::TRttiMethod::Invoke 
Dsreflect::TDSMethod::Invoke(TObject, TDSMethodValues) 
TDSServerConnectionHandler::DbxExecute(const TDBXExecuteMessage) 
TDSServerCommand::DerivedExecuteUpdate 
TExecuteCallback 
TDSService::Execute(const string, const TRequestCommandHandler, TExecuteCallback) 
TDSService::ProcessRequest(const string, const TRequestCommandHandler, TExecuteCallback) 
TDSRESTService::ProcessREST(const string, const string, const TArray<Byte>, const TRequestCommandHandler) 
TDSRESTService::ProcessGETRequest(const string, TStrings, TArray<Byte>, TRequestCommandHandler) 
TDSRESTServer::DoDSRESTCommand(TDSHTTPRequest, TDSHTTPResponse, string) 
TDSRESTServer::DoCommand(TDSHTTPContext, TDSHTTPRequest, TDSHTTPResponse) 
Dshttpwebbroker::TDSRESTWebDispatcher::DispatchRequest(TObject, Web::Httpapp::TWebRequest, Web::Httpapp::TWebResponse) 

Hinweis: Dies hängt ganz von Ihrer Nutzung von DataSnap. Im obigen Fall werden Anforderungen über TDSRESTWebDispatcher (kommend von TIdCustomHTTPServer) an die DataSnap-API übergeben.

  • jedes Exception in einem ServerMethod angehoben wird in TDSService::ProcessRequest enden.
  • In diesem Verfahren wird jeder Exception gefangen und nur Message wird zu einem TRequestCommandHandler->CommandList hinzugefügt.
  • Weiter unten wird die Message als JSON/DBX-Befehl an den Ausgang geschrieben.

So können wir nie die Exception Objekt behandeln und Zugriff auf die StackTrace oder andere Informationen. Also das allein ist inakzeptabel und muss sich ändern

Die gute Nachricht ist, dass dieses Verfahren virtual ist und überschrieben werden kann. Die schlechte Nachricht ist, dass Sie im obigen Beispiel TDSRESTService mit Ihrer eigenen ProcessRequest Prozedur (einschließlich Ihrer Fehlerbehandler), TDSRESTServer mit eigenen DoDSRESTCommand (in der die TDSRESTService ist in einem monströs großen Verfahren erstellt) und TDSRESTWebDispatcher (je nach Ihrem Verwendung).

Meine persönliche Empfehlung ist, DataSnap nicht zu verwenden.

Hinweis: Zum Zeitpunkt des Schreibens habe ich keinen Aufruf des OnError Ereignisses gefunden.