【问题标题】:Exception handling in Delphi Datasnap REST ServerDelphi Datasnap REST Server 中的异常处理
【发布时间】:2015-12-01 10:31:56
【问题描述】:

我在我的 Datasnap REST 服务(Delphi XE3 但也尝试使用 Delphi 10 Seattle)中的异常处理方面苦苦挣扎。这些年来,我编写了六个 Windows 服务,并且总是包含一个 TApplicationEvents 组件,以便我可以将任何应用程序异常记录到 Windows 事件日志中。

但是,Datasnap 服务不会发生这种行为。 TApplicationEvents.OnException 事件永远不会被触发,所以我假设其他东西正在吃掉异常并在它到达之前处理它。

异常显示在 Web 服务方法的结果中,这很好,因为这意味着我至少可以在客户端显示一些东西,但我也想在那之前捕获它,以便我能够处理服务器端的不同异常。

到目前为止,我管理的唯一一致方法是将每个单独的方法包装在 try..except 块中,并在重新引发异常之前处理每个方法中的异常。然而,随着 20 种方法的 Web 服务不断增长,这并不会真正扩大规模。

我也尝试过实现一些 Datasnap 组件(TDSServer、TDSHTTPService、TDSTCPServerTransport 等)的 OnError、OnTrace 和其他事件,但这些似乎也从未被触发。

请问有人遇到过这种情况吗?

【问题讨论】:

  • Related (for Java): How to grab uncaught exceptions in a Java servlet web application 也许类似的解决方案是可能的。 (如果Datasnap中有全局请求过滤机制)
  • 如您所述,DataSnap 事件处理程序代码正在捕获异常。在编写其余代码之前,创建一个模板异常处理程序以放入每个新的事件处理程序很容易。根据您正在做什么,您可能希望在不同的资源请求中做出不同的响应。你当然知道这一切。作为替代方案,您可以只使用默认处理程序并自己解析路径信息,而不是创建不同的操作和事件处理程序,并且在该事件中只使用一个带有异常处理程序的事件处理程序。

标签: delphi delphi-xe3 datasnap


【解决方案1】:

Tl;Dr:它没有以可用的方式实现(在柏林 10.1 中)。

我遇到了同样的问题,在阅读了很多资料后,我没有找到切实可行的解决方案。

所以一个示例性的(我的)StackTrace 看起来像这样:

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-&gt;CommandList
  • 再往下,Message 将作为 JSON/DBX 命令写入输出。

因此我们永远无法处理Exception 对象并访问StackTrace 或其他信息。因此,仅此一项是不可接受的,必须改变

好消息是,这个过程是virtual 并且可以被覆盖。坏消息是,在上面的示例中,您必须使用自己的 ProcessRequest 过程(包括您的错误处理程序)扩展 TDSRESTService,使用自己的 DoDSRESTCommand 扩展 TDSRESTServer(其中 TDSRESTService 是在非常大的程序)和TDSRESTWebDispatcher(取决于您的使用情况)。

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

注意:在撰写本文时,我还没有发现任何对 OnError 事件的调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多