Announcement

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

    ListGrid update issue

    I created a new testcase, which shows a problem I got more clearly than in other posts of mine.

    I have the following code:

    TestModule
    Code:
    public class TestingModule implements EntryPoint {
    
    	public void onModuleLoad() {
    
    		final ListGrid countryList = new ListGrid();
    		countryList.setWidth(500);
    		countryList.setAlternateRecordStyles(true);
    		countryList.setDataSource(DataSource.get("worldDSExport"));
    		countryList.setAutoFetchData(true);
    
    		ListGridField pk = new ListGridField("pk");
    		pk.setHidden(true);
    		ListGridField countryName = new ListGridField("countryName", "Country");
    		ListGridField capital = new ListGridField("capital", "Capital");
    		ListGridField shouldShow = new ListGridField("shouldShow", "Should show");
    
    		countryList.setFields(pk, countryName, capital, shouldShow);
    		countryList.setAutoFitData(Autofit.VERTICAL);
    		countryList.setShowFilterEditor(true);
    		countryList.setAutoFitMaxRecords(10);
    
    		VLayout layout = new VLayout(15);
    		layout.setHeight(300);
    
    		HLayout formLayout = new HLayout(15);
    
    		IButton addBtn = new IButton("Press");
    		addBtn.addClickHandler(new ClickHandler() {
    
    			@Override
    			public void onClick(ClickEvent event) {
    				Record updateRecord = new Record();
    				updateRecord.setAttribute("pk", 1);
    				updateRecord.setAttribute("shouldShow", false);
    				DataSource.get("worldDSExport").updateData(updateRecord);
    
    			}
    		});
    		formLayout.addMember(addBtn);
    		layout.addMember(formLayout);
    
    		layout.addMember(countryList);
    
    		final ListGrid countryList2 = new ListGrid();
    		countryList2.setWidth(500);
    		countryList2.setAlternateRecordStyles(true);
    		countryList2.setDataSource(DataSource.get("worldDSExport2"));
    		countryList2.setAutoFetchData(false);
    
    		ListGridField pk2 = new ListGridField("pk");
    		pk2.setHidden(true);
    		ListGridField countryName2 = new ListGridField("countryName", "Country");
    		ListGridField capital2 = new ListGridField("capital", "Capital");
    		ListGridField shouldShow2 = new ListGridField("shouldShow", "Should show");
    
    		countryList2.setFields(pk2, countryName2, capital2, shouldShow2);
    		countryList2.setAutoFitData(Autofit.VERTICAL);
    		countryList2.setShowFilterEditor(true);
    		countryList2.setAutoFitMaxRecords(10);
    		
    		Criteria c2Criteria = new Criteria();
    		c2Criteria.addCriteria("filterContinent", "true");
    
    		countryList2.fetchData(c2Criteria);
    
    		layout.addMember(countryList2);
    
    		layout.draw();
    	}
    
    }
    worldDSExport:
    Code:
    <DataSource  
            ID="worldDSExport"  
            tableName="worldDS"  
            serverType="sql"  
        >  
            <fields>  
                <field name="pk"            type="integer"    hidden="true"            primaryKey="true" />  
                <field name="countryCode"   type="text"                   required="true"   />  
                <field name="countryName"   type="text"                 required="true"   />  
                <field name="capital"       type="text"                 />  
                <field name="government"    type="text"              length="500"      />  
                <field name="continent"     type="text"              >  
                </field>  
                <field name="independence"  type="date"                 />  
                <field name="area"          type="float"       />  
                <field name="population"    type="integer"             />  
                <field name="gdp"           type="float"                  />  
                <field name="member_g8"     type="boolean"                      />  
                
                <field name="shouldShow" type="boolean" sqlStorageStrategy="number" />
            </fields>  
            
            
            <operationBindings>
            
            <operationBinding operationType="update">
    			<serverObject className="zedes2.server.dmi.TestDMIHandler"
    				methodName="doUpdate" />
    		</operationBinding>
            
            </operationBindings>
        </DataSource>
    worldDSExport2:
    Code:
    <DataSource  
            ID="worldDSExport2"  
            tableName="worldDS"  
            serverType="sql"  
        >  
            <fields>  
                <field name="pk"            type="integer"    hidden="true"            primaryKey="true" />  
                <field name="countryCode"   type="text"                   required="true"   />  
                <field name="countryName"   type="text"                 required="true"   />  
                <field name="capital"       type="text"                 />  
                <field name="government"    type="text"              length="500"      />  
                <field name="continent"     type="text"              >  
                </field>  
                <field name="independence"  type="date"                 />  
                <field name="area"          type="float"       />  
                <field name="population"    type="integer"             />  
                <field name="gdp"           type="float"                  />  
                <field name="member_g8"     type="boolean"                      />  
                
                <field name="shouldShow" type="boolean" sqlStorageStrategy="number" />
            </fields>  
            
            
            <operationBindings>
    
    		<operationBinding operationType="fetch" >
    			<whereClause>
    			shouldShow=1
    
    			AND		
    				 
    			($defaultWhereClause)
    			
    			</whereClause>
    		</operationBinding>
    		
    		<operationBinding operationType="fetch" operationId="fetch_simple" >
    			
    			<whereClause>
    			 
    			($defaultWhereClause)
    			
    			</whereClause>
    		</operationBinding>
    		</operationBindings>
              
        </DataSource>
    TestDMIHandler
    Code:
    public class TestDMIHandler {
    
    	public DSResponse doUpdate(DSRequest dsRequest,
    			HttpServletRequest servletRequest) throws Exception {
    
    		DSResponse response = dsRequest.execute();
    
    		Integer pk = (Integer) response.getRecord().get("pk");
    		DSRequest newRequest = new DSRequest("worldDSExport2",
    				DataSource.OP_FETCH);
    		newRequest.setOperationId("fetch_simple");
    
    		newRequest.setCriteria("pk", pk);
    		newRequest.setRPCManager(dsRequest.getRPCManager());
    		DSResponse fetchResponse = newRequest.execute();
    		fetchResponse.setOperationType(DataSource.OP_UPDATE);
    
    		response.addRelatedUpdate(fetchResponse);
    
    		return response;
    
    	}
    
    }
    Note the
    Code:
    <field name="shouldShow" type="boolean" sqlStorageStrategy="number" />
    and
    Code:
    <operationBinding operationType="fetch" >
    			<whereClause>
    			shouldShow=1
    
    			AND		
    				 
    			($defaultWhereClause)
    			
    			</whereClause>
    		</operationBinding>
    in the DS.xml files.

    So the first listgrid shows all records, and the second one only the records with shouldShow=1.

    In my database I got two records:
    pk, countryCode, countryName, shouldShow
    1, de, Germany, True
    2, us, USA, True

    So both countries are shown in both grids, which is correct.

    Then I press the button. This button changes the "shouldShow" of record 1 to False.

    This is correct, the record is changed.
    But STILL BOTH records are in BOTH listgrids, although the second listGrid should only show records with shouldShow=True.

    Why is this happening?
    How could I update the second grid using updateData() and respecting its criteria ?

    I am using SmartGWT 4.0: v9.0p_2013-10-17/PowerEdition Deployment (built 2013-10-17)
    Last edited by edulid; 30 Oct 2013, 08:50.

    #2
    Hi,

    criteria of LG2 still is
    Code:
    c2Criteria.addCriteria("filterContinent", "true");
    .

    This is from your old example. Does changing it to shouldShow change the outcome?

    Best regards,
    Blama

    Comment


      #3
      Yes, it was a copy-paste error, but the corrected code delivers the same results:

      TestingModule
      Code:
      public class TestingModule implements EntryPoint {
      
      	public void onModuleLoad() {
      
      		final ListGrid countryList = new ListGrid();
      		countryList.setWidth(500);
      		countryList.setAlternateRecordStyles(true);
      		countryList.setDataSource(DataSource.get("worldDSExport"));
      		countryList.setAutoFetchData(true);
      
      		ListGridField pk = new ListGridField("pk");
      		pk.setHidden(true);
      		ListGridField countryName = new ListGridField("countryName", "Country");
      		ListGridField capital = new ListGridField("capital", "Capital");
      		ListGridField shouldShow = new ListGridField("shouldShow", "Should show");
      
      		countryList.setFields(pk, countryName, capital, shouldShow);
      		countryList.setAutoFitData(Autofit.VERTICAL);
      		countryList.setShowFilterEditor(true);
      		countryList.setAutoFitMaxRecords(10);
      
      		VLayout layout = new VLayout(15);
      		layout.setHeight(300);
      
      		HLayout formLayout = new HLayout(15);
      
      		IButton addBtn = new IButton("Press");
      		addBtn.addClickHandler(new ClickHandler() {
      
      			@Override
      			public void onClick(ClickEvent event) {
      				Record updateRecord = new Record();
      				updateRecord.setAttribute("pk", 1);
      				updateRecord.setAttribute("shouldShow", false);
      				DataSource.get("worldDSExport").updateData(updateRecord);
      
      			}
      		});
      		formLayout.addMember(addBtn);
      		layout.addMember(formLayout);
      
      		layout.addMember(countryList);
      
      		final ListGrid countryList2 = new ListGrid();
      		countryList2.setWidth(500);
      		countryList2.setAlternateRecordStyles(true);
      		countryList2.setDataSource(DataSource.get("worldDSExport2"));
      		countryList2.setAutoFetchData(false);
      
      		ListGridField pk2 = new ListGridField("pk");
      		pk2.setHidden(true);
      		ListGridField countryName2 = new ListGridField("countryName", "Country");
      		ListGridField capital2 = new ListGridField("capital", "Capital");
      		ListGridField shouldShow2 = new ListGridField("shouldShow", "Should show");
      
      		countryList2.setFields(pk2, countryName2, capital2, shouldShow2);
      		countryList2.setAutoFitData(Autofit.VERTICAL);
      		countryList2.setShowFilterEditor(true);
      		countryList2.setAutoFitMaxRecords(10);
      		
      
      		countryList2.fetchData();
      
      		layout.addMember(countryList2);
      
      		layout.draw();
      	}
      
      }

      Comment


        #4
        Hi,

        generally I'd expect it to work this way as the LG2 knows that it shouldn't display the returned row.

        But as I'm not executing your code and just reading it, I might be wrong. Nevertheless I noticed the following:
        Code:
        c2Criteria.addCriteria("filterContinent", [B]"[/B]true[B]"[/B]);
        The field is boolean and for addCriteria there is an overload addCriteria(java.lang.String field, java.lang.Boolean value).
        Does the 1st fetch for LG2 really include the WHERE clause? I don't know how the framework behaves in this case, if it converts "true"->true.

        Could you show the 4 SQL (LG1 fetch, LG2 fetch, LG1 Update, DS2 DMI fetch) from the server log?

        Best regards,
        Blama

        Comment


          #5
          Well, of course it does, because of your operationBinding. But perhaps the client side does not filter on the field as the data types don't match.

          Comment


            #6
            As I said , I already deleted the filterContinent criteria.

            This is the new code, but it has the same problem

            Code:
            public class TestingModule implements EntryPoint {
            
            	public void onModuleLoad() {
            
            		final ListGrid countryList = new ListGrid();
            		countryList.setWidth(500);
            		countryList.setAlternateRecordStyles(true);
            		countryList.setDataSource(DataSource.get("worldDSExport"));
            		countryList.setAutoFetchData(true);
            
            		ListGridField pk = new ListGridField("pk");
            		pk.setHidden(true);
            		ListGridField countryName = new ListGridField("countryName", "Country");
            		ListGridField capital = new ListGridField("capital", "Capital");
            		ListGridField shouldShow = new ListGridField("shouldShow", "Should show");
            
            		countryList.setFields(pk, countryName, capital, shouldShow);
            		countryList.setAutoFitData(Autofit.VERTICAL);
            		countryList.setShowFilterEditor(true);
            		countryList.setAutoFitMaxRecords(10);
            
            		VLayout layout = new VLayout(15);
            		layout.setHeight(300);
            
            		HLayout formLayout = new HLayout(15);
            
            		IButton addBtn = new IButton("Press");
            		addBtn.addClickHandler(new ClickHandler() {
            
            			@Override
            			public void onClick(ClickEvent event) {
            				Record updateRecord = new Record();
            				updateRecord.setAttribute("pk", 1);
            				updateRecord.setAttribute("shouldShow", false);
            				DataSource.get("worldDSExport").updateData(updateRecord);
            
            			}
            		});
            		formLayout.addMember(addBtn);
            		layout.addMember(formLayout);
            
            		layout.addMember(countryList);
            
            		final ListGrid countryList2 = new ListGrid();
            		countryList2.setWidth(500);
            		countryList2.setAlternateRecordStyles(true);
            		countryList2.setDataSource(DataSource.get("worldDSExport2"));
            		countryList2.setAutoFetchData(false);
            
            		ListGridField pk2 = new ListGridField("pk");
            		pk2.setHidden(true);
            		ListGridField countryName2 = new ListGridField("countryName", "Country");
            		ListGridField capital2 = new ListGridField("capital", "Capital");
            		ListGridField shouldShow2 = new ListGridField("shouldShow", "Should show");
            
            		countryList2.setFields(pk2, countryName2, capital2, shouldShow2);
            		countryList2.setAutoFitData(Autofit.VERTICAL);
            		countryList2.setShowFilterEditor(true);
            		countryList2.setAutoFitMaxRecords(10);
            		
            
            		countryList2.fetchData();
            
            		layout.addMember(countryList2);
            
            		layout.draw();
            	}
            
            }

            Comment


              #7
              Hi,

              sorry, I read the wrong answer. Without criteria on the client, this won't work.
              Does your use-case not allow
              Code:
              Criteria c2Criteria = new Criteria();
              c2Criteria.addCriteria([B]"shouldShow", true[/B]);
              countryList2.fetchData(c2Criteria);
              ?
              Your initial question was:
              How could I update the second grid using updateData() and respecting its criteria?
              But your ListGrid does not have criteria.

              Best regards,
              Blama

              Comment


                #8
                Of course it has:

                Code:
                <operationBinding operationType="fetch" >
                			<whereClause>
                			shouldShow=1
                
                			AND		
                				 
                			($defaultWhereClause)
                			
                			</whereClause>
                		</operationBinding>
                So the question could be formulated so:
                How could I update the second grid using updateData() and respecting the where clause?

                Comment


                  #9
                  The ListGrid is by design totally unaware of the customized SQL in your operationBinding. It will show or not show records based on the criteria you've applied client-side. See the ResultSet documentation for more information about automatic cache synchronization.

                  Comment


                    #10
                    Hi edulid,

                    compared to your example from yesterday (http://forums.smartclient.com/showthread.php?t=28427) you now have a handover point between the client and the server (that is the shouldShow-field in the DS, which was missing when you used "filterContinent", which wasn't a ds.xml field).

                    All automatic action in the DS.xml happens additionally to your hardcoded
                    Code:
                    <operationBinding operationType="fetch">
                      <whereClause>
                        shouldShow=1
                        AND		
                        ($defaultWhereClause)
                      </whereClause>
                    </operationBinding>
                    Please try setting the criteria as descibed in http://forums.smartclient.com/showpo...29&postcount=7.

                    What I'd expect as SQL for the 1st fetch in the server log is sth like
                    Code:
                    SELECT wordsDS.pk, wordsDS.countryCode, wordsDS.countryName, wordsDS.capital, wordsDS.government, wordsDS.continent, wordsDS.independence, wordsDS.area, wordsDS.population, wordsDS.gdp, wordsDS.member_g8, wordsDS.shouldShow FROM worldDS WHERE
                        shouldShow=1
                        AND		
                        ([B]shouldShow='1'[/B])
                    (exact like this with the linefeeds)

                    The 2nd fetch is then just like
                    Code:
                    SELECT wordsDS.pk, wordsDS.countryCode, wordsDS.countryName, wordsDS.capital, wordsDS.government, wordsDS.continent, wordsDS.independence, wordsDS.area, wordsDS.population, wordsDS.gdp, wordsDS.member_g8, wordsDS.shouldShow FROM worldDS WHERE ([B]pk='1'[/B])
                    (I'd leave out the <whereClause> in the OperationBinding, as it is just the standard with some linefeeds).

                    Please note that the client will NEVER see any SQL the server executes (for security reasons). So the client can't know about what you call criteria. The only way the client and the server talk is over HTTP. So what Firebug or the Firefox Webdeveloper Tools don't display isn't there.

                    Best regards,
                    Blama

                    Comment


                      #11
                      Please refer to http://forums.smartclient.com/showthread.php?t=28447 .

                      Thinking about the whole problem, and the approach I did here (addRelatedUpdate() ), I got the following idea:

                      After the addRelatedUpdate() returns to the listgrid, but before it applies to it, is it possible to catch it in a way similar as the DMIHandlers catch the dsRequest before it is executed?

                      So something like:

                      Code:
                      listGrid: 
                      
                      public void doUpdate(DSResponse response) throws Exception {
                      
                      		me.apply(response);
                      }

                      So we could check if the record applies to the actual <whereClause> by something similar like:

                      Code:
                      public void doUpdate(DSResponse response) throws Exception {
                      
                      Criteria c =  getActualCriteria();
                      fetchData(c, new callback() {
                                       if (response.getData().length==1) {
                      		this.apply(response);
                                       } else {
                                       if (recordVisible) {
                                           removeRecord();
                                       }
                      }
                      In this case, this.apply(response) only gets executed if it applies to the actual whereClause. If not,it is removed from the listGrid if visible.
                      Would this be doable?

                      I just had the idea to do it similar to the DMIHandlers.

                      Comment


                        #12
                        Hi edulid,

                        I know there is ListGrid.addDataArrivedHandler() (http://www.smartclient.com/smartgwte...ivedHandler%29) which might be the thing you're looking for in your recent question.
                        I never used it, so you'll have to try. If it is activated after the LG updates itself (resulting in a possible data arrives->LG update->your Handler call->You decide to remove again), you could also try the underlying ResultSet.addDataArrivedHandler()(http://www.smartclient.com/smartgwte...ivedHandler%29).

                        Again, I never did this so it might not work or even be the correct approach. I just know that the APIs are there and allowed to use.

                        What I think is that whatever custom logic you plan to implement there has to rely on the data from the DS (or do you have a different source of information that is not .ds.xml related?). If so, you can express your logic in (perhaps fairly complex) Criteria/AdvancedCriteria, which then is the way to go. As you didn't present your use case yet, I can only guess. Isomorphic can't do more, either.

                        Just as a note, if this is about security like "do not display fordidden rows": Thats no security at all. Just use Firebug or tap your HTTP traffic in any other way to see that.
                        The way to go here is to use declarative security, that is, assign roles based on your loginname during login, then act in the server side DMI according to the roles, disallowing access to certain operations or integrating additional criteria to CRUD-requests.

                        Best regards,
                        Blama

                        Comment


                          #13
                          A tremendous mountain is being made out of a molehill here, as they say.

                          The problem is just that the ListGrid doesn't know about criteria being applied on the server that would eliminate rows.

                          So just apply that criteria to the ListGrid, and it will eliminate the same rows.

                          Once you do this, any which way of updating the grid - addRelatedUpdates or updateCaches - will work.

                          Comment


                            #14
                            Originally posted by Isomorphic View Post

                            So just apply that criteria to the ListGrid, and it will eliminate the same rows.

                            Once you do this, any which way of updating the grid - addRelatedUpdates or updateCaches - will work.
                            Where exactly?

                            Please refer to http://forums.smartclient.com/showthread.php?t=28447. There I have an example testcase of the problem (in my second post). How to modify it, so that the addRelatedUpdates() work ?
                            Last edited by edulid; 31 Oct 2013, 06:29.

                            Comment


                              #15
                              You have client-side criteria that filter on category_text. You then change the category_id but evidently the data you send back from the server is not including updated values for category_text.

                              You've got some other more basic issues, like the criteria are targeting "categoryText" but the ListGridField is "category_text".

                              To sum up again: this is very simple:

                              1. make sure you supply criteria to the ListGrid which will eliminate rows you do not want to see.

                              2. make sure the server returns data which contains updated values for all the fields where you have client-side criteria

                              Comment

                              Working...
                              X