Delphi Datasnap REST服务器中的异常处理

5
我正在处理我的Datasnap REST服务(Delphi XE3,但也尝试了Delphi 10 Seattle)中的异常处理问题。我在过去写过半打Windows服务,并且始终包括TApplicationEvents组件,以便我可以将任何应用程序异常记录到Windows事件日志中。
然而,这种行为在Datasnap服务中并不发生。 TApplicationEvents.OnException事件从未被触发,因此我认为有其他东西会吃掉这个异常并在它到达之前处理它。
异常显示在Web服务方法的结果中,这很好,因为这意味着我至少可以在客户端上显示一些东西,但我还想在那之前捕获它,以便我能够在服务器端处理不同的异常。
迄今为止我唯一一致的方法是在每个单独的方法中包装一个try..except块,并在每个方法中处理异常,然后重新引发异常。 但是,随着一个具有20个及以上方法的Web服务的增长,这种方式不会真正扩展。
我还尝试实现一些Datasnap组件(TDSServer,TDSHTTPService,TDSTCPServerTransport等)的OnError,OnTrace和其他事件,但这些似乎也从未被触发过。
请问是否有人遇到过类似的情况?

相关(针对Java):如何在Java Servlet Web应用程序中捕获未捕获的异常。如果在Datasnap中存在全局请求过滤器机制,则可能有类似的解决方案。 - mjn
正如您所指出的,异常被DataSnap事件处理程序代码捕获。很容易创建一个模板异常处理程序,在编写其余代码之前将其放置在每个新事件处理程序中。根据您正在进行的操作,您可能希望对不同的资源请求做出不同的响应。当然,您已经知道这一点。作为替代方案,您可以使用默认处理程序并自己解析pathinfo,只需使用具有异常处理程序的单个事件处理程序即可,而不是创建不同的操作和事件处理程序。 - Toby
1个回答

0

简而言之:(在10.1 Berlin中)它没有以可用的方式实现。

我遇到了同样的问题,在阅读了大量源代码后,我没有找到实际的解决方案。

因此,一个典型的(我的)堆栈跟踪看起来像这样:

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)

注意:这完全取决于您使用DataSnap的方式。 在上面的情况下,请求通过TDSRESTWebDispatcher(来自TIdCustomHTTPServer)传递到DataSnap API。

  • ServerMethod中引发的每个Exception最终都会出现在TDSService :: ProcessRequest中。
  • 在此过程中,捕获每个Exception,并仅将其Message添加到TRequestCommandHandler->CommandList中。
  • 在稍后,Message被写入输出作为JSON / DBX命令。

因此,我们永远无法处理Exception对象并访问StackTrace或其他信息。 因此,这本身就是不可接受的,并且必须更改。

好消息是,这个过程是虚拟的,可以被覆盖。坏消息是,在上面的例子中,您将不得不使用自己的ProcessRequest过程(包括您的错误处理程序)扩展TDSRESTService,使用自己的DoDSRESTCommand扩展TDSRESTServer(在其中创建了一个庞大的过程TDSRESTService),以及TDSRESTWebDispatcher(根据您的使用情况)。

我个人的建议是不要使用DataSnap。

注意:在撰写本文时,我还没有找到任何调用OnError事件的地方。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接