Announcement

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

    DataSource.setAutoCacheAllData Broken - Throws Exception

    Hello:

    If someone has any experience with client-only data source I would really appreciate some insight. From my experience with client-only data sources nothing works as advertised. For example here is a datasource that I have that talks to my back-end PHP scripts connected to MYSQL:

    Code:
    public class ContactsLimitedDataSource extends RestDataSource{
    
    	public ContactsLimitedDataSource(String id){
    		setID(id);
    		setShowPrompt(false);
    		setDataFormat(DSDataFormat.JSON);
    		setDataProtocol(DSProtocol.POSTPARAMS);
    		setDataURL(Utils.constants.url());
    		
    		HashMap<String, String> m = new HashMap<String, String>();
    		m.put("app", "contacts");
    		m.put("cmd", "getlist");
    		m.put("limit","yes");
    		setDefaultParams(m);
    				
    		setAddDataURL(Utils.constants.url());
    			
    		DataSourceIntegerField idField = new DataSourceIntegerField("id");	
    		idField.setPrimaryKey(true);
    		idField.setHidden(true);
    				
    		DataSourceTextField nameField = new DataSourceTextField("name");		
    		DataSourceIntegerField typeField = new DataSourceIntegerField("ttype");
    		
    		setFields(idField,nameField,typeField);		
    	}	
    
    }
    Simple enough. But when I set the setAutoCacheAllData to true I get the following error message:

    TMR1:WARN:ResultSet:isc_ResultSet_6 (created by: undefined):cacheAllData - cacheResultSet.dataArrived: startRow/endRow: 0/0
    com.smartgwt.client.core.JsObject$SGWT_WARN: 08:27:54.330:TMR1:WARN:ResultSet:isc_ResultSet_6 (created by: undefined):cacheAllData - cacheResultSet.dataArrived: startRow/endRow: 0/0
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannel.reactToMessages(BrowserChannel.java:1668)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:401)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:222)
    at java.lang.Thread.run(Thread.java:637)

    I've asked this question before and have never received an answer. If someone... SOMEONE has worked with client-side data sources and/or caching I would really appreciate it.

    Thanks.

    Chris

    #2
    Sigh.....

    Guess no-one has ever used the caching in DataSources.

    Comment


      #3
      Please read the FAQ. You'll have a much better chance of your posts being looked at if you include basics like the GWT and SmartGWT versions, make your test case standalone, and include all the relevant diagnostics, such as what you see in the RPC tab, and all messages in the Developer Console.

      Without these basics your post could be about a bug fixed months ago, or a usage error. So it gets ignored in favor of posts that are more likely to be about real issues.

      Comment


        #4
        To chodges:
        from your code I see that your data source is not clientOnly (setClientOnly(true) is not invoked).

        I have analogous code and the same exception if to set CacheAllData to true on the data source. Fetch request is not produced although setAutoFetchData(true) is invoked on the ListGrid. Call to setAutoCacheAllData(true) on the data source did not solve the problem. I’m using smartgwt ver. 2.2 with GWT ver. 1.7.1.

        Comment


          #5
          Hi romankol:

          I'm using SmartGWT 2.2 with GWT 2.0.3.

          Yes the problem I have is if I change the datasource to be client-only then I can't fetch the data from the remote server and have it cached.

          So ideally what I want to do is:

          1) Assuming my understanding of the method is correct (setAutoCacheAllData) set the setAutoCacheAllData to TRUE

          2) Perform a fetch that returns ALL of the data

          3) Have the datasource cache the result until I force a cache flush/re-read.

          4) Any UI components that use this data source would be retrieving the data from the cached result set

          But for the life of me I can not get this to work as advertised. Do you know if there is a memory limit to how much can be cached?

          Thanks.

          Chris
          Last edited by chodges; 12 Aug 2010, 07:40.

          Comment


            #6
            Hello, I am having the exact same problem. I am using SmartGWT 2.2.
            A simple example is basicly:
            Code:
            		RestDataSource ds = new RestDataSource();
            		ds.setDataFormat(DSDataFormat.JSON);
            		ds.setFields(
            			new DSIntegerField("ID").setPrimaryKey(),
            			new DSStringField("description")			
            		);
            		OperationBinding binding = new OperationBinding();
            		binding.setDataProtocol(DSProtocol.POSTMESSAGE);
            		binding.setOperationType(DSOperationType.FETCH);
            		ds.setOperationBindings(binding);
            		ds.setAutoCacheAllData(true);
            		ds.setFetchDataURL("/test");
            		
            		ds.fetchData();
            No JSON request is being send to the server, instead the following error is in the log:
            Code:
            com.smartgwt.client.core.JsObject$SGWT_WARN: 23:07:27.790:TMR3:WARN:ResultSet:isc_ResultSet_0 (created by: undefined):cacheAllData - cacheResultSet.dataArrived: startRow/endRow: 0/0
            N.B. without setAutoCacheAllData everything works as expected

            Comment


              #7
              Yeah I've never actually solved this but did an absolutely ugly and kludgey workaround.

              Look closely at the getInstance and getCachedInstance code..... Butt ugly but it works. I just wish we could some concrete clarity on how the cacheAllData parameter is supposed to work - but I never get a response.

              Code:
              package com.mybllc.myapp.client.ds;
              
              import java.util.HashMap;
              import com.mybllc.myapp.client.Utils;
              import com.smartgwt.client.data.Criteria;
              import com.smartgwt.client.data.DSCallback;
              import com.smartgwt.client.data.DSRequest;
              import com.smartgwt.client.data.DSResponse;
              import com.smartgwt.client.data.RestDataSource;
              import com.smartgwt.client.data.fields.DataSourceIntegerField;
              import com.smartgwt.client.data.fields.DataSourceTextField;
              import com.smartgwt.client.types.DSDataFormat;
              import com.smartgwt.client.types.DSProtocol;
              
              public class ListSource extends RestDataSource {
              
              	private static ListSource instance = null;
              	private static RestDataSource cachedInstance = null;
              	
              	public static ListSource getNewInstance(){
              		return new ListSource("DBList_DS_New");	
              	}
              	
              	public static ListSource getInstance(){
              		if(instance == null){								
              			instance = new ListSource("DBList_DS");																
              		}
              		
              		if(cachedInstance == null){
              			
              			instance.fetchData(new Criteria(), new DSCallback(){
              
              				@Override
              				public void execute(DSResponse response, Object rawData,
              						DSRequest request) {
              										
              					cachedInstance = new RestDataSource();	
              					cachedInstance.setInheritsFrom(instance);
              					cachedInstance.setClientOnly(true);
              					cachedInstance.setCacheData(response.getData());
              				}
              				
              			});
              			
              			
              		}
              		
              		return instance;
              	}
              	
              	public static RestDataSource getCachedInstance(){
              		return cachedInstance;
              	}
              	
              	public void reloadCache(){
              		
              		instance.fetchData(new Criteria(),new DSCallback(){
              			
              			@Override
              			public void execute(DSResponse response, Object rawData,
              					DSRequest request) {
              						
              				cachedInstance.setCacheData(response.getData());
              				
              			}
              			
              		});
              	}
              	
              	public ListSource(String id){
              		setID(id);		
              		setShowPrompt(false);
              		setDataFormat(DSDataFormat.JSON);
              		setDataProtocol(DSProtocol.POSTPARAMS);
              		setClientOnly(false);
              		setDataURL(Utils.constants.url());
              		
              		HashMap<String, String> m = new HashMap<String, String>();
              		m.put("app", "lists");
              		
              		setDefaultParams(m);
              		
              		setAddDataURL(Utils.constants.url());
              			
              		DataSourceIntegerField idField = new DataSourceIntegerField("id");
              		idField.setHidden(true);
              		idField.setPrimaryKey(true);
              				
              		DataSourceIntegerField attribField = new DataSourceIntegerField("attributeID");
              		attribField.setCanFilter(true);
              		attribField.setHidden(true);
              		
              		DataSourceTextField descriptionField = new DataSourceTextField("description","Description");
              		
              		DataSourceIntegerField parentField = new DataSourceIntegerField("parent");
              		parentField.setHidden(true);
              		
              		DataSourceIntegerField editField = new DataSourceIntegerField("editable");
              		editField.setHidden(true);
              		
              		setFields(idField,attribField,descriptionField,parentField,editField);
              	}
              }
              So basically the first time something uses this resource I make a call to the server for ALL of the data and create the cached instance of the DS.


              Originally posted by dencel
              Hello, I am having the exact same problem. I am using SmartGWT 2.2.
              A simple example is basicly:
              Code:
              		RestDataSource ds = new RestDataSource();
              		ds.setDataFormat(DSDataFormat.JSON);
              		ds.setFields(
              			new DSIntegerField("ID").setPrimaryKey(),
              			new DSStringField("description")			
              		);
              		OperationBinding binding = new OperationBinding();
              		binding.setDataProtocol(DSProtocol.POSTMESSAGE);
              		binding.setOperationType(DSOperationType.FETCH);
              		ds.setOperationBindings(binding);
              		ds.setAutoCacheAllData(true);
              		ds.setFetchDataURL("/test");
              		
              		ds.fetchData();
              No JSON request is being send to the server, instead the following error is in the log:
              Code:
              com.smartgwt.client.core.JsObject$SGWT_WARN: 23:07:27.790:TMR3:WARN:ResultSet:isc_ResultSet_0 (created by: undefined):cacheAllData - cacheResultSet.dataArrived: startRow/endRow: 0/0
              N.B. without setAutoCacheAllData everything works as expected

              Comment


                #8
                Have you tried setClientOnly(true) AND providing a DataURL? This results in a client-only datasource that fetches the initial data from your URL and then never contacts the server again.

                Comment


                  #9
                  Hello David,

                  This does not solve the problem, I require the behaviour to save newly added records through this datasource.

                  Comment


                    #10
                    Hello Chodges,

                    I am using your idea now, a little bit different approach listed below:
                    The cache is capable to listen to datachanges in the parent.

                    I have a cache capable datasource:
                    Code:
                     public class CacheableDSHack extends RestDataSource{
                            private CacheDatasource cache; 
                    
                    	public CacheDatasource getCache() {
                    		if(cache==null){
                    			cache = new CacheDatasource(this);
                    			cache.reload();
                    		}
                    		return cache;
                    	}
                    	@Override
                    	protected void transformResponse(DSResponse response, DSRequest request,
                    			Object data) {
                    		if(cache!=null){
                    			if(response.getStatus()==DSResponse.STATUS_SUCCESS){
                    				DSOperationType type = request.getOperationType();
                    				if(DSOperationType.ADD.equals(type)){
                    					Record[] recordsAdded = response.getData();
                    					for(Record recordAdd:recordsAdded){
                    						cache.addData(recordAdd);
                    					}
                    				}
                    				if(DSOperationType.UPDATE.equals(type)){
                    					Record[] recordsUpdated = response.getData();
                    					for(Record recordUpdate:recordsUpdated){
                    						cache.updateData(recordUpdate);
                    					}
                    				}
                    				if(DSOperationType.REMOVE.equals(type)){
                    					Record[] recordsUpdated = response.getData();
                    					for(Record recordUpdate:recordsUpdated){
                    						cache.removeData(recordUpdate);
                    					}
                    				}
                    
                    			}
                    		}
                    		super.transformResponse(response, request, data);
                    	}  
                     }
                    And the cache capable datasource uses a helper cache datasource:
                    Code:
                     public class CacheDatasource extends DataSource{
                    	
                    	private DataSource delegateDatasource;
                    	public CacheDatasource(DataSource delegate){
                    		super(); 
                    		this.delegateDatasource=delegate;
                    		setID(delegate.getID()+ "Cache");
                    		setInheritsFrom(delegate);
                    		setClientOnly(true);	
                    		setTestData(new Record[]{});
                    	}
                    	
                    	public void reload(){
                    		delegateDatasource.fetchData(
                    			null,new DSCallback() {
                    				@Override
                    				public void execute(DSResponse response, Object rawData, DSRequest request) {
                    					Record[] records = getCacheData();
                    					for(Record record:records){
                    						removeData(record);
                    					}
                    					records = response.getData();
                    					for(Record record:records){
                    						addData(record);
                    					}
                    				}
                    			}	
                    		);
                    	}
                    }
                    Notice: using the code in reload is really ugly, but I couldn't figure out an other way to revalidate bound gui components. setTestData does not invalidate the bound gui components.

                    Usage is as simple as:
                    Code:
                     CacheableDSHack ds = ...
                     listGrid.setOptionDataSource(ds.getCache()); <-- Use the cache instead of DS

                    Comment

                    Working...
                    X