2015-12-01 15 views
5

Tôi đang đấu tranh với xử lý ngoại lệ bên trong Dịch vụ REST Datasnap REST của tôi (Delphi XE3 nhưng cũng đã thử với Delphi 10 Seattle). Tôi đã viết một nửa tá Dịch vụ Windows trong nhiều năm và tôi luôn bao gồm một thành phần TApplicationEvents để tôi có thể ghi lại bất kỳ Ngoại lệ Ứng dụng nào vào Nhật ký sự kiện Windows.Xử lý ngoại lệ trong Delphi Datasnap REST Server

Tuy nhiên, hành vi này không xảy ra với Dịch vụ dữ liệu. Các sự kiện TApplicationEvents.OnException không bao giờ bị sa thải, vì vậy tôi giả định một cái gì đó khác là ăn ngoại lệ và xử lý nó trước khi nó được ở đây.

Ngoại lệ được hiển thị trong kết quả của phương thức dịch vụ web, điều này có nghĩa là tôi ít nhất có thể hiển thị nội dung nào đó ở phía khách hàng, nhưng tôi cũng muốn bắt nó trước đó để tôi có thể xử lý các ngoại lệ khác nhau phía máy chủ.

Cách duy nhất phù hợp mà tôi đã quản lý cho đến nay là bọc từng phương thức riêng lẻ trong khối try..except và xử lý ngoại lệ trong mỗi phương pháp, trước khi tăng lại ngoại lệ. Tuy nhiên, với một dịch vụ Web gồm 20 phương pháp và đang phát triển, điều này không thực sự mở rộng.

Tôi cũng đã thử triển khai OnError, OnTrace và các sự kiện khác của một số thành phần Datasnap (TDSServer, TDSHTTPService, TDSTCPServerTransport, v.v.) nhưng chúng chưa bao giờ bị sa thải.

Có ai đi qua bất cứ điều gì như thế này không?

+0

Có liên quan (đối với Java): [Cách lấy các ngoại lệ chưa nắm bắt trong ứng dụng web Java servlet] (http://stackoverflow.com/questions/7410414/how-to-grab-uncaught-exceptions-in-a-java -servlet-web-application) Có thể một giải pháp tương tự là có thể. (nếu có cơ chế lọc yêu cầu chung trong Datasnap) – mjn

Trả lời

0

Tl; Tiến sĩ: nó không được triển khai theo cách có thể sử dụng (ở 10.1 Berlin).

Tôi đã gặp vấn đề tương tự và sau khi đọc qua rất nhiều nguồn, tôi không tìm thấy giải pháp thực tế nào.

Vì vậy, một gương mẫu StackTrace (tôi) sẽ trông như thế này:

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) 

Lưu ý: Điều này phụ thuộc hoàn toàn vào việc bạn sử dụng DataSnap. Trong các yêu cầu trường hợp trên được chuyển vào API DataSnap thông qua TDSRESTWebDispatcher (bắt đầu từ TIdCustomHTTPServer).

  • Mỗi Exception được nêu trong ServerMethod sẽ kết thúc bằng TDSService::ProcessRequest.
  • Trong thủ tục này, mỗi Exception bị bắt và CHỈ Message của nó được thêm vào TRequestCommandHandler->CommandList.
  • Tiếp tục xuống dưới Message được viết dưới dạng lệnh JSON/DBX cho đầu ra.

Vì vậy, chúng tôi không bao giờ có thể xử lý đối tượng Exception và truy cập StackTrace hoặc thông tin khác. Vì vậy, điều này một mình là không thể chấp nhận và phải thay đổi

Tin tốt là thủ tục này là virtual và có thể bị ghi đè. Tin xấu là, trong ví dụ trên bạn sẽ phải mở rộng TDSRESTService với thủ tục ProcessRequest của riêng bạn (bao gồm cả trình xử lý lỗi), TDSRESTServer với riêng DoDSRESTCommand (trong đó TDSRESTService được tạo theo quy trình lớn) và TDSRESTWebDispatcher (tùy thuộc vào sử dụng).

Đề xuất cá nhân của tôi là không sử dụng DataSnap.

Lưu ý: Tại thời điểm viết bài này, tôi chưa tìm thấy bất kỳ lời gọi nào về sự kiện OnError.