Looks like we can't reproduce the issue or there's a problem in the test case provided.
  1. #1
    Touch Premium Member
    Join Date
    Jan 2011
    Location
    Lisbon, Portugal
    Posts
    192
    Vote Rating
    0
    jmaia is on a distinguished road

      0  

    Post 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

  2. #2
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,509
    Vote Rating
    374
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Do you use some proxy extension? I haven't seen proxy type 'jsonAjax' before.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  3. #3
    Touch Premium Member
    Join Date
    Jan 2011
    Location
    Lisbon, Portugal
    Posts
    192
    Vote Rating
    0
    jmaia is on a distinguished road

      0  

    Default


    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

  4. #4
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,509
    Vote Rating
    374
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    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

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  5. #5
    Touch Premium Member
    Join Date
    Jan 2011
    Location
    Lisbon, Portugal
    Posts
    192
    Vote Rating
    0
    jmaia is on a distinguished road

      0  

    Default


    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

  6. #6
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,509
    Vote Rating
    374
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Well, the logic of firing exception event is quite straightforward - response must contain success:false:
    PHP Code:
        processResponse: function(successoperationrequestresponsecallbackscope){
            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, {
                        
    responseresponse,
                        
    resultSetresult
                    
    });

                    
    operation.commitRecords(result.records);
                    
    operation.setCompleted();
                    
    operation.setSuccessful();
                } else {
                    
    operation.setException(result.message);
                    
    me.fireEvent('exception'thisresponseoperation);
                }
            } else {
                
    me.setException(operationresponse);
                
    me.fireEvent('exception'thisresponseoperation);
            }

            
    //this callback is the one that was passed to the 'read' or 'write' function above
            
    if (typeof callback == 'function') {
                
    callback.call(scope || meoperation);
            }

            
    me.afterRequest(requestsuccess);
        }, 
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  7. #7
    Touch Premium Member
    Join Date
    Jan 2011
    Location
    Lisbon, Portugal
    Posts
    192
    Vote Rating
    0
    jmaia is on a distinguished road

      0  

    Default


    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

  8. #8
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,509
    Vote Rating
    374
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    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

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  9. #9
    Touch Premium Member
    Join Date
    Jan 2011
    Location
    Lisbon, Portugal
    Posts
    192
    Vote Rating
    0
    jmaia is on a distinguished road

      0  

    Default


    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

  10. #10
    Touch Premium Member
    Join Date
    Jan 2011
    Location
    Lisbon, Portugal
    Posts
    192
    Vote Rating
    0
    jmaia is on a distinguished road

      0  

    Default


    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

Thread Participants: 2