Quantcast
Channel: SmartClient Forums
Viewing all articles
Browse latest Browse all 4756

Guidance needed for my use case

$
0
0
I have a requirement for which we are not sure how to go about it. Please note that i have tried with different approaches ,however we need some guidance if we're heading the right path.

Following is the use case,

We have a ListGrid with Paging enabled. This grid is populated using an ‘AsynchronousDataSource’ (The ‘AsynchronousDatasource’ is a custom datasource which extends the RestDataSource). The ‘AsynchronousDatasource’ makes a REST web service call every 3 secs. This is achieved as follows:

The web service call is scheduled using the code snipped given below:
Code:

timer = new Timer() {
      @Override
      public void run() {
        try {
          refreshCache(response, dsRequest);
        } catch (final Exception e) {
          cancel();
        }
      }
    };
    timer.schedule(getWaitTimeOut() * 1000);

refreshCache() method (in the above given snippet) is as follows:
Code:

      final DSResponse carrier = new DSResponse();
      carrier.setInvalidateCache(true);
      carrier.setData(response.getData());
      request.setOperationType(DSOperationType.UPDATE);
      updateCaches(carrier, request);

The processing in the backend also happens asynchronously. Until the process Is completed successfully we are returning a wait message (here startRow 0 , endRow0,totalRows 0).
Once is process is completed, we are sending the actual data/response with proper startRow,endRow and totalRows.

This design works fine with first 75 records (the first page).
When user scroll past the 75Th it works as follows:
• The ListGrid fires a web service call with startRow 75 and endRow 150. Assuming the backend processing is still in progress, a wait message is returned.
• Once the response comes back to the front end (DataSource#transformResponse), we check if it a valid response or invalid response(invalid response is nothing but the wait message). If it is an invalid response, the second web service call is fired as follows:
o refreshCache() method (given above) is executed which in turn call the updateCaches() method. The updateCaches() method with invalidateCache flag set as true will trigger a server call.
o It is observed that this server call is fired with startRow=0 and endRow=75 (instead of startRow=75 and endRow=150)
o However from the server we are returning the response with startRow = 75 and endRow =150. But, in the front end the first 75 rows are cleared and the next 75 records (obtained as result of the WS call) are added at the position 75.
As per our analysis, we think that the updateCache along with invalidateCache flag set as true is responsible for wiping out the existing cache (the first 75 rows). Kindly suggest.


Following is the workaround that we tried:
Instead of using the custom ‘AsynchronousDataSource’, we used a plain DataSource class (which does not have any timer or schedule logic) which extends the RestDataSource. The schedule logic is moved to the panel where we are creating and using the ListGrid.

We are not invoking fetchData on grid as we do not want to give control on cache management to the grid, instead we want to take control of it.

A recursive method#makeServerCall is created to perform the following logic:
1.Call fetchData on this is datasource and on callback receive the response.
2.On callback we also check if the response is valid or not (based on the some properties sent by the server)
3.If it is not a valid response, we are schedule a timer for 3 seconds and then on trigger of this timer, call the recursive method #makeServerCall.

NOTE: Here when a dummy response has arrived result set of the list grid is clearing the current cache and integrating 0 rows.

The above three points will be executed recursively until a valid response is received.
Once we receive the valid response ,we are creating a new ResultSet and executing the following code,

Code:

ResultSet resultset = new ResultSet();
resultset.setDataSource(gridDS);
resultset.setFetchMode(FetchMode.PAGED);
resultset.setInitialLength(response.getTotalRows());
Record[] responseData = response.getData();
Record[] initialData = new Record[response.getEndRow()];
if(dataRecords == null){
dataRecords= new ArrayList<Record>();
}
if(dataRecords.size() > 0 && dataRecords.size() < request.getStartRow() ){
int a=0;
for(;a<dataRecords.size();a++){
initialData[a]=dataRecords.get(a);
}
for(;a<request.getStartRow();a++){
initialData[a]=null;
}
for(;a<request.getEndRow();a++){
initialData[a]=responseData[a-request.getStartRow()];
}
}else{
if(dataRecords.size() ==0){
for(int i=0;i<request.getEndRow();i++){
initialData[i]=responseData[i];
dataRecords.add(i, initialData[i]);
}
}else{
int a=0;
for(;a<dataRecords.size();a++){
initialData[a]=dataRecords.get(a);
}
for(;a<request.getEndRow();a++){
initialData[a]=responseData[a-request.getStartRow()];
dataRecords.add(a, initialData[a]);
}
}
}
resultset.setInitialData(initialData);
grid.setData(resultset);

The above code will be executed in the call back of the gridDS.fetchData after which we're creating an initial data .

What we are doing is we are capturing records fetched in a list called dataRecords.

Note that this is linked list which is only capture sequential records fetch 0-75,75-150 and not arbitrary.

• After WebService call with params 0-75 --> dataRecords is of size 75.--> initialData = response received from the server
• After 75-150-- dataRecords is of size 150 --> intialData = array of 0-75 records(dataRecords from above) + response received from server.
• For arbitary scroll down say 425-500
dataRecords(assuming 150 records are already there in the viewport) = first 150 records.
initialData = dataRecords( first 150 records)+ null values (to fill the gap) covering 150 to 425+ response from the server.

The above code is triggering following requests:
0-75 --> received dummy response
0-75 --> received dummy response ,invalidate the current cache, integrate 0 rows at 0 position
0-75 --> received valid response integrate to the cache , invalidate the current cache, integrate 75 rows at 0 position
75-150--> dummy response ,invalidate the current cache, integrate 0 rows at 0 position
75-150-->received valid response integrate to the cache , invalidate the current cache, integrate 150 rows at 0 position

The point of concern for this solution is that every dummy response invalidates the cache (wipes out the existing cache). So, for the solution to work as expected, we need the ListGrid cache to behave as follows:
0-75 --> received dummy response ,ignore this response
0-75 --> received dummy response ,ignore this response
0-75 --> received valid response integrate to the cache ,do not wipe out the existing cache just like normal listgrid . cache 75 rows at position 0
75-150--> dummy response ,do not invalidate the existing cache, just ignore
75-150-->received valid response, integrate 75 rows at 75th position in the cache. This way we can integrate chunks of 75 records at the right positions where the scroll is dragged to, just like any normal ListGrid.

Please guide us to find a better solution for this issue.

Viewing all articles
Browse latest Browse all 4756

Trending Articles