Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone sync error even after response code 200

Hello Backbone ninjas,

This is my first time using Backbone - so please excuse my "noob"ness. In my functionality (part of a larger app),I have a Backbone View vA, backed by a model mA (as it should be ) and the server side is in Spring MVC having annotated Spring controller methods with @RequestBody and @ResponseBody. I've got Jackson working fine with Spring.

Now, in the app,

Backbone.Model
 |_ BaseModel (custom base model for our app)
   |_ mA (my model)

mA has its own endpoint and it Backbone sucessfully calls that when making a PUT request i.e., when I call save() from a submit button event handler from View vA like so:

this.model.save({

            success : function(){

                    alert('Request submitted successfully');


            },

            error : function(){
                alert('Something awful happened.');
            }

});

Our BaseModel has the following:

define([], function() {



window.BaseModel = Backbone.Model.extend({
 ......


});

onSyncError : function(model, response) {
        switch (response.status) {
        case 403:
        [...//some more code ]
        default:
            alert(bundle.getDefault('HTTP_RESP_OTH') + response.status);
        }
    },

    onSyncSuccess : function(model, response) {
        alert('Sync done! ');
    },

    sync : function(method, model, options) {
        options.error = this.onSyncError;
        Backbone.sync.call(this, method, model, options);
        ....//some more stuff.      
    },

}

Spring controller method:

@RequestMapping(value="/resource/xyz/{id}.json", method = RequestMethod.PUT, consumes     = {"application/json"}
, produces = {"application/json"})
@ResponseBody
public Map<String,String> methodX(@RequestBody XyzDTO  xyzDTO){
....
map.put("msg", "success");

return map;
}

Also, right before I make the save call, I modify a few Model attributes, since the server side DTO has a different structure like so:

this.model.unset("abc",{ silent: true });
this.model.set( { abc: {id : "2",xyz:{ ... //more code } ); 

The issue is, calling save() generates a PUT request and successfully calls the Spring endpoint handler, but I get a response code 200 (which is what I expect), but when I trace the call with Firebug, it goes into the onSyncError method and gives me an error message (because of the "default" case in it).

The Backbone doc says : "When returning a JSON response, send down the attributes of the model that have been changed by the server, and need to be updated on the client". Well, I don't need to update the model on the client side, its one of the last screens and I just need to tell the user of a success / error and redirect him to a main page/dashboard.

I read up some more, and it seems code 200 as response is not sufficient - there might be JSON parsing errors causing the sync to fail.

I checked the response in Firebug, and the response JSON looks like {"msg":"Success"}.

So, what could be going wrong?

like image 993
trishulpani Avatar asked Jun 06 '13 14:06

trishulpani


1 Answers

Backbone.Model.save() expects the response from the server to be an updated hash of the model's values. If your response is of the kind {"msg":"Success"}, Backbone may fail to sync with your model. Basically, it interprets your HTTP 200 JSON response as the model's attributes and tries to sync the model accordingly.

You might try either 1) Making your Spring controller path return a JSON-ified model response, 2) Return a plain 200 with an empty response body or 3) write a custom parse method which looks for responses with the {"msg":"Success"} format and responds differently.

like image 97
brettjonesdev Avatar answered Oct 25 '22 08:10

brettjonesdev