com.smartgwt.client.data
Class RestDataSource

java.lang.Object
  extended by com.smartgwt.client.core.BaseClass
      extended by com.smartgwt.client.data.DataSource
          extended by com.smartgwt.client.data.RestDataSource
All Implemented Interfaces:
HasHandlers, HasHandleErrorHandlers

public class RestDataSource
extends DataSource

The RestDataSource implements the 4 core DataSource operations using a simple protocol of XML or JSON requests and responses sent over HTTP, which can be easily fulfilled by any HTTP server technology.

RestDataSource is named for the REST (REpresentational State Transfer) pattern, which in brief says that simple messages passed over HTTP is a sufficient protocol for many web applications, without the need for further protocols such as WSDL or SOAP.

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. These request and response formats represent Isomorphic's recommended best practices for binding SmartGWT to backends which do not already support a similar, pre-existing request and response format and where the SmartGWT Java Server cannot be used.

If you have a pre-existing REST or WSDL service which is difficult to change, consider adapting SmartGWT to the existing service instead, by starting with a normal DataSource and using the 'client-side data integration' facilities to create a mapping between SmartGWT's DSRequest and DSResponse objects and the message formats of your existing services.

RestDataSource is typically used with PHP, Ruby, Python, Perl or custom server technologies, and represents an alternative to installing the SmartGWT Server in a Java technology stack, or using 'WSDL-based binding' with .NET or other WSDL-capable technologies.

The request and response formats used by the RestDataSource allow for many of the available features of SmartGWT's databinding system to be used, including data paging, searching & sorting, oldValues, com.smartgwt.client.data.ResultSet and 'relogin'. However advanced features such as 'uploading / binary fields', RPCManager.startQueue() and transaction chaining, ListGrid.exportData() and all 'server-based features' aren't available with RestDataSource and need to be re-implemented as needed.

Examples

XML formatted responses:

RestDataSource expects a response to like the following in response to a "fetch" request:

 <response>
    <status>0</status>
    <startRow>0</startRow>
    <endRow>76</endRow>
    <totalRows>546</totalRows>
    <data>
      <record>
          <field1>value</field1>
          <field2>value</field2>
      </record>
      <record>
          <field1>value</field1>
          <field2>value</field2>
      </record>
      ... 75 total records ... 
    </data>
 </response>
 
The <status> element indicates whether the fetch operation was successful (see StatusCodes).

The <data> element contains a list of record nodes, each of which represents a record returned by the server. The optional <startRow>, <endRow> and <totalRows> elements are needed only if data paging is in use, and populate the startRow, endRow and totalRows properties of the DSResponse.

Note: for a more compact format, simple field values may be specified on record nodes directly as attributes - in this case a record element might be structured like this:

     <record field1="value" field2="value" />
 

Note that a RestDataSource will bypass browser caching of all responses by default. See preventHTTPCaching.

Successful "add" or "update" request responses are similar in format - in this case the data element would be expected to contain a single record object containing the details of the record, as saved on the server.

The response from a "remove" operation would again include status and data elements, but in this case, only the primary key field value(s) of the removed record would be expected to be present under the data element.

If a validation failure occurred on the server, the response would have status set to RPCResponse.STATUS_VALIDATION_ERROR [-4], and any validation errors could be included as per-field sub-elements of an "errors" element. For a validation error, the response is not be expected to contain any <data> element.

A response showing a validation error might look like this:

 <response>
    <status>-4</status>
    <errors>
      <field1>
          <errorMessage>A validation error occurred for this field</errorMessage>
      </field1>
    </errors>
 </response>
 

An unrecoverable error, such as an unexpected server failure, can be flagged by setting <status> to -1 and setting <data> to an error message. In this case the <errors> element is not used (it's specific to validation errors). An unrecoverable error causes all response processing to be skipped and com.smartgwt.client.rpc.RPCManager#handleError to be invoked, which by default will show the provided error message as an alert using com.smartgwt.client.util.isc#warn.

JSON formatted responses:

JSON format responses are expected to contain the same data / meta-data as XMLresponses, encapsulated a simple object with a "response" attribute.
The response to a "fetch" request would therefore have this format:

 {    
    response:{
       status:0,
       startRows:0,
       endRow:76,
       totalRows:546,
       data:[
           {field1:"value", field2:"value"},
           {field1:"value", field2:"value"},
           ... 75 total records ...
       ]
    }
 }
 
The structure successful for "add", "update" and "remove" responses would be similar, though the data array would be expected to contain only a single object, representing the values as saved. This allows the server to return values such as an auto-generated sequence primaryKey, a last modified timestamp, or similar server-generated field values.

For a remove, only the value for the primaryKey field[s] would be required.

For a validation error, the status attribute would be set to RPCResponse.STATUS_VALIDATION_ERROR [-4], and errors would be specified in the errors attribute of the response. For example:

 {    response:
      {   status:-4,
          errors: 
              {   field1:{errorMessage:"A validation error on field1"},
                  field2:{errorMessage:"A validation error on field2"}
              }
      }
 }
 
An array of errors may also be returned for a single field, like this:
 {    response:
      {   status:-4,
          errors: 
              {   field1:[
                      {errorMessage:"First error on field1"},
                      {errorMessage:"Second error on field1"}
                  ]
              }
      }
 }
 

As with the XML format above, an unrecoverable error is indicated by setting the status attribute to -1 and the data property to the error message.

Server inbound data formats

The format of data sent to the server is determined by the dataProtocol specified for the operation. Request data is sent as parameters if the format is specified as "getParams" or "postParams".

In this case, the parameters sent to the server will consist of the DSRequest's data, and any parameters explicitly specified on the DSRequest object (as params.
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 data is sent to the server via the "postMessage" dataProtocol, the data will be serialized as an XML or JSON message according to the dataFormat setting. Both XML and JSON messages will contain request metadata such as startRow and endRow, and will appear exactly as though the subset of the DSRequest that is meaningful to the server had been passed to DataSource.xmlSerialize(com.google.gwt.core.client.JavaScriptObject) or com.smartgwt.client..JSON#encode respectively.

An example of an XML message might look like this:

    <data>
        <countryDS>
            <countryCode>US</countryCode>
            <countryName>Edited Value</countryName>
            <capital>Edited Value</capital>
            <continent>Edited Value</continent>
        </countryDS>
    </data>
    <dataSource>countryDS</dataSource>
    <operationType>update</operationType>
 
The operationBindings for a RestDataSource specify dataProtocol as "getParams" for the fetch operation, and "postParams" for update, add and remove operations.

Hierachical (Tree) data:

To create a hierachical DataSource, in the DataSource's fields array, a field must be specified as the parent id field - the field which will contain a pointer to the id of each node's parent. This can be achieved by setting the foreignKey and the rootValue attributes on the field definition. For example:

 RestDataSource.create({
    ID:"supplyItem",
    fields : [
        {name:"itemId", type:"sequence", primaryKey:true},
        {name:"parentId", type:"integer", foreignKey:"supplyItem.itemId", rootValue:0},
        ...
    ]
 });
 
Tree Data is then treated on the server as a flat list of records linked by parent id.
Tree data is typically displayed using a dataBound TreeGrid component. TreeGrids automatically create a com.smartgwt.client..ResultTree data object, which requests data directly from the DataSource. ResultTrees load data on demand, only requesting currently visible (open) nodes from the server. This is handled by including a specified value for the parent id field in the request criteria.
To implement a standard load-on-demand tree RestDataSource back end, you should therefore simply return the set of nodes that match the criteria passed in. For example, if your DataSource was defined as the "supplyItem" code snippet above, a fetch request for all children of a node with itemId set to 12 would have "parentId" set to 12 in the request criteria. A valid response would then contain all the records that matched this criteria. For example:
 <response>
    <status>0</status>
    <data>
      <record>
          <itemId>15</itemId>
          <parentId>12</parentId>
      </record>
      <record>
          <itemId>16</itemId>
          <parentId>12</parentId>
      </record>
    </data>
 </response>
 
The structure of responses for Add, Update and Delete type requests will be the same regardless of whether the data is hierachical. However you should be aware that the underlying data storage may need to be managed slightly differently in some cases.
Specifically, Add and Update operations may change the structure of the tree by returning a new parent id field value for the modified node. Depending on how your data is stored you may need to include special back-end logic to handle this.
Also, if a user deletes a folder within a databound tree, any children of that folder will also be dropped from the tree, and can be removed from the back-end data storage.
Note: For a general overview of binding components to Tree structured data, see 'Tree Databinding'.


Field Summary
 
Fields inherited from class com.smartgwt.client.core.BaseClass
config, id
 
Constructor Summary
RestDataSource()
           
RestDataSource(com.google.gwt.core.client.JavaScriptObject jsObj)
           
 
Method Summary
 com.google.gwt.core.client.JavaScriptObject create()
           
 java.lang.String getAddDataURL()
          Custom dataURL for add type operations
 java.lang.String getDataURL()
          Default URL to contact to fulfill all DSRequests.
 java.lang.String getFetchDataURL()
          Custom dataURL for fetch type operations
 java.lang.String getJsonRecordXPath()
          recordXPath mapping to the data node of json returned by the server. Applies if this.dataFormat is set to "json"
The default value will pick up data from a response structured as follows:
 java.lang.String getMetaDataPrefix()
          I sendMetaData is true, this attribute is used to specify the prefix to apply to 'meta data' properties when assembling parameters to send to the server.
static RestDataSource getOrCreateRef(com.google.gwt.core.client.JavaScriptObject jsObj)
           
 java.lang.Boolean getPrettyPrintJSON()
          When using dataFormat:"json" and dataProtocol:"postMessage" should we use the prettyPrint feature to enable indented, highly readable JSON messages.
 java.lang.String getRecordXPath()
          For RestDataSources, by default, either the xmlRecordXPath or jsonRecordXPath is used by default based on the dataFormat setting.
 java.lang.String getRemoveDataURL()
          dataURL for fetch type operations
 java.lang.Boolean getSendMetaData()
          Should operation meta data be included when assmebling parameters to send to the server? If true, meta data parameters will be prefixed with the metaDataPrefix.
Applies to operations where OperationBinding.dataProtocol is set to "getParams" or "postParams" only.
 java.lang.String getUpdateDataURL()
          Custom dataURL for update type operations
 java.lang.String getXmlRecordXPath()
          recordXPath mapping to the data node of XML returned by the server. Applies if this.dataFormat is set to "xml".
The default value will pick up data from a response structured as follows:
 void setAddDataURL(java.lang.String addDataURL)
          Custom dataURL for add type operations
 void setDataURL(java.lang.String dataURL)
          Default URL to contact to fulfill all DSRequests.
 void setFetchDataURL(java.lang.String fetchDataURL)
          Custom dataURL for fetch type operations
 void setJsonRecordXPath(java.lang.String jsonRecordXPath)
          recordXPath mapping to the data node of json returned by the server. Applies if this.dataFormat is set to "json"
The default value will pick up data from a response structured as follows:
 void setMetaDataPrefix(java.lang.String metaDataPrefix)
          I sendMetaData is true, this attribute is used to specify the prefix to apply to 'meta data' properties when assembling parameters to send to the server.
 void setPrettyPrintJSON(java.lang.Boolean prettyPrintJSON)
          When using dataFormat:"json" and dataProtocol:"postMessage" should we use the prettyPrint feature to enable indented, highly readable JSON messages.
 void setRecordXPath(java.lang.String recordXPath)
          For RestDataSources, by default, either the xmlRecordXPath or jsonRecordXPath is used by default based on the dataFormat setting.
 void setRemoveDataURL(java.lang.String removeDataURL)
          dataURL for fetch type operations
 void setSendMetaData(java.lang.Boolean sendMetaData)
          Should operation meta data be included when assmebling parameters to send to the server? If true, meta data parameters will be prefixed with the metaDataPrefix.
Applies to operations where OperationBinding.dataProtocol is set to "getParams" or "postParams" only.
 void setUpdateDataURL(java.lang.String updateDataURL)
          Custom dataURL for update type operations
 void setXmlRecordXPath(java.lang.String xmlRecordXPath)
          recordXPath mapping to the data node of XML returned by the server. Applies if this.dataFormat is set to "xml".
The default value will pick up data from a response structured as follows:
 
Methods inherited from class com.smartgwt.client.data.DataSource
addData, addData, addData, addField, addHandleErrorHandler, fetchData, fetchData, fetchData, fetchData, filterData, filterData, filterData, get, getAddGlobalId, getAutoDeriveSchema, getAutoDeriveTitles, getCallbackParam, getChildrenField, getClientOnly, getClientOnlyResponse, getCriteriaPolicy, getDataFormat, getDataProtocol, getDataSource, getDataTransport, getDbName, getDropExtraFields, getField, getIconField, getJsObj, getJsonPrefix, getJsonSuffix, getLegalChildTags, getPluralTitle, getPreventHTTPCaching, getPrimaryKeyField, getPrimaryKeyFieldName, getQualifyColumnNames, getResultBatchSize, getSchemaNamespace, getSendExtraFields, getServerConstructor, getServerType, getServiceNamespace, getShowLocalFieldsOnly, getShowPrompt, getStrictSQLFiltering, getTableName, getTagName, getTestData, getTitle, getTitleField, getUseFlatFields, getUseLocalValidators, getUseParentFieldOrder, isCreated, onInit, processResponse, recordsFromXML, removeData, removeData, removeData, setAddGlobalId, setAutoDeriveSchema, setAutoDeriveTitles, setCallbackParam, setChildrenField, setClientOnly, setCriteriaPolicy, setDataFormat, setDataProtocol, setDataTransport, setDbName, setDefaultParams, setDropExtraFields, setEnumConstantProperty, setEnumOrdinalProperty, setEnumTranslateStrategy, setFields, setIconField, setInheritsFrom, setJsonPrefix, setJsonSuffix, setOperationBindings, setPluralTitle, setPreventHTTPCaching, setQualifyColumnNames, setRecordName, setRequestProperties, setResultBatchSize, setSendExtraFields, setServerConstructor, setServerType, setServiceNamespace, setShowLocalFieldsOnly, setShowPrompt, setStrictSQLFiltering, setTableName, setTagName, setTestData, setTitle, setTitleField, setUseFlatFields, setUseLocalValidators, setUseParentFieldOrder, setXmlNamespaces, supportsTextMatchStyle, transformRequest, transformResponse, updateData, updateData, updateData, xmlSerialize, xmlSerialize
 
Methods inherited from class com.smartgwt.client.core.BaseClass
destroy, doAddHandler, error, errorIfNotCreated, fireEvent, getAttribute, getAttributeAsBoolean, getAttributeAsDouble, getAttributeAsElement, getAttributeAsFloat, getAttributeAsInt, getAttributeAsJavaScriptObject, getAttributeAsString, getConfig, getHandlerCount, getID, getOrCreateJsObj, getRef, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setAttribute, setID, setProperty, setProperty, setProperty, setProperty
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface com.google.gwt.event.shared.HasHandlers
fireEvent
 

Constructor Detail

RestDataSource

public RestDataSource()

RestDataSource

public RestDataSource(com.google.gwt.core.client.JavaScriptObject jsObj)
Method Detail

getOrCreateRef

public static RestDataSource getOrCreateRef(com.google.gwt.core.client.JavaScriptObject jsObj)

create

public com.google.gwt.core.client.JavaScriptObject create()
Overrides:
create in class DataSource

setXmlRecordXPath

public void setXmlRecordXPath(java.lang.String xmlRecordXPath)
                       throws java.lang.IllegalStateException
recordXPath mapping to the data node of XML returned by the server. Applies if this.dataFormat is set to "xml".
The default value will pick up data from a response structured as follows:
 <response>
    <status>0</status>
    <data>
      <record>
          <field1>value</field1>
          <field2>value</field2>
      </record>
      <record>
          <field1>value</field1>
          <field2>value</field2>
      </record>
    </data>
 </response>
 

Parameters:
xmlRecordXPath - xmlRecordXPath Default value is "/response/data/*"
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getXmlRecordXPath

public java.lang.String getXmlRecordXPath()
recordXPath mapping to the data node of XML returned by the server. Applies if this.dataFormat is set to "xml".
The default value will pick up data from a response structured as follows:
 <response>
    <status>0</status>
    <data>
      <record>
          <field1>value</field1>
          <field2>value</field2>
      </record>
      <record>
          <field1>value</field1>
          <field2>value</field2>
      </record>
    </data>
 </response>
 

Returns:
String

setJsonRecordXPath

public void setJsonRecordXPath(java.lang.String jsonRecordXPath)
                        throws java.lang.IllegalStateException
recordXPath mapping to the data node of json returned by the server. Applies if this.dataFormat is set to "json"
The default value will pick up data from a response structured as follows:
 {response:
  {status:0,
   data:[
      {field1:"value", field2:"value"},
      {field1:"value", field2:"value"}
   ]
 }
 

Parameters:
jsonRecordXPath - jsonRecordXPath Default value is "/response/data"
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getJsonRecordXPath

public java.lang.String getJsonRecordXPath()
recordXPath mapping to the data node of json returned by the server. Applies if this.dataFormat is set to "json"
The default value will pick up data from a response structured as follows:
 {response:
  {status:0,
   data:[
      {field1:"value", field2:"value"},
      {field1:"value", field2:"value"}
   ]
 }
 

Returns:
String

setRecordXPath

public void setRecordXPath(java.lang.String recordXPath)
For RestDataSources, by default, either the xmlRecordXPath or jsonRecordXPath is used by default based on the dataFormat setting.

Note that you can also apply record xpath binding via recordXPath.

Overrides:
setRecordXPath in class DataSource
Parameters:
recordXPath - recordXPath Default value is null

getRecordXPath

public java.lang.String getRecordXPath()
For RestDataSources, by default, either the xmlRecordXPath or jsonRecordXPath is used by default based on the dataFormat setting.

Note that you can also apply record xpath binding via recordXPath.

Overrides:
getRecordXPath in class DataSource
Returns:
String

setPrettyPrintJSON

public void setPrettyPrintJSON(java.lang.Boolean prettyPrintJSON)
                        throws java.lang.IllegalStateException
When using dataFormat:"json" and dataProtocol:"postMessage" should we use the prettyPrint feature to enable indented, highly readable JSON messages.

True by default because the bandwidth involved is generally neglible and the benefits for troubleshooting are key.

Parameters:
prettyPrintJSON - prettyPrintJSON Default value is true
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getPrettyPrintJSON

public java.lang.Boolean getPrettyPrintJSON()
When using dataFormat:"json" and dataProtocol:"postMessage" should we use the prettyPrint feature to enable indented, highly readable JSON messages.

True by default because the bandwidth involved is generally neglible and the benefits for troubleshooting are key.

Returns:
Boolean

setDataURL

public void setDataURL(java.lang.String dataURL)
                throws java.lang.IllegalStateException
Default URL to contact to fulfill all DSRequests. RestDataSources also allow per-operationType dataURLs to be set via

Overrides:
setDataURL in class DataSource
Parameters:
dataURL - dataURL Default value is null
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getDataURL

public java.lang.String getDataURL()
Default URL to contact to fulfill all DSRequests. RestDataSources also allow per-operationType dataURLs to be set via

Overrides:
getDataURL in class DataSource
Returns:
String

setFetchDataURL

public void setFetchDataURL(java.lang.String fetchDataURL)
                     throws java.lang.IllegalStateException
Custom dataURL for fetch type operations

Parameters:
fetchDataURL - fetchDataURL Default value is null
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getFetchDataURL

public java.lang.String getFetchDataURL()
Custom dataURL for fetch type operations

Returns:
String

setUpdateDataURL

public void setUpdateDataURL(java.lang.String updateDataURL)
                      throws java.lang.IllegalStateException
Custom dataURL for update type operations

Parameters:
updateDataURL - updateDataURL Default value is null
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getUpdateDataURL

public java.lang.String getUpdateDataURL()
Custom dataURL for update type operations

Returns:
String

setAddDataURL

public void setAddDataURL(java.lang.String addDataURL)
                   throws java.lang.IllegalStateException
Custom dataURL for add type operations

Parameters:
addDataURL - addDataURL Default value is null
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getAddDataURL

public java.lang.String getAddDataURL()
Custom dataURL for add type operations

Returns:
String

setRemoveDataURL

public void setRemoveDataURL(java.lang.String removeDataURL)
                      throws java.lang.IllegalStateException
dataURL for fetch type operations

Parameters:
removeDataURL - removeDataURL Default value is null
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getRemoveDataURL

public java.lang.String getRemoveDataURL()
dataURL for fetch type operations

Returns:
String

setSendMetaData

public void setSendMetaData(java.lang.Boolean sendMetaData)
                     throws java.lang.IllegalStateException
Should operation meta data be included when assmebling parameters to send to the server? If true, meta data parameters will be prefixed with the metaDataPrefix.
Applies to operations where OperationBinding.dataProtocol is set to "getParams" or "postParams" only.

Parameters:
sendMetaData - sendMetaData Default value is true
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getSendMetaData

public java.lang.Boolean getSendMetaData()
Should operation meta data be included when assmebling parameters to send to the server? If true, meta data parameters will be prefixed with the metaDataPrefix.
Applies to operations where OperationBinding.dataProtocol is set to "getParams" or "postParams" only.

Returns:
Boolean

setMetaDataPrefix

public void setMetaDataPrefix(java.lang.String metaDataPrefix)
                       throws java.lang.IllegalStateException
I sendMetaData is true, this attribute is used to specify the prefix to apply to 'meta data' properties when assembling parameters to send to the server. Applies to operations where OperationBinding.dataProtocol is set to "getParams" or "postParams" only.

Parameters:
metaDataPrefix - metaDataPrefix Default value is "_"
Throws:
java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getMetaDataPrefix

public java.lang.String getMetaDataPrefix()
I sendMetaData is true, this attribute is used to specify the prefix to apply to 'meta data' properties when assembling parameters to send to the server. Applies to operations where OperationBinding.dataProtocol is set to "getParams" or "postParams" only.

Returns:
String