Announcement

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

    #16
    Hi again.

    Now everything is working in my test project as long as I use it within a listgrid.
    But when I am trying to update a record of my datasource "manually", I get an exception:
    Code:
     java.lang.NullPointerException: null 	at com.vantrix.oam.shared.datasource.genericGwtRpc.GenericGwtRpcDataSource.getEditedRecord(GenericGwtRpcDataSource.java:237)
     	at com.vantrix.oam.shared.datasource.genericGwtRpc.GenericGwtRpcDataSource.executeUpdate(GenericGwtRpcDataSource.java:185) 
    	at com.vantrix.oam.shared.datasource.genericGwtRpc.GwtRpcDataSource.transformRequest(GwtRpcDataSource.java:82)
    It is the "request.getOldValues()" that is null.

    What I am doing to get that is pretty simple. I get the selected record from my listgrid. Get an integer attribute. Increment it by 1 and then do an update with that modified record:
    Code:
    ListGridRecord lRec = clustersListGrid.getSelectedRecord();
    int lNbrNodes = lRec.getAttributeAsInt( ClusterDs.NBR_NODES );
    lNbrNodes++;
    lRec.setAttribute( ClusterDs.NBR_NODES, lNbrNodes );
    ClusterDs.getInstance().updateData( lRec );
    Any idea?
    Thanks

    Comment


      #17
      Originally posted by tleveque
      Hi again.

      Now everything is working in my test project as long as I use it within a listgrid.
      But when I am trying to update a record of my datasource "manually", I get an exception:
      Code:
       java.lang.NullPointerException: null 	at com.vantrix.oam.shared.datasource.genericGwtRpc.GenericGwtRpcDataSource.getEditedRecord(GenericGwtRpcDataSource.java:237)
       	at com.vantrix.oam.shared.datasource.genericGwtRpc.GenericGwtRpcDataSource.executeUpdate(GenericGwtRpcDataSource.java:185) 
      	at com.vantrix.oam.shared.datasource.genericGwtRpc.GwtRpcDataSource.transformRequest(GwtRpcDataSource.java:82)
      It is the "request.getOldValues()" that is null.

      What I am doing to get that is pretty simple. I get the selected record from my listgrid. Get an integer attribute. Increment it by 1 and then do an update with that modified record:
      Code:
      ListGridRecord lRec = clustersListGrid.getSelectedRecord();
      int lNbrNodes = lRec.getAttributeAsInt( ClusterDs.NBR_NODES );
      lNbrNodes++;
      lRec.setAttribute( ClusterDs.NBR_NODES, lNbrNodes );
      ClusterDs.getInstance().updateData( lRec );
      Any idea?
      Thanks
      I am just finding many other problems.... It seems that this implementation is only supporting basic add/update/remove operation within a list widget.

      As soon as I want to do anything else, many problems occur.
      -Adding, editing or deleting a record from custom java code
      -Drag and drop between 2 list
      -Fetch related datasource. Criterias are ignored

      I wish I had time to dig into the code and implement that, but I don't. I will have to use another method to reach my server-side data.
      Maybe I will just let everything on client side and wait for a save action from the user to update the data on the server side.....

      Comment


        #18
        Hi tleveque

        Thanks for noticing the typo, I corrected it in the posted example.

        As for the other problems (NPE's), I don't quite understand why you update you data "manually", using

        Code:
        ClusterDs.getInstance().updateData( lRec );
        As I understand it, the SmartGWT ListGrid will do this automatically in the background, as shown in the Edit Row sample (http://www.smartclient.com/smartgwt/...id_editing_row):

        Code:
        final ListGrid countryGrid = new ListGrid();  
        countryGrid.setDataSource(CountryXmlDS.getInstance());  
          
        // create fields ommitted...
        countryGrid.setFields(countryCodeField, nameField,continentField, memberG8Field, populationField, independenceField);  
          
        countryGrid.setAutoFetchData(true);  
        countryGrid.setCanEdit(true);  
        countryGrid.setEditEvent(ListGridEditEvent.CLICK);  
          
        countryGrid.draw();
        As far as I know, adding "setCanEdit(true)" and "setEditEvent()" should be enough to make your ListGrid editable. ...The update-calls to the DataSource will occure asynchronously in the background. I don't know if a DataSource is to be "manually" updated.

        Or I am missing something? :-)

        Thanks again for testing & improving GenericGwtRpcDataSource

        cheers
        marbot

        Comment


          #19
          New version 1.1 now supports server-side paging and sorting

          Hi everyone

          It's been a rainy weekend in Switzerland, so I've had time to add some features to GenericGwtRpcDataSource.

          Seeing that some people have troubles getting server-side paging and sorting to work with a GWT RPC DataSource, and responding to the suggestion of Andre, I decided to add this functionality to the GenericGwtRpcDataSource. Furthermore, I've done some work trying to resolve the problems described by tleveque. I didn't add the error-handling code of fatzopilot, because I wanted the code to keep focussed - feel free to add it if you need it, it's a good suggestion.

          So here's how to use the new Version 1.1:

          - as with the old version, start by implementing a serializable Data Transfer Object (most likely a POJO):

          Code:
          package mytest.shared;
          import com.google.gwt.user.client.rpc.IsSerializable;
          
          public class YourDataObject implements IsSerializable {
          
          	private Integer id;
          	private String name;
          	private String location;
          
          	public Integer getId() { return id; }
          	public void setId(Integer id) { this.id = id;	}
          
          	public String getName() { return name; }
          	public void setName(String name) { this.name = name;}
          
          	public String getLocation() { return location;}
          	public void setLocation(String location) {this.location = location;}
          }
          - next, create a gwt rcp service, by extending GenericGwtRpcService. Set its @RemoteServiceRelativePath annotation:

          Code:
          package mytest.client;
          
          import mytest.client.lib.GenericGwtRpcService;
          import mytest.shared.YourDataObject;
          import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
          
          @RemoteServiceRelativePath("yourservice")
          public interface YourService extends GenericGwtRpcService<YourDataObject>{ }
          - create the asynchronous counterpart of the service by extending GenericGwtRpcServiceAsync:

          Code:
          package mytest.client;
          
          import mytest.client.lib.GenericGwtRpcServiceAsync;
          import mytest.shared.YourDataObject;
          
          public interface YourServiceAsync extends GenericGwtRpcServiceAsync<YourDataObject> {}
          - this part will take the most work: create your GwtRpcDataSource by extending GenericGwtRpcDataSource<D, T, SA>:

          Code:
          package mytest.client;
          
          import java.util.ArrayList;
          import java.util.List;
          
          import mytest.client.lib.GenericGwtRpcDataSource;
          import mytest.shared.YourDataObject;
          
          import com.google.gwt.core.client.GWT;
          import com.smartgwt.client.data.DataSourceField;
          import com.smartgwt.client.data.fields.DataSourceIntegerField;
          import com.smartgwt.client.data.fields.DataSourceTextField;
          import com.smartgwt.client.widgets.grid.ListGridRecord;
          
          public class YourDataSource
          		extends
          		GenericGwtRpcDataSource<YourDataObject, ListGridRecord, YourServiceAsync> {
          
          	private static YourDataSource instance;
          
          	// forces to use the singleton through getInstance();
          	private YourDataSource() {
          	};
          
          	public static YourDataSource getInstance() {
          		if (instance == null) {
          			instance = new YourDataSource();
          		}
          		return (instance);
          	}
          
          	@Override
          	public void copyValues(ListGridRecord from, YourDataObject to) {
          		to.setId(from.getAttributeAsInt("id"));
          		to.setName(from.getAttribute("name"));
          		to.setLocation(from.getAttribute("location"));
          	}
          
          	@Override
          	public void copyValues(YourDataObject from, ListGridRecord to) {
          		to.setAttribute("id", from.getId());
          		to.setAttribute("name", from.getName());
          		to.setAttribute("location", from.getLocation());
          	}
          
          	@Override
          	public List<DataSourceField> getDataSourceFields() {
          
          		List<DataSourceField> fields = new ArrayList<DataSourceField>();
          
          		DataSourceIntegerField idField = new DataSourceIntegerField("id");
          		idField.setHidden(true);
          		idField.setPrimaryKey(true);
          		fields.add(idField);
          
          		DataSourceTextField nameField = new DataSourceTextField("name", "Name");
          		nameField.setRequired(true);
          		fields.add(nameField);
          
          		DataSourceTextField locationField = new DataSourceTextField("location", "Location");
          		locationField.setRequired(true);
          		fields.add(locationField);
          
          		return fields;
          	}
          
          	@Override
          	public YourDataObject getNewDataObjectInstance() {
          		return new YourDataObject();
          	}
          
          	@Override
          	public ListGridRecord getNewRecordInstance() {
          		return new ListGridRecord();
          	}
          
          	@Override
          	public YourServiceAsync getServiceAsync() {
          		return GWT.create(YourService.class);
          	}
          }
          - Finally, code your server-side Service implementation. If you want to use server-side paging and sorting, the fetch()-method implementation will have to return a GenericGwtRpcList instead of a regular List implementation, as shown in the example below. Note that you have to set the totalRows (using GenericGwtRpcList.setTotalRows()), to tell the client how many rows to except:

          Code:
          package mytest.server;
          
          @SuppressWarnings("serial")
          public class YourServiceImpl extends RemoteServiceServlet implements
          		YourService {
          
          	@Override
          	public YourDataObject add(YourDataObject data) {
          		// your code here
                  }
          
          
          	@Override
          	public void remove(YourDataObject data) {
          		// your code here
          	}
          
          	@Override
          	public YourDataObject update(YourDataObject data) {
          		// your code here
          	}
          
          	@Override
          	public List<YourDataObject> fetch(Integer startRow, Integer endRow,
          			final String sortBy) {
          		
          		GenericGwtRpcList<YourDataObject> outList = new GenericGwtRpcList<YourDataObject>();
              
                  // to implement sorting, use the transfered sortBy String. It contains the field name to sort, 
                  // preceded by a '-' if the sorting is to be descending.
                  
                  // if startRow and endRow are not null, the client wishes paged fetching.
                  
                  // important to allow proper paging, we set the total counts of rows.
                  outList.setTotalRows(items.size());
          		
          		return outList; 
          		
          	}
          
          }
          ...and you're done implementing a GWT RPC DataSource! :-)

          In order to use server-side paging and sorting, you'll have to tell your ListGrid to do so:

          Code:
          final ListGrid yourGrid = new ListGrid();
          yourGrid.setDataSource(YourDataSource.getInstance());
          
          ListGridField nameField = new ListGridField("name", "Name");
          ListGridField locationField = new ListGridField("location", "Location");
          yourGrid.setFields(nameField, locationField);
          
          yourGrid.setAutoFetchData(true);
          yourGrid.setDataFetchMode(FetchMode.PAGED); // sets server-side paging and sorting
          yourGrid.setShowAllRecords(false);
          yourGrid.setDataPageSize(20); // sets the page size (default is 75)
          I've attached the new source-files. Note that you'll have to put GenericGwtRpcList in your shared package, as it is also needed on the server.

          Enjoy! :-) ...any improvement suggestion is welcome!

          marbot
          Attached Files

          Comment


            #20
            GenericGwtRpcDataSource: ListGrid example with server-side paging and sorting

            And here's a .zip containing the whole working test project (you'll need to compile it once to get your /sc -folder with the skins and icons):

            http://www.marbot.org/ListGridTest.zip
            (btw, why can't we upload .zip's?)

            It shows a ListGrid making server-side paging and sorting using the GenericGwtRpcDataSource showed below, as well as adding and removing rows. Double-click a row to edit it. Example sources are attached.

            cheers
            marbot
            Attached Files
            Last edited by marbot; 16 May 2010, 02:56.

            Comment


              #21
              Filtering in ListGrid not working

              Hi Marbot, i'd like you help me with some stuff.

              I use GWT2.0.3/SmartGWT2.1.1/Netbeans6.8/Firefox 3.6.3..

              I'm a very newbie in GWT stuff, coming to SmartGWT from Ext-GWT+ GWT-RPC +GILEAD(with not much of experience, but enough to get a working app), so I've used only GWT-RPC to work with server connections in GWT's world. I haven't understood at all anything about working with DataSources using SmartClient Java Server Framework or something like that, and googling I fell here and saw'u speaking my same language about GWT-RPC.
              I've got your example about GenericGwtRpc and done my own working example using that successfully, but I've a problem:
              Using ListGrid filters doesn't work at all. Using live filters the rpc calls are done, but nothing about filtering, just got the same records that previously had in the ListGrid.
              In my impl I used hibernate to get mysql-server connected and I've searched for errors into my code and nothing.
              So I don't know where exactly the problem is.

              Look, changing grid's properties and refreshing the page while in the dev mode, It worked once, but after changing properties again didn't work and couldn't get it working anymore( I'm refering to filtering).

              So, could you tell me about any grid property can cause that?

              Here my grid's code:
              Code:
              ListGrid grid = new ListGrid();
                      grid.setWidth(550);
                      grid.setHeight(300);
                      grid.setCellHeight(22);
                      grid.setDataSource(PersonDataSource.getInstance());
              
                      ListGridField idField = new ListGridField("id", "ID");
                      idField.setCanFilter(Boolean.FALSE);
                      ListGridField nombreField = new ListGridField("nombre", "Nombre");
                      ListGridField ciField = new ListGridField("ci", "C.Identidad");
              
                      ListGridField fotoField = new ListGridField("foto", "Foto");
                      fotoField.setCanFilter(Boolean.FALSE);
                      ListGridField cargoField = new ListGridField("cargo", "Cargo");
                      cargoField.setCanFilter(Boolean.FALSE);
                      ListGridField sexoField = new ListGridField("sexo", "Sexo");
                      sexoField.setCanFilter(Boolean.FALSE);
                      ListGridField areaField = new ListGridField("area", "Area");
                      areaField.setCanFilter(Boolean.FALSE);
                      ListGridField ape1Field = new ListGridField("ape1", "Ape1");
                      ape1Field.setCanFilter(Boolean.FALSE);
                      ListGridField ape2Field = new ListGridField("ape2", "Ape2");
                      ape2Field.setCanFilter(Boolean.FALSE);
              
                      grid.setFields(idField, 
                                     ciField,
                                     nombreField,
                                     ape1Field,
                                     ape2Field,
                                     sexoField,
                                     areaField,
                                     cargoField,
                                     fotoField);
              
                      grid.setAutoFetchData(true);
                      grid.setDataFetchMode(FetchMode.PAGED);
                      grid.setShowAllRecords(false);
                      grid.setDataPageSize(20);
                      grid.setCanEdit(true);
                      grid.setEditEvent(ListGridEditEvent.DOUBLECLICK);
              
                      grid.setShowFilterEditor(true);
                      grid.setFilterOnKeypress(true);
              
                      Canvas cv = new Canvas();
                      cv.addChild(grid);
                      cv.draw();
              Remember I'm a newbie in SmartGWT, so I't could be a very stupid question, and my first time posting here( second in my life).

              Sorry about my english.
              Please help me if you can.
              Thanks

              Dariel

              Comment


                #22
                Hi Dariel

                First of all, congratulations on the second posting of your life!

                I briefly looked into the problem, and the answer seems to be quite simple: GenericGwtRpcDataSource does not pass the filter criteria to the server... yet.

                I've enhanced the code to enable filtering. The only thing you'll have to do is replace your GenericGwtRpcDataSource, GenericGwtRpcService and GenericGwtRpcServiceAsync with the new ones (attached), and change your service implementation on the server: the fetch()-method signature now should define as:

                Code:
                @Override
                public List<YourDataObject> fetch(Integer startRow, Integer endRow, final String sortBy, Map<String, String> filterCriterias) {		
                //...
                }
                For every column a user filters, an entry is created in the filterCriterias Map. This Map holds the field name in the key-String, and the value entered by the user in the value-String. It's up to you to filter your results through Hibernate on the server-side.

                Hope this helps. I haven't tested this thoroughly, so please post any troubles you might have. If this works well, I'll update the original source.

                Thanks for testing GenericGwtRpcDataSource! :-)

                cheers
                marbot
                Attached Files

                Comment


                  #23
                  Hi marbot!
                  Great work with your datasource.
                  I am new to smartgwt and I am currently trying to find out if the following would be possible using the generic datasource:

                  I'am considering to use smartgwt for a an application where I have many Tabs with lot (like 30) or so ListGrids which need to be populated on the users demand with data coming from serverside. Every list displays like 10 to 100 rows which all have the same columns (id, value pairs). Depending on the listgrid that should be populated, the server needs to serve different values.
                  Would such a scenario be possible with a single generic datasource (instead of implementing 30 of them) only using some filtering? Can I send some identifier of the ListGrid that the ds is bound to, so that my fetch() implementation on the server knows which values to choose?

                  I would greatly appreciate any suggestion.

                  regards,

                  mgtop

                  Comment


                    #24
                    About filtering

                    Hi again Marbot, and thanks for your quick reply, that's the part I love about the open source programming!!
                    You're welcome, about my posting numbers, I mean.

                    Well, I just read your post, and haven't already tested your new classes, but let me tell you something first:
                    Last night I tried another option with the same way my app was built, but instead of using records from a database getting them with hibernate, I made an ArrayList of Persons and implemented CRUD on it, and the filtering worked like a charm! (I know the original implementation class uses a List too, but tried constructing one myself for being sure about if was an error in my own code).

                    Remember something, with the original classes I don't use any set of elements to filter by, so what I still don't get is why filtering works using an arraylist of elements, and not with the list I get from the query with hibernate if, after all, both of them are Lists.
                    Thanks, I'll test your code and let you know later.
                    Dariel

                    Comment


                      #25
                      Hi dariel

                      Well, as far as I know, there's client-side filtering and server-side filtering. Configuring your ListGrid with:

                      Code:
                      yourGrid.setAutoFetchData(true);
                      yourGrid.setDataFetchMode(FetchMode.PAGED); // sets server-side paging and sorting
                      yourGrid.setShowAllRecords(false);
                      will allow server-side paging, sorting and filtering. Maybe you've not set your ListGrid for server-side filtering in your ArrayList-Example? ... Have you tried setting a breakpoint in the server service implementation, to see if the filtering criteria are passed to the server?

                      cheers
                      marbot

                      Comment


                        #26
                        Originally posted by mgtop
                        Would such a scenario be possible with a single generic datasource (instead of implementing 30 of them) only using some filtering? Can I send some identifier of the ListGrid that the ds is bound to, so that my fetch() implementation on the server knows which values to choose?
                        Hi mgtop

                        Well, I think this should be possible, using the filtering-enhanced GenericGwtRpcDataSource I posted for Dariel, and the following settings for the ListGrid:

                        Code:
                        ListGrid grid = new ListGrid();
                        Criteria criteria = new Criteria();
                        criteria.addCriteria("yourKey", "yourFilterValue");
                        grid.setCriteria(criteria);
                        You then should get a Map with the defined filter criteria as filterCriterias on the server-side, and implement your service accordingly:

                        Code:
                        @Override
                        public List<YourDataObject> fetch(Integer startRow, Integer endRow, final String sortBy, Map<String, String> filterCriterias) {		
                        //...
                        }
                        I haven't tested this, though. I only looked at the methods defined on ListGrid.

                        cheers
                        marbot

                        Comment


                          #27
                          Hi Marbot, I've just tested your code but partially, and works perfectly for server-side filtering, but I just could test it until where I decide what to do with the filterCriteria Map, ex:

                          Code:
                          public List<Person> fetch(Integer startRow, Integer endRow, String sortBy, Map<String, String> filterCriteria) {
                                  
                                 //fetch(startRow, endRow, sortBy) is your old fetch()-method, I still use it if not filtering
                          List<Person> list = fetch(startRow, endRow, sortBy);
                          
                                 //not sure about when filtering isn't activated, but works like this..
                                  if(filterCriteria == null || filterCriteria.isEmpty()) 
                                      return list;
                          
                                //it's an example for a list already filtered, may be the same above list, which contains all of my Persons Object..
                                //Still I don't filter in data base, that's why I get all records and process them already in memory..
                                ArrayList<Person> filteredList = new ArrayList<Person>();
                                filteredList.add(new Person(400, "555555", "Tareko", "ape1", "ape2", "m"));
                          
                                return filteredList;
                              }
                          This works right, returning everything if not filtering, and if filtered is activated returns the filteredList, what partially ensures your code works, but my point is I don't know how to use the "Map<String, String>filterCritera" param, at the time to select an Object( Person in my case), that matches the given criteria(s).
                          For example, if a Map item has "name,Tareko", is filtering when the name attribute contains "Tareko" so, how do I convert from "name" to person.getName() ? (person is a Person class instance) ..
                          Is this by reflection or what.??

                          Thanks Marbot.
                          Dariel

                          Comment


                            #28
                            Hi Dariel

                            Glad to hear that passing the parameters for the filtering works.

                            Well, you really should do the filtering on the database, and not try to filter the List in Java. This would result in poor performance and obsolete, error prone code... I believe you use Hibernate, so simply using the Hibernate Query Language or a Hibernate Filter is the correct solution here.

                            If you really want to filter the List in Java, I suppose you could loop through the unfiltered List and pick the entries you need, something like that:

                            Code:
                                    ArrayList<Person> filtered = new ArrayList<Person>();
                                    for (String key : filterCriterias.keySet()) {
                            			if ("name".equals(key)) {
                            				for (Person person : list) {
                            					if (person.getName().equals(filterCriterias.get(key))) {
                            						filtered.add(person);
                            					}
                            				}
                            			}
                            		}
                            This is completely untested and dreadful code, though...

                            One last thing: your question does not concern GenericGwtRpcDataSource, but is a simple Java programming question. Please avoid to ask such things in this thread, so it keeps short and focussed. Thanks.

                            cheers
                            marbot

                            Comment


                              #29
                              Hi marbot, thanks again.

                              Sorry about my posting out of the actual subject.

                              Well I'll test this way you gave me everyway, but I'm going to try to get these operations done in the database like you said, it's just that I had to check for somethings that I'm not able to do into the db(because of not enough db knowledge), that's why I get all of my records and later process them but, I'll get your advise.

                              Thanks again, marbot.

                              Dariel

                              Comment


                                #30
                                Thank you, marbot.

                                Your sample project helps me a lot.
                                I am search the sample code for three days.
                                You save me.

                                Thanks again.

                                Comment

                                Working...
                                X