Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    SmartGWT.Mobile and SQL Datasources

    Version: SmartGWT.Mobile 7/5/2013

    I'm trying to call my SQL Datasources from SmartGWT.Mobile. I see the server execute the call correctly and returns proper XML, but my callback in SmartGWT.Mobile is not called.

    I would normally create a standalone example in the showcase to demonstrate the problem but the mobile showcase does not have a server module. In any case, here is my client code:

    Code:
           DataSource ds = new DataSource("get_count_info");
            ds.setMetaDataPrefix("");
            ds.setDataURL("/restAPI/");
            DataSource.setDefaultDataURL("/restAPI/");
            ds.setFetchDataURL("/restAPI/");
            
            ds.fetchData(null, new DSCallback() {
    			
    			@Override
    			public void execute(DSResponse dsResponse, Object rawData,
    					DSRequest dsRequest) {
    				if ( dsResponse != null ) {
    					if (dsResponse.getErrors() != null) {
    						
    						Record r = dsResponse.getData()[0];
    						totalDevices = r.getAttributeAsInt( "device_count" );
    						buttonDevicesBrowse[0].setTitle(String.valueOf(totalDevices) + " " + "Browse Devices");
    						buttonDevicesBrowse[1].setTitle(String.valueOf(totalDevices) + " " + "Browse Devices");
    						devicesInError = r.getAttributeAsInt( "error_count" );
    						buttonDevicesInError[0].setTitle(String.valueOf(devicesInError) + " " + "Devices in Error");
    						buttonDevicesInError[1].setTitle(String.valueOf(devicesInError) + " " + "Devices in Error");
    						devicesOutOfPaper = r.getAttributeAsInt( "no_paper_count" );
    						buttonDevicesOutOfPaper[0].setTitle(String.valueOf(devicesOutOfPaper) + " " + "Devices out of Paper");
    						buttonDevicesOutOfPaper[1].setTitle(String.valueOf(devicesOutOfPaper) + " " + "Devices out of Paper");
    						devicesOutOfToner = r.getAttributeAsInt( "no_toner_count" );
    						buttonDevicesOutOfToner[0].setTitle(String.valueOf(devicesOutOfToner) + " " + "Devices out of Toner");
    						buttonDevicesOutOfToner[1].setTitle(String.valueOf(devicesOutOfToner) + " " + "Devices out of Toner");
    				        return;
    					} 
    				}
    				//TODO: Handle error
    			}
    		});
    On the server, I have added the Isomorphic RESTHandler to my web.xml like this:
    Code:
        <servlet>
            <servlet-name>RESTHandler</servlet-name>
            <servlet-class>com.isomorphic.servlet.RESTHandler</servlet-class>
           <init-param>
               <param-name>defaultDataFormat</param-name>
               <param-value>json</param-value>
           </init-param>
           <init-param>
               <param-name>wrapJSONResponses</param-name>
               <param-value>false</param-value>
           </init-param>
        </servlet>    
    
    	<servlet-mapping>
    		<servlet-name>RESTHandler</servlet-name>
    		<url-pattern>/restAPI/*</url-pattern>
    	</servlet-mapping>
    Which generates the request in firebug:
    Code:
    GET /restAPI/?operationType=fetch&useStrictJSON=true&dataSource=get_count_info&isc_metaDataPrefix= HTTP/1.1
    Host: 10.85.22.218:8080
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0
    Accept: application/json,*/*
    Accept-Language: en,fr-ca;q=0.9,zh;q=0.7,ja;q=0.6,de;q=0.4,en-us;q=0.3,nl;q=0.1
    Accept-Encoding: gzip, deflate
    Referer: http://10.85.22.218:8080/index.html?gwt.codesvr=127.0.0.1:9997&locale=en
    Cookie: GLog=%7B%0D%20%20%20%20left%3A1754%2C%20%0D%20%20%20%20top%3A44%2C%20%0D%20%20%20%20width%3A1165%2C%20%0D%20%20%20%20height%3A1067%2C%20%0D%20%20%20%20priorityDefaults%3A%7B%0D%20%20%20%20%20%20%20%20Log%3A4%0D%20%20%20%20%7D%2C%20%0D%20%20%20%20defaultPriority%3A3%2C%20%0D%20%20%20%20trackRPC%3Atrue%0D%7D; JSESSIONID=1hd44mb9ecb5318n8vlmgzmmqc; login_token=8D101B2700E8852BCA1E4BCDAF947440; is_mobile=1
    Connection: keep-alive
    And I see the following response in firebug:
    Code:
    <?xml version="1.0"?>
    <response>
    <status>0</status>
    <queueStatus>0</queueStatus><startRow>0</startRow>
    <endRow>1</endRow>
    <totalRows>1</totalRows>
    <data>
    <record>
        <device_count>229</device_count>
        <map_device_count>0</map_device_count>
        <no_paper_count>29</no_paper_count>
        <no_toner_count>0</no_toner_count>
        <group_count>9</group_count>
        <error_count>69</error_count>
        <map_count>0</map_count>
    </record>
    </data>
    </response>
    The problem being that my execute override is never called.

    I was wondering if the fact that it returns in XML format is an issue so I tried several ways to get it to come back in JSON without success.

    I tried modifying the Showcase sample to return XML instead of JSON and saw the same behaviour (callback not called):

    Code:
    public class CountriesDataProviderServlet extends HttpServlet{
    
    	private static final long serialVersionUID = -7449311593970677641L;
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    			throws ServletException, IOException {
            int start = 0;
            String startRowParam = req.getParameter("startRow");
            if (startRowParam != null) {
                try {
                    start = Integer.parseInt(startRowParam);
                } catch (NumberFormatException ex) {}
            }
            if (start < 0) start = 0;
    
            int end = 5;
            String endRowParam = req.getParameter("endRow");
            if (endRowParam != null) {
                try {
                    end = Integer.parseInt(endRowParam);
                } catch (NumberFormatException ex) {}
            }
            if (end > 100) end = 100;
    
            resp.setContentType("text/xml");
    
    		PrintWriter wr = resp.getWriter();
            wr.write("<?xml version=\"1.0\"?><response><status>0</status><queueStatus>0</queueStatus><startRow>0</startRow><endRow>1</endRow><totalRows>1</totalRows><data><record>    <device_count>229</device_count>    <map_device_count>0</map_device_count>    <no_paper_count>29</no_paper_count>    <no_toner_count>0</no_toner_count>    <group_count>9</group_count>    <error_count>69</error_count>    <map_count>0</map_count></record></data></response>");	
        }
    
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    			throws ServletException, IOException {
    		doPost(req, resp);
    	}
    I can work towards getting a self-contained sample that demonstrates the issue but since the mobile showcase does not have a server, this will be large. Happy to hear suggestions.

    Thanks!

    Matt

    #2
    Of course I found the issue minutes after posting this.

    Adding the line:
    Code:
    ds.setDataProtocol(DSProtocol.POSTMESSAGE);
    solved my issues by forcing the call to be a POST instead of a GET, which apparently cannot be dealt with by the RESTHandler in the same way.

    Maybe this could be made clearer in the documentation? And/or maybe the mobile datasource should default to POST instead?

    Also, it would have been nice if the client had thrown an exception or warning to say that it could not consume the XML response.

    Debugging is more difficult without the console available - or am I missing something?

    Thanks,

    Matt

    Comment


      #3
      The actual issue with your GET request is that it was defaulting to expecting a JSON response and received XML instead. You can fix that by specifying XML as the response format expected:

      Code:
      final OperationBinding fetchBinding = new OperationBinding(DSOperationType.FETCH);
      fetchBinding.setDataFormat(DSDataFormat.XML);
      ds.setOperationBindings(fetchBinding);
      We've also made a change that SGWT.mobile will now just explicitly ask that the response be in XML or JSON format according to your settings on the DataSource - the server-side RESTHandler can generate either.

      On debugging/logs: SGWT.mobile logs to the browser's console rather than a separate Developer Console. To view the console logs on Android, the logcat tool can be used. On iOS 6+, (desktop) Safari has the ability to show a remote Web Inspector when the iPhone Simulator app is running or an iOS device is connected to the Mac. See http://moduscreate.com/enable-remote-web-inspector-in-ios-6/

      Comment

      Working...
      X