Raising a custom Exception within TDABusinessProcessor.OnAfterProcessChange ends up with EDAApplyUpdateFailed with no inner exception on the client

Hi everyone
I think the title already nails the problem pretty accurately!

I have got the following code within the OnAfterProcessChange event handler of a TDABusinessProcessor:

// check whether the stored procedure returns a json structure containing all ambiguous accounting fields
  // if so, this means that the user has to specifiy which ones shall be applied
  if ParamByName(par_AmbiguousAccountingFields).AsString <> '' then
  begin
    try
      // convert the json array into a delphi structure
      AmbiguousAccountingFields := TAmbiguousAccountingFields.Create;
      JSonValue := TJSonObject.ParseJSONValue(ParamByName(par_AmbiguousAccountingFields).AsString);

      for Item in JSonValue as TJSONArray do
      begin
        with AmbiguousAccountingFields.Add do
        begin
          ItemTypeCode                       := Item.GetValue<string>('ItemTypeCode');
          ItemTypeName                       := Item.GetValue<string>('ItemTypeName');
          ValueOnCurrentSemester             := Item.GetValue<Currency>('ValueOnCurrentSemester');
          ValueOnPreviousSemesterParticipant := Item.GetValue<Currency>('ValueOnPreviousSemesterParticipant');
        end;
      end;

      // finally raise an exception containing all ambiguous accounting fields
      raise EAmbiguousAccountingFields.Create('', AmbiguousAccountingFields);
    finally
      JSonValue.Free;
    end;
  end;

The problem is that on the client I only ever receive a EDAApplyUpdateFailed having no inner exception whatsoever!
Can you help me raising an exception on the client actually containing the necessary payload?`

Kind regards
Francois

Hi,
looks like you have set BP.RaiseExceptionAtError to true (for personal BP) or DataService.ReturnUpdateFailureDelta to false (for autogenerated BP)
so EDAApplyUpdateFailed exception is raised.

by other hand, you can try get your original error message from the EDAApplyUpdateFailed.Message property:

constructor EDAApplyUpdateFailed.Create(aChange: TDADeltaChange; anOriginalException: Exception);
begin
  if (anOriginalException<>NIL) then begin
    inherited Create(anOriginalException.Message); //<<<<
  end
  else inherited Create('');

Hi EvgenyK
Many thanks for your response.

  1. Unfortunately the RaiseExceptionAtError Flag on the personal BP ist already set to false and yet, an EDAApplyUpdateFailed Exception is all I get on the client :-/

  2. I am afraid you didn’t understand the problem I am facing. I do NOT want to provide the client with a simple message but with a RemObjects Datastructure which the client can then further process. When you take a closer look at the code snippet within my initial post, you will realize that the EAmbiguousAccountingFields Exception takes an object of type TAmbiguousAccountingFields, which is itself a list of TAmbiguousAccountingField objects. I need this structure on the client and not a simple message. I am posting the client side code snippet as well in order to illustrate the basic idea:

    try
      // store this course participant
      DataSet.ApplyAndUpdate(False);
    except
     // THIS IS ALWAYS AN EDAApplayUpdateFailed
     on Exp: Exception do
     begin
       // THIS IS ALWAYS NIL (WHERE IS MY EXCEPTION????)
       if Exp.InnerException is EAmbiguousAccountingFields then
       begin
         FormAccountingSelector                           := TFormAccountingSelector.Create(Self);
         FormAccountingSelector.AmbiguousAccountingFields := (Exp.InnerException as EAmbiguousAccountingFields).AmbiguousAccountingFields;
    
         try
           if FormAccountingSelector.ShowModal = mrOk then
           begin
             FDMDisposal.tbl_CourseParticipantDetail.FieldByName('AccountingSource').AsString := FormAccountingSelector.SelectedAccountingSource;
             DataSet.ApplyAndUpdate(False);
           end;
         finally
           FormAccountingSelector.Free;
         end;
       end;
     end;
     else
       raise;
    end;
    

Kind regards
Francois

We don’t use/support InnerException.
Try to find your exception’s message in EDAApplayUpdateFailed.Message property

I don’t want to be rude or anything but did you actually read my message?

EDAApplyUpdateFailed.Message is of type string and I spent a considerable amount of time stating excplicitly that simply returning a string is useless as the payload of this exception is not ment for the end customer to read but rather for the client to interpret and take actions based on the information provided by that very payload! The payload of the exception I am raising on the server is a TAmbiguousAccountingFields object and not a &%*ç string!

As I already said, RemObjects/Data Abstract don’t use/support InnerException property.

this means that Exp.InnerException will be always nil.

at this moment, you can only get OriginalException.Message value in EDAApplyUpdateFailed.Message because only this value is passed from server inside EDAApplyUpdateFailed.

if you declare your exception (i.e. EAmbiguousAccountingFields ) in RODL (I suppose you are using RODL-based server), you can pass it from server-side to client-side.

So what you’re basically saying is that when using dataabstract its not possible to provide the requesting client with anything different than a simple string as means of a feedback to a failed client request?

by default - DA passes only original message inside EDAApplyUpdateFailed.Message.

if you declare new exception in RODL, you can pass almost everything - arrays, complex types (aka structs), streams, simple types inside your exception.

Well, this is exactly what I am doing. I did define a new custom exception type in the RODL named EAmbiguousAccountingFields and I am raising that very exception in the… …you know… …please read my initial question… …or the title of this thread which states that I am exactly doing what you are supposing - it just doesnt work! :wink:

If you send simple testcase to support@ now, I can review it and say what is wrong