Announcement

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

    [SmartGWT.mobile] Issues in DataSource calls

    1. SmartGWT.mobile 1.0
    2. Browser: Chromium 17.0.963.83
    3. Eclipse IDE 3.7.2 - Google Plugin for Eclipse 2.5.2

    Problem #1 - Missing metaDataPrefix on requests

    If you read the user_guide.txt of SmartGWT.mobile you'll find the following statement:
    "Specifically, the DataSource implementation in SmartGWT.mobile behaves like a RestDataSource with dataFormat:"json"."
    If you then refer to the RestDataSource of SmartGWT (http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/data/RestDataSource.html) you'll find the following:
    If sendMetaData is true, the DSRequest meta data properties will also be present as parameters, prefixed with metaDataPrefix.

    Example URL constructed with the metaDataPrefix set to "_" (the default):

    [dataURL]?field1=value1&_operationType=fetch&_startRow=0&_endRow=50&_sortBy=-field2&_dataSource=dsName

    In this case the server would be able to separate the request's data from the meta data via the "_" prefix.
    If the SmartGWT.mobile behaves like a RestDataSource you should be able to define the sendMetaData flag and the metadata should have the default prefix. Instead the metadata is sent without the prefix.

    Steps to reproduce:
    * Check the online demo: http://smartgwt-mobile.smartclient.com/
    * Go to: Data Binding > Table View (Check the request to the server),
    Code:
    {
       operationType: "fetch", dataSource: "continentsDS", requestId: 2,
       startRow: 0, endRow: 1
    }
    * The metadata parameters should be prefixed with "_", so "_operationType" instead the request goes with "operationType".

    Checking the Java implementation you'll find:
    Code:
    @SuppressWarnings("unchecked")
        private void performDSOperation(String opType, Record data,
                        DSCallback callback, DSRequest props) 
        {
            
            // Form a DSRequest
            DSRequest dsRequest = new DSRequest();
            dsRequest.put("operationType", opType);      // <-- this should be configurable?
            dsRequest.put("dataSource", this.get("ID"));
            dsRequest.put("data", data);
            dsRequest.put("callback", callback);
            dsRequest.put("requestId", _getNextRequestId());
            if (props != null) dsRequest.putAll(props);
            
            // Declined to implement a ton of involved sort logic here...
    
            sendDSRequest(dsRequest);
        }

    Problem # 2 - Exception when data returned contains a null value - Bug in: JSONUtils.getPropertyType

    If the data array on a server response contains a record, and the value of one of the properties it's null the operation fails with:
    Code:
    com.google.gwt.core.client.JavaScriptException: (TypeError): Cannot read property 'constructor' of null
    Checking the implementation of JSONUtils.getPropertyType:
    Code:
     public static native String getPropertyType(JavaScriptObject jso, String keyName) /*-{
            var value = jso[keyName];
            var type = typeof value;
            if (type == 'object') {     // <--- Here you need to check if is null since: typeof null === 'object' 
              // (... some code)
            }
            // (... some code)
            return type;
        }-*/;
    Sample of response that will make the operation fail:
    Code:
    {
      response: {
        status: 0,
        startRow: 0,
        endRow: 0,
        totalRows: 1,
        data: [{
          field1: null,
          field2: "value"
        }]
      }
    }
    Thanks,

    Ivan

    #2
    Hi,
    A RestDataSource is used just like a normal DataSource. RestDataSources are pre-configured, using the general-purpose databinding facilities of DataSources, to expect a particular format for responses and to send requests in a specific format.
    http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/data/RestDataSource.html

    The default OperationBidings for a DataSource (behaves like a RestDataSource) are not set when building new instance of the class.

    I'm using a simple code like this:
    Code:
      private Panel getPanel(String panelName, String entityName) {
        final Panel panel = new ScrollablePanel(panelName);
    
        DataSource ds = new DataSource();
        ds.setSendMetaData(true);
        ds.setTitleField("_identifier");
        ds.addField(new DataSourceField("_identifier", "string"));
        ds.setDataURL("./org.openbravo.service.datasource/" + entityName);
    
        final TableView tv = new TableView();
        tv.setDataSource(ds);
        panel.addMember(tv);
    
        tv.fetchData();
        return panel;
      }
    }
    This build of 2012-03-29, introduces a regression, since now the default OperationBinding are not available when creating a DataSource object. Check the constructor of the class:

    Code:
        public DataSource() {
            attributes.put("dataTagName", "data");
            attributes.put("recordName", "record");
            attributes.put("sendMetaData", Boolean.TRUE);
            attributes.put("metaDataPrefix", "_");
            // What's missing is something like: attributes.put("operationBindings", something);
        }
    And now the whole flow of making DataSource requests expect a OperationBinding[], if is not available it fallback to DSDataFormat.ISCSERVER instead of DSDataFormat.JSON

    Thanks,

    Ivan

    Comment


      #3
      Hi again,

      Also check why the a call to fetchData() makes 2 requests to the server.

      Steps to reproduce:
      * Visit: http://smartgwt-mobile.smartclient.com/
      * Open your favorite network monitor (e.g. Chrome Web Tools - Network tab)
      * Go to: Data Binding > Table View
      * Check that 2 requests are made to the server (continents)

      Cheers,

      Ivan

      Comment


        #4
        Could you clarify your post #2 above - the DataSource in SmartGWT.mobile uses the RestDataSource protocol by default, and never uses the ISCSERVER protocol. So why would it matter whether it creates OperationBindings by default?

        Comment


          #5
          Hi,

          Regarding post #2.

          I updated the smartgwt-mobile.jar to the latest build, then added to the previous code snippet the line:
          Code:
          ds.setSendMetaData(true);
          Recompiled and restarted the Dev Mode server, and test it. After the update I was not able to see the request's metadata in the Network Panel of Chrome Web Tools.

          Debugging the code, I found that there is no OpenrationBinding[] defined for the DataSource object, therefore the code assumes that there is a ISCSERVER request.

          Code:
          private void sendGWTRequest(DSRequest dsRequest) {
                  final OperationBinding opBinding = getOperationBinding(dsRequest);
          
                  final DSDataFormat dataFormat;
                  if (opBinding == null) dataFormat = DSDataFormat.ISCSERVER;
                  else if (opBinding.getDataFormat() != null) dataFormat = opBinding.getDataFormat();
                  else dataFormat = DSDataFormat.ISCSERVER;
                  assert dataFormat != null;
          // (... rest of the code)
          }
          You can also see it in the online demo. In my first report (post #1) I was able see the post data sent in the request, now i'm not able.

          Hopefully this clarifies the issue.

          Thanks,

          Ivan

          Comment


            #6
            Hi,

            Friendly bump!

            Any news on this? am I doing something wrong?

            Thanks,

            Ivan

            Comment


              #7
              The latest build contains fixes for both issues.

              Comment


                #8
                Hi again,

                Here you have my Environment Details:
                * Eclipse 3.7.2
                * Google Plugin for Eclipse 2.5.2
                * Google Web Toolkit SDK 2.4.0
                * Browser: Chromium 18.0.1025.162

                The issue related to the 2 requests for triggered by a single fetchData() is still present in SmartGWT.mobile 1.0 (downloaded on 2012-04-19)

                Here you have my sample code:
                Code:
                    final Panel panel = new ScrollablePanel(panelName);
                
                    DataSource ds = new DataSource();
                    ds.setTitleField("name");
                    ds.addField(new DataSourceField("name", "string"));
                    ds.setDataURL("products.json");
                
                    final TableView tv = new TableView();
                    tv.setDataPageSize(50);
                    tv.setDataSource(ds);
                    panel.addMember(tv);
                
                    tv.fetchData();
                And a sample response from *products.json*

                Code:
                {
                  "response": {
                    "startRow": 0,
                    "endRow": 4,
                    "totalRows": 5,
                    "data": [{
                      "id": "0DC5C5281B3643DEAB978EB04139516B",
                      "name": "Orange Juice bio",
                    }, {
                      "id": "20EA4222B741434A9203471A3B29C343",
                      "name": "Vino Blanco 0,75L",
                    }, {
                      "id": "20FBF069AC804DE9BF16670000B9562E",
                      "name": "Cherry Cola",
                    }, {
                      "id": "2A81EB0F5C4F40F6A6E04A938F8DCFF9",
                      "name": "Office Rental",
                    }, {
                      "id": "34560A057833457D962F7A573F76F5BB",
                      "name": "Ale Beer",
                    }],
                    "status": 0
                  }
                }
                This triggers a double request in the same call. See the attached pic.


                Thanks,

                Ivan
                Attached Files

                Comment

                Working...
                X