-
26 Jan 2012 7:50 AM #1
Possible bug ? Proxy reader success property is not firing the exception event
Possible bug ? Proxy reader success property is not firing the exception event
Hello there,
I have a store whose proxy is configured as follows:
Code:proxy:{ type:'jsonAjax', api:{ read:'Acl/Details' }, reader:{ type:'json', root:'data.AccessControls' }, actionMethods:{ read:'POST' }, listeners:{ exception:function (proxy, response, operation, options) { if (response.status != -1) { MyApp.generic.Messaging.processProxyRequestEx(response); } } } },
The problem is that my exception handler does not run if the response's success property is false. When I have a response such as this:
Code:{ data: null, message: 'The Acl details could not be retrieved due to an unexpected error on the server', success: false}
When I get a response like the above, I get an error 'obj.data is null' on the readRecords method of Ext.data.reader.Reader.
This method is called when processing the response from the server. Trying to investigate a bit further I looked into the processResponse method on the Ext.data.proxy.Server object and noticed that the Ext platform code is actually trying to read the response object structure BEFORE checking for the success property value. Check below:
Code:// Should this be documented as protected method? processResponse: function(success, operation, request, response, callback, scope){ var me = this, reader, result; if (success === true) { reader = me.getReader(); // JMAIA: HERE DATA IS EXTRACTED result = reader.read(me.extractResponseData(response)); // JMAIA: HERE sucess IS CHECKED. IF DATA = NULL AND SUCCESS = FALSE THIS CODE IS NOT REACHED DUE TO AN ERROR AND THE EXCEPTION EVENT IS NOT FIRED if (result.success !== false) { //see comment in buildRequest for why we include the response object here Ext.apply(operation, { response: response, resultSet: result }); operation.commitRecords(result.records); operation.setCompleted(); operation.setSuccessful(); } else { operation.setException(result.message); me.fireEvent('exception', this, response, operation); } } else { me.setException(operation, response); me.fireEvent('exception', this, response, operation); } //this callback is the one that was passed to the 'read' or 'write' function above if (typeof callback == 'function') { callback.call(scope || me, operation); } me.afterRequest(request, success); },
What happens is that if the server responds with an error (something other than HTTP status 200) the exception event is fired, but if the server responds with 200, but with a success property of false and no data, it yields an error before getting to the bit of code where it is actually checking for the success property in order to fire the event.
Please let me know if there is any workaround for this, as all the code on my application depends on this to inform the user if anything went wrong on the server or not.
Regards,
Joao Maia
-
26 Jan 2012 1:01 PM #2
Do you use some proxy extension? I haven't seen proxy type 'jsonAjax' before.
Jozef Sakalos, aka Saki
A lot of valuable info at:
Saki's Extensions and Plugins
Saki's Extensions and Plugins Docs
Saki's Examples, Latest: Grid in Card Layout
Saki's Blog, Featured: Writing a Big Application in Ext, Latest: Grid MultiSearch Plugin Video
-
27 Jan 2012 2:27 AM #3
Yep, sorry for that.
jsonAjax is a proxy extension I created that I use throughout my application. Basically it's an extension to Ext.data.proxy.Ajax that overrides the buildRequest and doRequest methods in order to do two simple things:
- Send all form data JSON encoded (my back-end server expects everything in JSON format)
- Add a lastRequest property so that the request can be cancelled at any time
Code follows below. I don't think the problem is due to the extension because there is hardly any changes to the original methods.
Code:/** * An ajax proxy that posts the data encoded in json and sends it on the body of the request */ Ext.define('MyApp.ux.json.JSONAjaxProxy', { extend: 'Ext.data.proxy.Ajax', alias: 'proxy.jsonAjax', /** * Overriden destroy method. Empty on purpose to avoid the posting of a request when destroying the object */ destroy: function() { }, /** * Overriden buildRequest method that encodes the parameter in json format when building the request */ buildRequest: function(operation) { var params = Ext.applyIf(operation.params || {}, this.extraParams || {}), request; //copy any sorters, filters etc into the params so they can be sent over the wire params = Ext.applyIf(params, this.getParams(operation)); if (operation.id && !params.id) { params.id = operation.id; } // decode sort parameter if present if (params && params.sort) { params.sort = Ext.JSON.decode(params.sort); } // decode filter parameter if present if (params && params.filter) { params.filter = Ext.JSON.decode(params.filter); } request = Ext.create('Ext.data.Request', { // explicitly JSON-encode POSTed parameters params : (Ext.JSON.encode(params)), action : operation.action, records : operation.records, operation: operation, url : operation.url }); request.url = this.buildUrl(request); // Save the request on the Operation. Operations don't usually care about Request and Response data, but in the // ServerProxy and any of its subclasses we add both request and response as they may be useful for further processing operation.request = request; return request; }, doRequest: function(operation, callback, scope) { var writer = this.getWriter(), request = this.buildRequest(operation, callback, scope); if (operation.allowWrite()) { request = writer.write(request); } Ext.apply(request, { headers : this.headers, timeout : this.timeout, scope : this, callback : this.createRequestCallback(request, operation, callback, scope), method : this.getMethod(request), disableCaching: false // explicitly set it to false, ServerProxy handles caching }); this.lastRequest = Ext.Ajax.request(request); return request; } });
Regards,
Joao Maia
-
28 Jan 2012 1:32 AM #4
OK, then I'd try to use the standard Ext proxy to see if the problem lies in the extension or not.
Jozef Sakalos, aka Saki
A lot of valuable info at:
Saki's Extensions and Plugins
Saki's Extensions and Plugins Docs
Saki's Examples, Latest: Grid in Card Layout
Saki's Blog, Featured: Writing a Big Application in Ext, Latest: Grid MultiSearch Plugin Video
-
30 Jan 2012 2:58 AM #5
Hi Saki,
I tried the using proxy type: 'ajax' (Ext.data.proxy.Ajax) and got the exact same problem.
I was already expecting that because the overrides I did on jsonAjax have almost the same code as the Ext platform ajax proxy. I only changed two lines of code and none of these was related to processing the response from the server, but to the sending of the request.
So I guess there is some problem with the Ext 'ajax' proxy on the circumstances that I described.
Regards,
Joao Maia
-
30 Jan 2012 3:33 AM #6
Well, the logic of firing exception event is quite straightforward - response must contain success:false:
PHP Code:processResponse: function(success, operation, request, response, callback, scope){
var me = this,
reader,
result;
if (success === true) {
reader = me.getReader();
result = reader.read(me.extractResponseData(response));
if (result.success !== false) {
//see comment in buildRequest for why we include the response object here
Ext.apply(operation, {
response: response,
resultSet: result
});
operation.commitRecords(result.records);
operation.setCompleted();
operation.setSuccessful();
} else {
operation.setException(result.message);
me.fireEvent('exception', this, response, operation);
}
} else {
me.setException(operation, response);
me.fireEvent('exception', this, response, operation);
}
//this callback is the one that was passed to the 'read' or 'write' function above
if (typeof callback == 'function') {
callback.call(scope || me, operation);
}
me.afterRequest(request, success);
},
Jozef Sakalos, aka Saki
A lot of valuable info at:
Saki's Extensions and Plugins
Saki's Extensions and Plugins Docs
Saki's Examples, Latest: Grid in Card Layout
Saki's Blog, Featured: Writing a Big Application in Ext, Latest: Grid MultiSearch Plugin Video
-
30 Jan 2012 4:13 AM #7
Saki,
Please check my first post on this thread.
My response does contain success: false. It also contains data: null, which is why I am getting the error.
I followed the processResponse function step-by-step using firebug and what I noticed was that the error occurs on the following two lines, that run BEFORE the check for the success property on the response:
Code:reader = me.getReader(); result = reader.read(me.extractResponseData(response));
Probably it happens because my 'root' is set to the property 'data.AccessControls' of the response, and since the data on the response is null, ExtJS is returning an error on reader.read.
But my question is shouldn't the success property be queried before actually trying to read the full response data ? If the success property is false, as it is in this case, what sense does it make to go look for data on the root of the response ? It may or may not be there, depending on what happened on the server...
Furthermore, I may not have enough control on the server side to decide what to put on the response, in the root property, if the request fails. Therefore, I don't think the Ext platform should not throw any exceptions because of this.
Regards,
Joao Maia
-
31 Jan 2012 1:50 AM #8
Well, I personally cannot say if this is an on-purpose design decision or a bug - only developers can. If you want I'll move this thread to Bugs so they can either explain it of fix, if it is a bug.
Jozef Sakalos, aka Saki
A lot of valuable info at:
Saki's Extensions and Plugins
Saki's Extensions and Plugins Docs
Saki's Examples, Latest: Grid in Card Layout
Saki's Blog, Featured: Writing a Big Application in Ext, Latest: Grid MultiSearch Plugin Video
-
31 Jan 2012 2:05 AM #9
Yes, it would be great if you can do that. That way I'll know if it's going to be fixed, of if I should start thinking of a workaround for it.
Regards,
Joao Maia
-
1 Feb 2012 3:26 AM #10
Hi Saki,
Have you moved the thread to the Bugs ? Do you know where I can get any feedback on this issue from the developers ?
Please let me know where or how I can follow up this issue.
Thank you,
jm
Looks like we can't reproduce the issue or there's a problem in the test case provided.


Reply With Quote