1
votes

I have the following code listed below:

oTable = sap.ui.getCore().byId('tableID');
var index = oTable.getSelectedIndex();

if (index > -1) {
    var currentRowContext = oTable.getContextByIndex(index);
    var model = oTable.getModel();
    var name = model.getProperty("NAME", currentRowContext);

    var phase = model.getProperty("PHASE", currentRowContext);
    var originalPhase = Phase;
    var sequence;

    var batchChanges = [];

    jQuery.ajax({
        type: "GET",
        contentType: "application/json",
        url: "http://urlpathforxsodata/customer.xsodata/TOOL/?$filter=NAME eq '" + name + "'",
        dataType: "json",
        async: false,
        success: function(data, textStatus, jqXHR) {

            // After processing while loop, index will be the
            // first non-frozen record
            while (originalPhase == phase) {
                index = index + 1;
                phase = data.d.results[index].PHASE;
            }

            for (var i = 0; i < index; i++) {
                var frozenFlag = data.d.results[i].FROZEN_FLG;
                if (frozenFlag != 1) {
                    sequence = data.d.results[i].SEQUENCE;
                    var entry = {
                        NAME: name,
                        SEQUENCE: sequence,
                        FROZEN_FLG: 1,
                    };

                    batchChanges.push(model.createBatchOperation(
                        "/TOOL(NAME='" + name + "',SEQUENCE=" + sequence + ")",
                        "PUT",
                        entry)
                    );
                }
            }

            model.addBatchChangeOperations(batchChanges);

            // submit changes and refresh the
            // table and display message
            model.submitBatch(function(data) {
                model.refresh();
            });
        }
    });
}

The beginning part of the code is business logic that I've verified to determine which rows I would like to update. I use Ajax to return a data set exactly as what is shown in the table (table cannot be filtered or sorted upon so indices will match). My question is related to the entry and batch calls I am making. It's not working and I'm getting the following order:

POST /FiringOrder.xsodata/TOOL /Services/customer.xsodata/$batch

"2014-11-06 11:26:02 The following problem occurred: HTTP request failed400,Bad Request,{ "error": { "code": "", "message": { "lang": "en-US", "value": "Syntax error in resource path at position 29."}}} - " sap-ui-core.js:80

"2014-11-06 11:26:02 The following problem occurred: HTTP request failed400,Bad Request,{ "error": { "code": "", "message": { "lang": "en-US", "value": "Syntax error in resource path at position 29."}}} - "

Three questions:

  1. Is there a better way to debug http requests errors? (I'm really new to this sorry!)
  2. Am I formatting my batch or entry wrong? I have doubts with the URL path I am passing with the parameters (the name and sequence are both keys to the record) and if I should be using PUT to update. Trying MERGE doesn't do anything besides give me a difference error immediately and the error message is unavailable.
  3. Last but not least, all this logic is in my controller. Is this right or should this type of logic be done on the server?
3

3 Answers

2
votes

first of all, its really hard to read your code :-) check this documentation:
SAPUI5 - Batch Operations - how to do it right?

about 1) what you get as error message is the response from the backend (SAP), its the same as the error you get in transaction /IWFND/ERROR_LOG .. in my opinion this information is enough, BAD REQUEST says your request (POST) is malformed, your logic raises a dump in the backend - for details check the backend. I think your way by logging success/error message from AJAX is the most common for debugging http requests.

about 2) I think yes, first of all it says bad request (check backend for error log). Otherwise did you initialize your model in the controller? Odata POSTing works only on Odata Model, currently you are trying to call it for the table model? I think thats not working, so I would propose keeping the logic till "model.addBatchChangeOperations(batchChanges);" submit and then:

onInit : function() { // in controller
    // register the central service (for create/update/other operations)
    var sServiceUrl = "/sap/opu/odata/sap/YOUR_SRV/";
    var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, true);
    sap.ui.getCore().setModel(oModel);
}

then in view or whereever you submit:

var oModel = sap.ui.getCore().getModel(); // ensure that you did not overwrite your 
                                          // model locally!! with some JSON model for example
oModel.addBatchChangeOperations(batchChanges);
oModel.setUseBatch(true);
oModel.submitBatch();

about 3) If you are working locally (in the frontend) with data which you want to post, I think the controller is fine (imho).

Further Comment: As far as I get it, you want to reload data in a table, I think this could be done easier by posting the data, fetching the result, then rebind the data to the table.

Regards, zY

2
votes

This will be a different beast if your model is an OData V2 Model. If this is the case with your model, your controller's programming flow must:

  1. Make sure that the oModel.setUseBatch parameter is true,
  2. Make a series of requests, for which you assign a GroupID or a ChangeSetID,
  3. Finally submit all of the requests in one $batch request using the oModel.submitChanges() method.

I detail this in my response to the SAP SCN thread. I'll go ahead and paste the code snippet here of a working JS Controller method that is submitting a $batch request of a series of PUT requests to an SAP server.

var _postPaymentClosure = function(itemsTable){  
return function(oEvent){  
    var source = oEvent.getSource();  
    var oModel = source.getModel();  
    oModel.setUseBatch(true); //if this is not already done  
    var scopeKey = paymentScopeRBG.getSelectedIndex();  
    var items = itemsTable.getItems();  
    var changeSetId = "foo";  

    //Prep header-level group/changeset params  
    var mParameters = {  
        "groupId": changeSetId,  
        "changeSetId": changeSetId  
    }; //I'm using both...maybe one isn't needed??  
 //Loop through the items, updating each  
    var row;  
    var itemObject;  
    var context;  
    for(var i = 0; i < items.length; i++){  
        row = items[i];  
        context = row.getBindingContext();  
        itemObject = context.getObject();  

        //Do whatever updates to the JSON you want here....  
        itemObject.PaymentCardID = "bar";  

      //Then execute the v2 model's Update function  
       oModel.update(context.sPath, itemObject, mParameters);  
    }  

//Finally, submit all the batch changes  
    oModel.submitChanges(mParameters);  
    };
};  
0
votes

In my case i needed to add line oModel.setRefreshAfterChange(true); in loop.

var mParameters = {
            groupId :"batchCreate"
         }
for (var i = 0; i < data.length; i++) {
        sEntry.Matnr = data[i].Matnr;
        sEntry.Bbynr = data[i].Bbynr;
        sEntry.Prio = data[i].Prio;

        oModel.update("/Data1Set('"+data[i].Bbynr+"')", sEntry, mParameters);

        oModel.submitChanges(mParameters);
        oModel.setRefreshAfterChange(true);
        }

    },