Announcement

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

    GWT-RPC DataSource implementation

    [from Isomorphic: we strongly recommend against using GWT-RPC for reasons listed in the FAQ. The approach is this thread should only be used as a temporary solution and only if you have a large set of pre-existing GWT-RPC services]

    Hi All,
    After some testing already provided GWT-RPC data source implementation (sticky post) (it was good starting point) I've decided to write my own. After reading post on how to implement Google Gears ( http://forums.smartclient.com/showthread.php?t=1192 ) I've realized that SmartClient already has possibility to use custom servers to load data. After checking SmartClient sources I've found protocol (which is not included in smartGWT) - "clientCustom". Using this protocol in data source allows to call custom server on data operations. It is done by overriding transformRequest method. When protocol is set to "clientCustom" - SmartClient after calling transformRequest method expects call of method processResponse after asynchronous call to server finishes.
    The only thing is missing - possibility to set "clientCustom" protocol in smartGWT.
    Here is what you can do:
    - download smartGWT sources
    - edit file main/src/com/smartgwt/client/types/DSProtocol.java - add these lines just after enumeration declaration :
    Code:
        /**
         * dsRequest.data should be poplulated by custom call to server in transformRequest method. transformRequest should issue async request
         * to server and call processResponse on completion with created DSResponse object. If call was successful status and data should be filled.
         * If call was unsuccessful only status should contain error code.
         */
        CLIENTCUSTOM("clientCustom"),
    - build your own smartGWT as it is described in http://code.google.com/p/smartgwt/wiki/BuildingFromSVN

    I really hope that smartGWT developers will include it in future releases.

    Please find attached implementation of GWT-RPC data source
    Working example with real GWT RPC services I will upload in next response - can not upload more than 5 files.

    Any comments are welcome.

    Aleksandras
    Attached Files
    Last edited by Isomorphic; 10 Apr 2012, 11:16.

    #2
    Working example of GWT-RPC data source.

    Hi again.
    As promised - uploading working example of GWT-RPC data source.

    files in client package:
    GwtRpcDataSource.java
    TestDataSource.java
    TestRecord.java
    TestServiceAsync.java
    TestService.java

    files in server package:
    TestServiceImpl.java

    Aleksandras
    Attached Files

    Comment


      #3
      This is a much clear implementation.


      thanks

      -jason

      Comment


        #4
        I agree this seems like a very clean approach... with the exception of having to alter the DSProtocol class.

        Isomorphic -- any chance this will be included in a future build?

        Comment


          #5
          You may not need to recompile/rebuild. use this hack:
          setAttribute("dataProtocol", "clientCustom", false);
          in DataSource.

          -jason

          Comment


            #6
            Sweet. Thanks.

            Comment


              #7
              Nice job Alius. Just FYI, those APIs (dataProtocol:"clientCustom" and the processResponse() method) were added to SmartClient precisely to enable GWT-RPC integration, but Alius was faster in creating a sample than we were :)

              Relative to the other recently posted approach for GWT-RPC integration, the approach Alius has demonstrated has the advantage that paging could be implemented if the GWT-RPC service supports it.

              One thing to correct - in TestDataSource.java it's assumed that a grid is initiating the requests. It would be more correct to use dsRequest.getOldValues() to get the originally submitted values (works with any component).

              Comment


                #8
                The "clientCustom" enum has been added to DSProtocol in SVN.

                Comment


                  #9
                  Updated example.

                  Hi Isomorphic,

                  Thank you for correction.
                  Problem is that there is no method getOldValues() in DSRequest class (in smartGWT).

                  For the time being I've written my own version of combining original values with changes.

                  Please find an updated version of TestDataSource.java

                  Hi Sanjiv,

                  I've written some code which can be added to DSRequest to address this issue.
                  If you will find it suitable - please add it to next release.
                  Code:
                      /**
                      * The original record without changes.
                      *
                      * @param oldValues Original record without changes. Default value is null
                      */
                      public void setOldValues(ListGridRecord oldValues) {
                          setAttribute("oldValues", oldValues);
                      }
                      /**
                       * The original record without changes.
                       *
                       *
                       * @return ListGridRecord
                       *
                       */
                      public ListGridRecord getOldValues()  {
                          JavaScriptObject oldValues = getAttributeAsJavaScriptObject ("oldValues");
                          return new ListGridRecord (oldValues);
                      }
                  
                      /**
                       * Returns record where changes are combined with original values.
                       *
                       *
                       * @return ListGridRecord
                       */
                      private ListGridRecord getEditedRecord () {
                          // Retrieving values before edit
                          JavaScriptObject oldValues = getAttributeAsJavaScriptObject ("oldValues");
                          // Creating new record for combining old values with changes
                          ListGridRecord newRecord = new ListGridRecord ();
                          // Copying properties from old record
                          JSOHelper.apply (oldValues, newRecord.getJsObj ());
                          // Retrieving changed values
                          JavaScriptObject data = getData ();
                          // Apply changes
                          JSOHelper.apply (data, newRecord.getJsObj ());
                          return newRecord;
                      }

                  Aleksandras
                  Attached Files

                  Comment


                    #10
                    Just reacting to
                    the approach Alius has demonstrated has the advantage that paging could be implemented
                    Any reason why getStartRow returns an int where getEndRow returns an Integer? Or this is just a glitch.

                    Emmanuel

                    Comment


                      #11
                      Where is the problem?

                      Hi, Thank you this template is great. But i am having problems with listgrid. Every thing is exactly as yours and here is my listgrid:
                      public void onModuleLoad() {

                      ListGridField rowNum = new ListGridField("id", "Id");
                      rowNum.setWidth(65);
                      rowNum.setCellFormatter(new CellFormatter() {
                      public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
                      return rowNum +"";
                      }
                      });

                      ListGridField mail = new ListGridField("email", 100);

                      final ListGrid listGrid = new ListGrid();
                      rootPanel.add(listGrid);
                      listGrid.setWidth100();
                      listGrid.setHeight100();
                      TestDataSource dataSource = new TestDataSource();
                      listGrid.setAutoFetchData(true);
                      listGrid.setDataSource(dataSource);

                      listGrid.setFields(rowNum, mail);
                      listGrid.draw();
                      }

                      I added args start and end row and sorting to the fletch method.
                      I use setAutoFletch(true) but it doesn't fletch any records. If i use listGrid getData() it loads me just the 'first page'. What am i missing? The example is exactly the same. My server side pagination is checked and working.

                      Comment


                        #12
                        Most probably it is not related to GWT-RPC but more to ListGrid.

                        What values do you get from request.getStartRow () and request.getEndRow () ?

                        Add this code to your application startup:
                        Code:
                        if (!GWT.isScript()) {
                            KeyIdentifier debugKey = new KeyIdentifier();
                            debugKey.setCtrlKey(true);
                            debugKey.setKeyName("D");
                        
                            Page.registerKey(debugKey, new KeyCallback() {
                                public void execute(String keyName) {
                                    SC.showConsole();
                                }
                            });
                        }
                        Add this code to start of your executeFetch implementation:
                        Code:
                        SC.logWarn ("Start row:" + Integer.toString (request.getStartRow ()));
                        SC.logWarn ("End row:" + request.getEndRow ().toString ());
                        SC.logWarn ("Sort by:" + request.getSortBy ());
                        Start your application in hosted mode and press Ctrl-D - this will open console where you will be able to track values.

                        Aleksandras.

                        Comment


                          #13
                          sry i cant do that, my project is not very trivial, it is struts and i inject gwt entry point in some jsp. I cant run it in hosted mode, and every time i deploy it :).
                          So what i can tell you is that the server side method for fletching is called only once, no matter of start and end row.

                          Comment


                            #14
                            This is my entry point:
                            public void onModuleLoad() {

                            ListGridField rowNum = new ListGridField("id", "Id");
                            rowNum.setWidth(65);
                            rowNum.setCellFormatter(new CellFormatter() {
                            public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
                            return rowNum +"";
                            }
                            });

                            ListGridField mail = new ListGridField("email", 100);

                            final ListGrid listGrid = new ListGrid();
                            rootPanel.add(listGrid);
                            listGrid.setWidth100();
                            listGrid.setHeight100();
                            TestDataSource dataSource = new TestDataSource();
                            listGrid.setAutoFetchData(true);
                            listGrid.setDataSource(dataSource);
                            listGrid.setFields(rowNum, mail);
                            listGrid.setDataPageSize(10);
                            listGrid.fetchData();
                            listGrid.draw();
                            }


                            And this is what i have changed in the datasource:

                            public TestDataSource() {
                            DataSourceField field;
                            field = new DataSourceIntegerField("id", "id");
                            field.setPrimaryKey(true);
                            field.setRequired(false);
                            addField(field);
                            field = new DataSourceTextField("mail", "mail");
                            field.setRequired(true);
                            addField(field);
                            }

                            @Override
                            protected void executeFetch(final String requestId, final DSRequest request, final DSResponse response) {
                            int startRow = request.getStartRow();
                            int endRow = request.getEndRow();
                            String sortBy = request.getSortBy();
                            TestServiceAsync service = ServiceUtils.getTestServiceAsync();
                            service.fetch(startRow, endRow, sortBy, new AsyncCallback<List<TestRecord>>() {
                            public void onFailure(Throwable caught) {
                            response.setStatus(RPCResponse.STATUS_FAILURE);
                            processResponse(requestId, response);
                            }

                            public void onSuccess(List<TestRecord> result) {
                            ListGridRecord[] list = new ListGridRecord[result.size()];
                            for (int i = 0; i < list.length; i++) {
                            ListGridRecord record = new ListGridRecord();
                            copyValues(result.get(i), record);
                            list[i] = record;
                            }
                            response.setData(list);
                            processResponse(requestId, response);
                            }
                            });
                            }

                            The rpc is working fine(i tested it before).

                            Comment


                              #15
                              Example of data source with paging.

                              Hi All,

                              As mnenchev requested I did some research about paging (BTW: I'm total newbie to SmartClient as well as to GWT - so everything to me is quite new).

                              Important thing to note: for paging to work correctly DSResponse.setTotalRows (Integer) has to be set. Here you have to provide total amount of matching records (not a size of returned list).

                              Please find an attached TestDataSource.java with paging example.

                              Aleksandras.
                              Attached Files

                              Comment

                              Working...
                              X