#1 2017-10-24 10:48:04

tomek
Member
Registered: 2017-10-24
Posts: 46

cross platfrom client - exceptions handling

Hi
I'm using interface based services + cross platfrom client.
I've problem with exceptions handling in client app. If service fails I get only "Error calling ServiceClassName.SomeService - returned status 500".
Is it possbile to get any additional info from cross platform client TSQLRestClientHTTP the way TSQLHttpClient does (LastErrorMessage)?

Regards, Tomek

Offline

#2 2017-10-24 11:58:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: cross platfrom client - exceptions handling

In fact, the pattern on server side is that exceptions should be exceptional (dead database, etc...).
Your server code should catch exceptions and convert it into high-level errors, most likely enumerations (with optional text message for the details).

See http://blog.synopse.info/post/2015/04/1 … -good-idea
and https://synopse.info/files/html/Synopse … l#TITL_165

Offline

#3 2017-10-24 13:07:12

tomek
Member
Registered: 2017-10-24
Posts: 46

Re: cross platfrom client - exceptions handling

Hi
Thx for your answer.
Actually I've already read those docs, but I'm not sure if I understand it correctly. It says:

By default, any Exception raised on the server side, within an interface-based service method, will be intercepted, and transmitted as an error to the client side, then a safe but somewhat obfuscated EInterfaceFactoryException will be raised on the client side, containing additional information serialized as JSON."

I'm looking only for this "additional information", I don't need full Exception object.
Standard TSQLHttpClient does have LastErrorMessage method to get it, cross platform TSQLRestClientHTTP does not.

Regards, Tomek

Offline

#4 2017-10-26 17:06:22

tomek
Member
Registered: 2017-10-24
Posts: 46

Re: cross platfrom client - exceptions handling

I did some research, and found this "additional info" in client response in Call.OutBody just before EServiceException is raised. It contains exactly root exception message from server.
I did temporary fix for myself in SynCrossPlatformREST.pas, TSQLRestClientURI.CallRemoteService (line 3061):

var sOutBody: UTF8String;
  if Call.OutStatus<>HTTP_SUCCESS then begin
    SetString(sOutBody, PUTF8Char(@Call.OutBody[0]), Length(Call.OutBody));
    raise EServiceException.CreateFmt('Error calling %s.%s - returned status %d'
                                      + #13#10 + sOutBody,
      [aCaller.fServiceName,aMethodName,Call.OutStatus]);
  end;

I'm not sure if it won't break anything and I hope for more complex and decent solution smile

Regards, Tomek

Offline

#5 2017-10-26 17:48:41

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,659
Website

Re: cross platfrom client - exceptions handling

I guess https://synopse.info/fossil/info/3aaaade511 is the correct way of implementing it.

Offline

#6 2017-10-27 07:07:27

tomek
Member
Registered: 2017-10-24
Posts: 46

Re: cross platfrom client - exceptions handling

Ok, thx for your interest.

Regards, Tomek

Offline

#7 2017-10-27 16:39:07

tomek
Member
Registered: 2017-10-24
Posts: 46

Re: cross platfrom client - exceptions handling

I've another issue with exception handling, this time with client side exceptions.
When connection is broken for some reason I get "Error calling ServiceClassName.SomeService - returned status 501".
Root exception after unsuccessful request is: EWinHTTP: 'winhttp.dll error 12029 (cannot connect)' which is quite meaningful. But exception then is catched in try except block at
TSQLRestClientHTTP.InternalURI (SynCrossPlatfromREST.pas line 3304)
and reraised later with mentioned status 501.
I've tried to populate Call.OutBody with E.message at this point but with no success. I guess this is because of corrupted content of E.message: '(Ú蝰ӕ慌ՙ'#0#0'끸....'

    try
      fConnection.URI(Call,inType,fKeepAlive);
      break; // do not retry on transmission success, or asynchronous request
    except
      on E: Exception do begin
        Log(E);
        fConnection.Free;
        fConnection := nil;
        SetLength(Call.OutBody, Length(E.message));
        Move(pointer(E.message)^,pointer(Call.OutBody)^, Length(E.message));
        Call.OutStatus := HTTP_NOTIMPLEMENTED;
        if fForceTerminate then
          break;
      end; // will retry once (e.g. if connection broken)
    end;

Regards, Tomek

Offline

#8 2017-10-30 13:22:09

tomek
Member
Registered: 2017-10-24
Posts: 46

Re: cross platfrom client - exceptions handling

I've found correct way to populate Call.OutBody without encoding issues.
I still need confirmation if it's right approach, and I don't understand why actually Call.OutStatus is hardcoded to HTTP_NOTIMPLEMENTED a this point.
(SynCrossPlatfromREST.pas line 3300)

    try
      fConnection.URI(Call,inType,fKeepAlive);
      break; // do not retry on transmission success, or asynchronous request
    except
      on E: Exception do begin
        Log(E);
        fConnection.Free;
        fConnection := nil;
        if Length(Call.OutBody) = 0 then                       // added
          Call.OutBody := TextToHttpBody(E.message);
        Call.OutStatus := HTTP_NOTIMPLEMENTED;                 //?
        if fForceTerminate then
          break;
      end; // will retry once (e.g. if connection broken)
    end;

Regards, Tomek

Last edited by tomek (2017-10-30 13:24:33)

Offline

#9 2017-11-03 17:14:30

marcinb
Member
Registered: 2014-04-08
Posts: 11

Re: cross platfrom client - exceptions handling

Hi AB

Can you comment Tomek's suggestion?
Is it worth something? If so can you add to the 'official' sources?

Thanks,
Marcin

Offline

Board footer

Powered by FluxBB