简体   繁体   English

Delphi Datasnap REST Server中的异常处理

[英]Exception handling in Delphi Datasnap REST Server

I'm struggling with exception handling inside my Datasnap REST Service (Delphi XE3 but also tried with Delphi 10 Seattle). 我正在努力处理我的Datasnap REST服务中的异常处理(Delphi XE3,但也尝试使用Delphi 10 Seattle)。 I have written half a dozen Windows Service over the years and I always include a TApplicationEvents component so that I can log any Application Exceptions to the Windows Event Log. 多年来我写了六个Windows服务,我总是包含一个TApplicationEvents组件,以便我可以将任何应用程序异常记录到Windows事件日志中。

However, this behaviour is not happening with a Datasnap Service. 但是,Datasnap服务不会发生此行为。 The TApplicationEvents.OnException event never gets fired, so I assume something else is eating the exception and handling it before it gets here. TApplicationEvents.OnException事件永远不会被触发,所以我假设其他东西正在吃异常并在它到达之前处理它。

The exception is displayed in the web service method's result, which is fine because it means I can at least display something on the client side, but I'd also like to catch it before then so that I might be able to handle different exceptions server-side. Web服务方法的结果中显示异常,这很好,因为这意味着我至少可以在客户端显示某些内容,但我还想在此之前捕获它,以便我可以处理不同的异常服务器-侧。

The only consistent way I have managed so far is to wrap each individual method in a try..except block, and handle the exception in each method, before re-raising the exception. 到目前为止我唯一一致的方法是将每个单独的方法包装在try..except块中,并在重新引发异常之前处理每个方法中的异常。 However, with a Web Service of 20 methods and growing, this isn't really going to scale up. 但是,随着20种方法的Web服务不断增长,这种情况并没有真正扩大。

I have also tried implementing the OnError, OnTrace and other events of the some of the Datasnap components (TDSServer, TDSHTTPService, TDSTCPServerTransport, etc.) but these never seem to get fired either. 我也尝试过实现一些Datasnap组件的OnError,OnTrace和其他事件(TDSServer,TDSHTTPService,TDSTCPServerTransport等),但这些事件似乎也从未被解雇过。

Has anyone come across anything like this, please? 有没有人遇到这样的事,拜托?

Tl;Dr: it's not implemented in a usable fashion (in 10.1 Berlin). Tl; Dr:它没有以可用的方式实现(在柏林10.1)。

I came across the same problem and after reading through a lot of source, I found no practical solution. 我遇到了同样的问题,在阅读了大量资料后,我发现没有实际的解决方案。

So an exemplary (my) StackTrace would look like this: 所以示例(我的)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)

Note: This depends entirely on your usage of DataSnap. 注意:这完全取决于您对DataSnap的使用。 In the above case requests are passed into the DataSnap API through TDSRESTWebDispatcher (comming from TIdCustomHTTPServer ). 在上述情况下,请求通过TDSRESTWebDispatcher (来自TIdCustomHTTPServer )传递到DataSnap API。

  • Every Exception raised in a ServerMethod will end up in TDSService::ProcessRequest . ServerMethod引发的每个Exception ServerMethod将以TDSService::ProcessRequest结束。
  • In this procedure every Exception is caught and ONLY its Message is added to a TRequestCommandHandler->CommandList . 在此过程中,将捕获每个Exception ,并且只将其Message添加到TRequestCommandHandler->CommandList
  • Further down the Message is written as JSON/DBX command to the output. 接下来, Message被写为输出的JSON / DBX命令。

So we can never handle the Exception Object and access the StackTrace or other information. 因此,我们永远不能处理Exception对象并访问StackTrace或其他信息。 So this alone is unacceptable and has to change 所以这一点是不可接受的,必须改变

The good news is, that this procedure is virtual and can be overwritten. 好消息是,这个程序是virtual ,可以被覆盖。 The bad news is, that in the example above you would have to extend TDSRESTService with your own ProcessRequest procedure (including your errorhandler), TDSRESTServer with own DoDSRESTCommand (in there the TDSRESTService is created in a monstrously large procedure) and TDSRESTWebDispatcher (depending on your usage). 坏消息是,在你上面的例子将不得不延长TDSRESTService用自己ProcessRequest程序(包括您的ErrorHandler), TDSRESTServer用自己的DoDSRESTCommand (在那里TDSRESTService是一个无情无义大的过程中创建)和TDSRESTWebDispatcher (取决于您的用法)。

My personal recommendation is to don't use DataSnap. 我个人的建议是不要使用DataSnap。

Note: At the point of writing this, I haven't found any invoke of the OnError event. 注意:在编写本文时,我没有找到任何OnError事件的调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM