You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "R. Goodwin (JIRA)" <ji...@apache.org> on 2008/08/10 12:09:47 UTC

[jira] Commented: (WICKET-1784) Break circular dependency between DataView and IDataProvider (size versus offset/count)

    [ https://issues.apache.org/jira/browse/WICKET-1784?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12621223#action_12621223 ] 

R. Goodwin commented on WICKET-1784:
------------------------------------

Bit of theory to support the ticket description:

The Transfer Object Pattern
-------------------------------------
Core J2EE Patterns, Alur et al, 2nd edition
Page 415

Forces:
  * You want to reduce remote requests across a network
Solution
  * Use a Transfer Object to carry multiple data elements across a tier

In terms of IDataProvider in the UI tier communicating with a session facade or business object on a remote server we want to make a single call that returns a single object containing both:
1. Subset of search results (paged)
2. The 'count' of total results

----

The example below illustrates the difficulty of implementing the Transfer Object pattern with Wicket.
The implementation of IDataProvider below does not work.


class SearchResultsDataProvider implements IDataProvider

   private SearchObject searchObject;
   
   public int size()  {

        // About to call search service, but where is offset and count, we need those now
        searchObject.setOffset( ?? );
        searchObject.setPerPage( ?? );

        int total = getSearchService().performSearch(searchObject).getTotalResults();
       return total;
   }

   public Iterator iterator(int offset, int count)  {

        // Okay to call search service here, but already (tried to) do this in size() method?
        searchObject.setOffset(offset);
        searchObject.setPerPage(count);

        List<T> results = lookupSearchService().performSearch(searchObject).getSearchResults();
        return results.iterator();
   }

}

class SearchObject  {

    // Class to represent the transfer object,
    // Is exchanged between UI tier running on one box and the data tier running on another box.

    // Search criteria
    private int offset;
    private int resultsPerPage;
    private Object otherSearchCriteria;

    // Search results
    private List<T> searchResults;
    private int totalResults;
}


@Stateless
class SearchService {

    // This runs on another server, possibly in another server cluster    
    
    // Takes a SearchObject containing search criteria, populates with results and total, 
    // then returns it to UI tier.
    
    public SearchObject performSearch(SearchObject searchObject)  {
        
        int offset = searchObject.getOffset();
        int perPage = searchObject.getResultsPerPage();

        // Could be a db search,
        // Or could be a Lucene index search etc ...
        List<T> results = doActualSearch(offset, perPage, otherSearchCriteria);
        searchObject.setResults(results);
      
        // Do another search to get total results,
        // or just read from Hits object if was a Lucene search
        int total = doCountQuery(otherSearchCriteria);
        searchObject.setTotalResults(total);

        return searchObject;
    }
}


> Break circular dependency between DataView and IDataProvider (size versus offset/count)
> ---------------------------------------------------------------------------------------
>
>                 Key: WICKET-1784
>                 URL: https://issues.apache.org/jira/browse/WICKET-1784
>             Project: Wicket
>          Issue Type: Improvement
>          Components: wicket
>    Affects Versions: 1.3.3
>         Environment: Wicket 1.3.3
>            Reporter: R. Goodwin
>
> In some environments searches are performed in 'single call' fashion,
> E.g. two queries performed by the data services tier before returning combined results to the UI tier:
> i. Query for paged search results
> ii. Query for a 'count' value representing total possible results
> The contract between DataView and IDataProvider does not support a 'single call' environment as the give/take relationship between these classes is biased towards DataView.
> DataView expects IDataProvider to provide it's size before providing IDataProvider with its offset and count.
> * DataView may have good reasons for needing size before it can provide offset/count.
> * But IDataProvider has equally good reasons for needing offset/count before it can provide size.
> The circular dependency:
> 1. DataView calls IDataProvider.size()
> 2. IDataProvider cannot return size as it cannot start a query until it receives offset/count from DataView
> 3. These it does not receive until DataView calls IDataProvider.iterator() later on
> Others who experienced this problem (with CODE examples):
> * http://www.nabble.com/IDataProvider-and-Hibernate-Search-td15546101.html
> * http://www.mail-archive.com/users@wicket.apache.org/msg14266.html
> ---
> The suggested solution of caching the combined search results and count value does not work if the search cannot begin until offset and count are available. And writing a custom DataView is not feasible either time wise as I understand that it cannot be done without needing to write a number of other classes too.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.