jsdo AfterSaveChanges errorhandling

Posted by agent_008_nl on 03-Jul-2015 07:30

oe 11.5.1 progress.jsdo.3.1

Trying to handle errors set on the oe backend, f.e.

somebeforebufferhandle:error = true.         

somebeforebufferhandle:error-string = "Orderstatus is verplicht".

In the jsdo aftersavechanges I get the following request.response. Do I have to query prods:errors or is there another way to get the errors? Why is the _errorString for epurchaseOrder (setting error-string on the afterbuffer does not change this) undefined? Am I using the wrong jsdo (I read something about kendo-dialect here https://documentation.progress.com/output/oemobile1151/index.html#page/oemobile/jsdo-dialect-of-the-kendo-ui-datasource.html and I'm not using kendo)?

Regards, Stefan.

 

Posted by egarcia on 08-Jul-2015 05:34

Hello Stefan,

Thank you for your feedback and suggestions.

The behavior that you are seeing is because by default, the JSDO applies changes automatically, i.e., if an update was successful, the changes are accepted, if an update failed, the changes are rejected.

Reference:

documentation.progress.com/.../openedge115

You should be able to query the error string using getErrorString() if  you set autoApplyChanges to false in the JSDO before calling saveChanges().

Example:

jsdo.autoApplyChanges = false;

In this case, you would need to call rejectChanges() or acceptChanges() yourself.

Please check the documentation for autoApplyChanges, acceptChanges(), rejectChanges(), acceptRowChanges(), and rejectRowChanges().

The example from the documentation is trying to address the various types of errors that you could get:

- Errors returned as an HTTP error 500 with the error message as text

- Errors returned from the AppServer as an HTTP error 500 with the error message as an error object

- Errors returned via before-image information in a DataSet (this an HTTP 200 OK but success would be false - I will submit a bug report for this issue in the doc).

For a future release, we are considering adding a getErrors() API that would make the various type of errors available using a single method. The structure returned by this API which will also provide the id (_id).

Please let me know if using autoApplyChanges = false solves the issue.

Thank you and regards.

All Replies

Posted by egarcia on 03-Jul-2015 09:11

Hello Stefan,

You do not need to query "prods:errors".

You can use the getErrorString() method to access the error string on the record (jsrecord.getErrorString()).

(Internally, the code merges the response from the server into the internal memory of the JSDO using prods:id and prods:clientId.)

The jsrecord is passed as a parameter to the AfterCreate, AfterUpdate and AfterDelete events.

For the AfterSaveChanges event you access the jsrecord using the request object to process the records that changed.

Are you using CUD/single-record update (saveChanges()) or Submit/multi-record (saveChanges(true))?

Depending on this you need to use request.batch or request.jsrecords to process the records that changed.

For a future release, we are considering adding a method that returns all the errors.

References:

- documentation.progress.com/.../openedge115

- documentation.progress.com/.../openedge115

- documentation.progress.com/.../openedge115

- documentation.progress.com/.../openedge115

I hope this helps.

Posted by Bill Wood on 03-Jul-2015 09:38

WRT

    >>> Am I using the wrong jsdo (I read something about kendo-dialect here)?

Posted by agent_008_nl on 03-Jul-2015 09:44

Hi Edsel,

I will test it monday, thanks, looks good. I'm using submit (saveChanges(true)).

Good weekend, Stefan.

Posted by egarcia on 03-Jul-2015 09:54

hello Stefan,

You are welcome.

The version that you are using is fine. JSDO 3.1 and greater has the support for Submit and usage of the JSON before-image format.

Could you clarify on what you saw in the documentation update (related to the JSDO dialect) and whether you need feedback on this? (I am guessing it was about the processing of errors.)

Have a good weekend,

Edsel.

Posted by agent_008_nl on 06-Jul-2015 01:39

Hi Edsel,

Last update: debugging this myself, I'll get back when I need help.

I still do not have it working. The generated error  is the same:

somebeforebufferhandle:error = true.        

somebeforebufferhandle:error-string = "Orderstatus is verplicht".

jsrecord.getErrorString() returns null as you can see.

Note an important small change I made in jsdo3.1 to make it work with savechanges(true):

I commented out the following in the jsdo savechanges function

if (!this._hasCUDOperations)
            throw new Error(msg.getMsgText("jsdoMSG026")); 

(see your mail https://community.progress.com/community_groups/mobile/f/17/p/18211/64554.aspx#64554, there is a bugreport)

 I tested with jsdo version 4.0 also, with the same modification, same results. 

The output I get with the function copied below the output:

The function I use:

   function saveChanges(action, dataArrayId) {

       var jsdo = dataModel.jsdo;

       jsdo.subscribe('AfterSaveChanges',

                       function callback(jsdo, success, request) {

                           jsdo.unsubscribe('AfterSaveChanges', callback, jsdo);

                           if (success) {

                               var dataReturned = [];

                               jQuery.each(request.jsrecords, function(i, value ) {

                                   dataReturned.push(value.data);

                                   dataReturnedIdea._idBefore = dataArrayId;

                               });

                               eventManager.fireEvent(action + "-data", function(listener){

                                  listener.listenerFunction(dataReturned); // jsdo.getData()

                               });

                           }

                           else {  console.log(request.response[Object.keys(request.response)[0]]["prods:errors"]);

                             jQuery.each(request.jsrecords, function(i, jsrecord) {

                               console.log(jsrecord);

                               console.log(jsrecord.getErrorString());

                            });

                           }

                       },

                       jsdo);

       try{

           jsdo.saveChanges(true); // true -> use submit

          } catch (e) {

           console.log("Error executing function in dataModel.updateData: saveChanges, exception: " + e.message);

          }

   }

Any idea what goes wrong?

 

Thanks, Stefan.

Posted by agent_008_nl on 06-Jul-2015 01:54

Thanks Edsel, no, I do not need feedback on the dialect, I was just wondering if I needed to query prods:errors.

Posted by egarcia on 06-Jul-2015 06:03

Hello Stefan,

Thank you for your reply.

I will try to reproduce it and let you know.

Regards.

Posted by agent_008_nl on 06-Jul-2015 08:19

Thanks Edsel, but I think the error is caused by an addRecord call, I'll try to debug myself and let you know. No need for you to try at this moment.

Regards, Stefan.

Posted by agent_008_nl on 08-Jul-2015 04:45

Hi Edsel,

 

It is not the addRecord I found. When I have assigned the error:

somebeforebufferhandle:error = true.        

somebeforebufferhandle:error-string = "Orderstatus is verplicht".

In afterSaveChanges parameter succes is false. In the _applyChanges function of the jsdo jsrecord.data._errorString != undefined is true, so _undoUpdate is called. After this call jsrecord.data._errorString is empty again, that is why jsrecord.getErrorString() returns null for succes === false. In dvmad.pdf (the doc for mobile) you can find the, eh, documented way, to get the error in this case.

 

It is not with getErrorString(). You query request.response._errors. But when I copy & paste that code request.response._errors is undefined. _errors is built in the jsdo function _updateLastErrors, but only if it is not a submit (+ some more conditions):

    this._updateLastErrors = function(jsdo, batch, changes) {
        if (batch) {
            if (batch.operations == undefined) return;

Maybe a solution would be to add some handling for batch === null in _updateLastErrors (I did not think this out thoroughly). I would be good to have the _id of the jsrecord in _errors in that case also. Or just leave _errorString filled (don't let the undo empty it / re-assign) and empty them with a special call to the jsdo from within afterSaveChanges?  

Regards, Stefan.

 

Posted by egarcia on 08-Jul-2015 05:34

Hello Stefan,

Thank you for your feedback and suggestions.

The behavior that you are seeing is because by default, the JSDO applies changes automatically, i.e., if an update was successful, the changes are accepted, if an update failed, the changes are rejected.

Reference:

documentation.progress.com/.../openedge115

You should be able to query the error string using getErrorString() if  you set autoApplyChanges to false in the JSDO before calling saveChanges().

Example:

jsdo.autoApplyChanges = false;

In this case, you would need to call rejectChanges() or acceptChanges() yourself.

Please check the documentation for autoApplyChanges, acceptChanges(), rejectChanges(), acceptRowChanges(), and rejectRowChanges().

The example from the documentation is trying to address the various types of errors that you could get:

- Errors returned as an HTTP error 500 with the error message as text

- Errors returned from the AppServer as an HTTP error 500 with the error message as an error object

- Errors returned via before-image information in a DataSet (this an HTTP 200 OK but success would be false - I will submit a bug report for this issue in the doc).

For a future release, we are considering adding a getErrors() API that would make the various type of errors available using a single method. The structure returned by this API which will also provide the id (_id).

Please let me know if using autoApplyChanges = false solves the issue.

Thank you and regards.

Posted by agent_008_nl on 08-Jul-2015 07:10

Great, it works, thanks Edsel!

Posted by bcpreece on 22-Mar-2017 06:58

Hi Edsel

The resolution you describe looks fine for someone doing their own programming at the front end, but it's hard to see how to apply it to the code auto-generated by Telerik Platform Views. So far the best I have been able to do is to wrangle the error out of the responseText property of xhr by clumsy string handling:

           error: function (e) {

               app.mobileApp.pane.loader.hide();

               if (e.xhr) {

                   var errorText = "";

                   try {

                       errorText = JSON.stringify(e.xhr);

                   } catch (jsonErr) {

                       errorText = e.xhr.responseText || e.xhr.statusText || 'An error has occurred!';

                   }

                   var errorIndex = e.xhr.responseText.indexOf('"prods:error"');

                   var errorMessagePlus = e.xhr.responseText.slice(errorIndex + 15);

                   errorIndex = errorMessagePlus.indexOf('"');

                   var errorText = errorMessagePlus.slice(0, errorIndex);

                   alert("Error:" + errorText);

               } else if (e.errorThrown) {

                   alert("Error thrown" + e.errorThrown);

               }

           },

I can also parse the responseText string back into an object and the error message is tantalisingly there, but my javascript knowledge isn't sufficient to extract the error:

prods:errors looks like a sub object of dsSolutionAsset, but I can't seem to extract it

Any suggestions?

Regards

Brian

Posted by egarcia on 22-Mar-2017 08:56

Hello Brian,

This post is from a couple of years ago.

We have since added a getErrors() API to return errors via a single method without requiring you to parse JSON structures. (It returns errors for CRUD operations whether the error is returned via prods:errors, as an error object (JSON), or as text.)

documentation.progress.com/.../index.html

Please give it a try and let me know if you have comments or questions.

Thank you and regards,

Edsel

Posted by bcpreece on 22-Mar-2017 12:42

Thanks, Edsel, that works a treat. How do I clear the error condition before the user presses Save again? At the moment, I get the error message, which is trapped in an error function generated as part of the Telerik Platform auto generated code. The user then corrects the error and clicks Save again, but the same error message comes out. However, the changes are then processed correctly and the view returns to the List page, but does not refresh it.

This thread is closed