Results 1 to 9 of 9

Thread: Problems with rest proxy for cordova packaged app

  1. #1
    Sencha User
    Join Date
    Jan 2014
    Posts
    4
    Answers
    1

    Default Answered: Problems with rest proxy for cordova packaged app

    Hi there,

    I have developed a simple shopping list application which connects to a remote server to perform CRUD operations on the list.

    The Sencha Touch code connects to the server using a rest proxy, which (I believe) performs Ajax calls to perform the various get, post, put operations etc.

    I have used CORS to get around the cross-domain Ajax issues, by setting the response headers appropriately on the back-end rest server, which is written in PHP.

    This all seems to be working perfectly on my local machine - I can see the various HTTP requests being fired off to the remote server, and everything is coming back fine.

    When I package this app to run on Android, the proxy doesn't seem to work any more.

    Here is the code for the model with the proxy:
    Code:
    Ext.define('ShoppingList.model.ShoppingListItem', {
        extend: 'Ext.data.Model',
        fields: [
            'label', 'itemId',
        ],
        proxy: {
            type: 'rest',
            url: 'http://xxxx.com/app.php/shoppinglist',
            reader: {
                type: 'json',
                root: 'items'
            },
            writer: {
                type: 'json'
            }
        }    
    });
    I have tried adding a listener to the load event of the store to see what is being returned - 'successful' is coming back as 'true' - but there are no records.

    The strange thing is - aside from this proxy, I also make a direct Ajax call separately in the app.js file, to retrieve a maximum id from the list. This call appears to work in the packaged app - the alert is shown and the response is displayed correctly.

    Code:
    Ext.Ajax.request({
        url: 'http://xxxx.com/max_id_cors.php',
        reader: {
            type: 'json',
            root: 'maxItems'
        },
        success : function(response) {
            alert('it worked! ' + response.responseText);
            maxId = response.responseText;
        },
        failure : function(response, options) {
            alert('it did not work!' + response.responseText);
            console.log("Failure" + response.responseText + ", status: "
                    + response.status);
        }
    });
    Because this part works - I'm fairly sure there are no CORS-related cross-domain issues going on here. Both php scripts that are referred to are returning the same headers, and aside from that it's working on my local machine.

    I'm building the app using the "sencha app build native" command, and it is packaging with Cordova.

    Does anybody have any idea where I'm going wrong?

    Best regards,
    Keith

  2. I finally managed to get this to work - I reworked my code a little and did the following things:

    - Moved the proxy to the store instead of the model.
    - Separated out my dataview, proxy, model and store into their own files.

    I think the second item is what fixed it. My project has a dataview which loads data from the rest proxy to display records. Previously I was defining my dataview as part of the 'items' list of my main view, like this:

    Main.js:
    Code:
    Ext.define('ShoppingList.view.Main', {
        extend: 'Ext.tab.Panel',
        xtype: 'main',
        requires: [
            ...
        ],
        config: {
            tabBarPosition: 'bottom',
    
    
            items: [{
                    ... tab bar here ...
                },{
                    xtype: 'dataview',
                    scrollable: true,
                    id: 'shoppinglist',
                    store: 'ShoppingListStore',
                    useComponents: true,
                    defaultType: 'mylistitem'
                }
            },{
                ... other pages here ... 
            }]
        }
    });
    I changed this so that the dataview was defined in its own view file:

    ShoppingList.js:
    Code:
    Ext.define('ShoppingList.view.ShoppingList', {
        extend: 'Ext.dataview.DataView',
        alias: 'widget.shoppinglistview',
        requires: [
            'ShoppingList.store.ShoppingListStore',
            'ShoppingList.view.ListItem'
        ],
        config: {
            layout: 'fit',
            scrollable: true,
            id: 'shoppinglist',
            store: 'ShoppingListStore',
            useComponents: true,
            defaultType: 'mylistitem'
        }
    });
    ... and then referenced that from Main.js:
    Code:
    Ext.define('ShoppingList.view.Main', {
        extend: 'Ext.tab.Panel',
        xtype: 'main',
        requires: [
            ...
        ],
        config: {
            tabBarPosition: 'bottom',
    
    
            items: [{
                    ... tab bar here ...
                },{
                    xtype: 'shoppinglistview'
                }]
            },{
                ... other pages here ... 
            }]
        }
    });
    I'm not sure why this worked - I'd guess it might be something to do with the order in which things are loaded between the two different methods shown above. Hope this helps someone with a similar problem.

  3. #2

    Default

    Wow, this is my exact problem too. Been trying to fix it for the passed day.

    It works on my browser both via MAMP and local file access but as soon as it goes through the build command it has issues.

    Like Schoke, i too have stuck in console logs and alerts to make sure it's loading all the individual files.

    I am using Stackmob though.

    Hopefully someone can help with our problem

  4. #3
    Sencha User
    Join Date
    Aug 2010
    Posts
    315
    Answers
    4

    Default

    Hi, you have to whitelist the domain you are accessing with cordova:
    http://docs.phonegap.com/en/3.3.0/guide_appdev_whitelist_index.md.html#Whitelist%20Guide
    A
    nd if you are targetting local machine (127.0.0,1) in your test this will not work in a packaged app as 127.0.0.1 is referring to your device, you have to publish the backend on a public ip or domain.

  5. #4

    Default

    Hey @steve1964,

    I have my whitelist set to * to allow all connections to try and get it working. It has no effect.

    One think i can add is i am using the Sencha StackMob plugin and on the local build it works fine as it adds the api.stackmob.com to my schema url. For example, my store looks like this:


    Code:
    Ext.define('LoginDemo.store.Attendees', { // (or model)   
     extend: 'Ext.data.Store', // (or Ext.data.Model)    
    
    requires: [       
     'LoginDemo.model.AttendeesModel',       
     'Ext.data.proxy.Ajax'    
    ],   
    
    config: {        
        autoload: true,        
        model: 'LoginDemo.model.AttendeesModel',       
        storeId: 'Attendees',        
        proxy: {           
            type: 'stackmob',            
            url: 'attendees'        
        }    
    }
    });
    Running this on Chrome works as it will take the above url and add it after the api.stackmob.com

    But when i package the app to run it on the simulator or device it doesn't pick it up and shows the error:

    Code:
    GET http://localhost:8888/LoginDemo/phonegap/www/attendees 404 (Not Found)
    Which means it doesn't replace the local domain with "api.stackmob.com" as it should and does when running locally.

  6. #5
    Sencha User
    Join Date
    Jan 2014
    Posts
    4
    Answers
    1

    Default

    Hi steve1964,

    The domain I'm trying to access is already whitelisted in config.xml. It's a remote target so it's not targetting localhost.

    As noted, a direct Ext.Ajax.request call to this domain does work. It seems to be only on the rest proxy that it's not working.

  7. #6
    Sencha User
    Join Date
    Jan 2014
    Posts
    4
    Answers
    1

    Default

    So I've been doing some more digging deep in the Sencha Touch js code... it seems as though the proxy that's being constructed is actually a Memory proxy and not a Rest proxy. No idea why this is happening!!

    To test this out on my app - I added the following constructors to the Sencha Touch files within my project:

    src/data/proxy/Memory.js:
    Code:
     constructor: function(config) {
      alert('constructing a memory proxy');
      this.callParent(arguments);
     },
    src/data/proxy/Rest.js:
    Code:
     
    constructor: function(config) {
      alert('constructing a rest proxy');
      this.callParent(arguments);
     },
    Running the app on my local machine shows me the alert - "constructing a rest proxy"... this calls the rest service as expected.

    Running the app packaged on my Android emulator shows me the alert - "constructing a memory proxy". No call is issued to the rest service.

    Is this a bug? Any way I can get around this?

  8. #7

    Default

    Excellent find!!

    Does anyone have any idea how to fix this, i'd like to really try getting the app on a device

  9. #8
    Sencha User
    Join Date
    Jan 2014
    Posts
    4
    Answers
    1

    Default

    I finally managed to get this to work - I reworked my code a little and did the following things:

    - Moved the proxy to the store instead of the model.
    - Separated out my dataview, proxy, model and store into their own files.

    I think the second item is what fixed it. My project has a dataview which loads data from the rest proxy to display records. Previously I was defining my dataview as part of the 'items' list of my main view, like this:

    Main.js:
    Code:
    Ext.define('ShoppingList.view.Main', {
        extend: 'Ext.tab.Panel',
        xtype: 'main',
        requires: [
            ...
        ],
        config: {
            tabBarPosition: 'bottom',
    
    
            items: [{
                    ... tab bar here ...
                },{
                    xtype: 'dataview',
                    scrollable: true,
                    id: 'shoppinglist',
                    store: 'ShoppingListStore',
                    useComponents: true,
                    defaultType: 'mylistitem'
                }
            },{
                ... other pages here ... 
            }]
        }
    });
    I changed this so that the dataview was defined in its own view file:

    ShoppingList.js:
    Code:
    Ext.define('ShoppingList.view.ShoppingList', {
        extend: 'Ext.dataview.DataView',
        alias: 'widget.shoppinglistview',
        requires: [
            'ShoppingList.store.ShoppingListStore',
            'ShoppingList.view.ListItem'
        ],
        config: {
            layout: 'fit',
            scrollable: true,
            id: 'shoppinglist',
            store: 'ShoppingListStore',
            useComponents: true,
            defaultType: 'mylistitem'
        }
    });
    ... and then referenced that from Main.js:
    Code:
    Ext.define('ShoppingList.view.Main', {
        extend: 'Ext.tab.Panel',
        xtype: 'main',
        requires: [
            ...
        ],
        config: {
            tabBarPosition: 'bottom',
    
    
            items: [{
                    ... tab bar here ...
                },{
                    xtype: 'shoppinglistview'
                }]
            },{
                ... other pages here ... 
            }]
        }
    });
    I'm not sure why this worked - I'd guess it might be something to do with the order in which things are loaded between the two different methods shown above. Hope this helps someone with a similar problem.

  10. #9

    Default

    I also fixed my issue. I found that in the app.json i needed to add a custom path under the js section to include the file for compression. It wasn't being added to the build and was therefore throwing an error.

    Doing this fixed my issue and allowed the app to work as it did on production.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •