[aerogear-dev] Client Paging Strawman

Kris Borchers kris at redhat.com
Tue Jan 15 09:12:04 EST 2013


On Jan 15, 2013, at 8:09 AM, Matthias Wessendorf <matzew at apache.org> wrote:

> On Tue, Jan 15, 2013 at 3:01 PM, Kris Borchers <kris at redhat.com> wrote:
>> 
>> On Jan 15, 2013, at 7:57 AM, Matthias Wessendorf <matzew at apache.org> wrote:
>> 
>>> On Tue, Jan 15, 2013 at 2:52 PM, Kris Borchers <kris at redhat.com> wrote:
>>>> Though this discussion has been great, I feel like it has headed "down a
>>>> path I (JS) cannot follow". Luke, that Star Wars quote was for you. ;)
>>>> 
>>>> When doing a read() (or next() or prev()…), I would expect the exact same
>>>> type of response, which is a list of objects. This is easily accomplished in
>>>> JS, we overload the read method to accept a parameter that tells it to use
>>>> paging and which page to grab and then return only the results that were
>>>> requested. This can then be made easier with helper functions like next(),
>>>> prev(), etc. that use the overloaded read() method so the dev doesn't even
>>>> need to know it exists of they don't want. This would be accomplished by
>>>> maintaining the current paging state on the pipe so a call to next() just
>>>> knows what to do. Also, via a couple of setter methods on the pipe instance,
>>>> we can adjust the offset and limit at any time.
>>>> 
>>>> I honestly feel like this is going to be the best developer experience on
>>>> JS, I just don't know how or if it even makes sense for iOS and Java to try
>>>> to get there but for JS I just can't get myself onboard with this idea of
>>>> returning an object that contains next(), prev(), etc. methods instead of
>>>> just the data that the user wants.
>>> 
>>> 
>>> on next() a callback would be invoked, which delivers:
>>> - the payload (like it does on read)
>>> - the "paged result set"
>>> 
>>> does that make sense ?
>> 
>> Not really. All I would want returned from next() is the array of objects (payload) just as read() works.
> 
> yes
> 
>> If that changes, then I have to interact with next() differently than I would read() and that doesn't seem like a good developer experience because
> 
> 
> how would you change the paging params? Like from "3rd next invoke, I
> want to show 20, instead of 5". Hrm...Perhaps that would mean a new
> "pipe" needs to be set up ?

Nope, as I've said before, there would be a setter for offset and limit so that the initial values that were used when the pipe was set up can be modified at any time.
> 
> -M
> 
>> I can just dump the result of read() into my templates for example, but I have to hang on to and further process the result from next() in your suggestion. I'm not a fan.
>>> 
>>> 
>>> 
>>>> 
>>>> On Jan 15, 2013, at 7:45 AM, Sebastien Blanc <scm.blanc at gmail.com> wrote:
>>>> 
>>>> Just to summarize what have until now :
>>>> 
>>>> 1. Kris's proposition: https://gist.github.com/4531575
>>>> 
>>>> 2. Summers's proposition: https://gist.github.com/4532661
>>>> 
>>>> 3. qmx's propositon: https://gist.github.com/4538709
>>>> 
>>>> 4. Sebi's propositionhttps://gist.github.com/4538725
>>>> 
>>>> 
>>>> 
>>>> 
>>>> On Tue, Jan 15, 2013 at 2:32 PM, Matthias Wessendorf <matzew at apache.org>
>>>> wrote:
>>>>> 
>>>>> On Tue, Jan 15, 2013 at 2:25 PM, Matthias Wessendorf <matzew at apache.org>
>>>>> wrote:
>>>>>> I was wondering, if the result should be received on every rquest,
>>>>> 
>>>>> 
>>>>> ideally on the callback..., to not block (at least in iOS land, I
>>>>> would pass that "result set" on to the "success" block)
>>>>> 
>>>>> -M
>>>>> 
>>>>>> 
>>>>>> thx
>>>>>> 
>>>>>> On Tue, Jan 15, 2013 at 2:01 PM, Sebastien Blanc <scm.blanc at gmail.com>
>>>>>> wrote:
>>>>>>> In the same spirit (inspired from
>>>>>>> 
>>>>>>> http://stackoverflow.com/questions/5412059/how-to-implement-general-pagination)
>>>>>>> :
>>>>>>> 
>>>>>>> 
>>>>>>> public interface PagedResult<T> {
>>>>>>> 
>>>>>>>   PagedResult<T> next();
>>>>>>> 
>>>>>>>   PagedResult<T> prev();
>>>>>>> 
>>>>>>>   PagedResult<T> withOffset(int offset);
>>>>>>> 
>>>>>>>   PagedResult<T> withLimit(int limit);
>>>>>>> 
>>>>>>>   List<T> result();
>>>>>>> 
>>>>>>> }
>>>>>>> 
>>>>>>> 
>>>>>>> On Tue, Jan 15, 2013 at 1:38 PM, Douglas Campos <qmx at qmx.me> wrote:
>>>>>>>> 
>>>>>>>> I'm not a fan of those PageContext objects (remembers me of some
>>>>>>>> wild-ass
>>>>>>>> ThreadLocals leaking all over)
>>>>>>>> 
>>>>>>>> My proposal for the paging aware APIs would be something like this:
>>>>>>>> 
>>>>>>>> public interface PagedResult<T> {
>>>>>>>> 
>>>>>>>>   List<T> next();
>>>>>>>> 
>>>>>>>>   List<T> prev();
>>>>>>>> 
>>>>>>>>   List<T> page(int offset, int limit);
>>>>>>>> 
>>>>>>>> }
>>>>>>>> 
>>>>>>>> and the Async counterpart
>>>>>>>> 
>>>>>>>> public interface AsyncPagedResult<T> {
>>>>>>>> 
>>>>>>>>   void next(Callback<List<T>> callback);
>>>>>>>> 
>>>>>>>>   void prev(Callback<List<T>> callback);
>>>>>>>> 
>>>>>>>>   void page(int offset, int limit, Callback<List<T>> callback);
>>>>>>>> 
>>>>>>>>   public static interface Callback<U> {
>>>>>>>>       public void onResult(U result);
>>>>>>>>   }
>>>>>>>> }
>>>>>>>> 
>>>>>>>> I don't like the idea of having a companion object for holding the
>>>>>>>> pagination state.
>>>>>>>> 
>>>>>>>> Thoughts?
>>>>>>>> 
>>>>>>>> -- qmx
>>>>>>>> 
>>>>>>>> On 15/01/2013, at 08:37, Matthias Wessendorf <matzew at apache.org>
>>>>>>>> wrote:
>>>>>>>> 
>>>>>>>>> Hi Summers,
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> https://gist.github.com/4532661
>>>>>>>>> 
>>>>>>>>> That is a way to do paging which keeps Pipes immutable, uses
>>>>>>>>> readWithFilter, and doesn't impose any (for convenient definitions
>>>>>>>>> of any)
>>>>>>>>> bookkeeping on the developer.
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> from your Andorid gist:
>>>>>>>>> 
>>>>>>>>> A) Once the response has been received, the Pipe implementation will
>>>>>>>>> return a List of objects. If this List instance is passed to
>>>>>>>>> Pipe.getPageContext the appropriate PageContext will be returned
>>>>>>>>> 
>>>>>>>>> Note: There is no 'return' - the readWithFilter is void, instead a
>>>>>>>>> Callback is invoked (onSuccess(list)), see Pipe.java
>>>>>>>>> 
>>>>>>>>> B) The developer will receive from readWithFilter() a List of
>>>>>>>>> object. If
>>>>>>>>> she passes this list into Pipe.getPageContext(List result) she will
>>>>>>>>> receive
>>>>>>>>> the PageContext associated with this result.
>>>>>>>>> 
>>>>>>>>> Do you mean like:
>>>>>>>>> 
>>>>>>>>> ...
>>>>>>>>> myPipe.readWithFilter(filter, new Callback<List<Data>>() {
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> @Override
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> public void onSuccess(List<Data> data) {
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> // get the PageContext:
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> PageContext ctx = myPipe.getPageContext(data);
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> ...
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> }
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> @Override
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> public void onFailure(Exception e) {
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> }
>>>>>>>>> });
>>>>>>>>> Not sure about that.....
>>>>>>>>> 
>>>>>>>>> But for iOS I am thinking about passing in the PageContext into the
>>>>>>>>> closure/block of the readWithFilter, like:
>>>>>>>>> 
>>>>>>>>> -(void) readWithFilter:(void (^)(id<AGFilterConfig> config)) config
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> success:(void (^)(id listOfObjects, id pageContext))success
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> failure:(void (^)(NSError *error))failure;
>>>>>>>>> A usage would look like:
>>>>>>>>> 
>>>>>>>>>   [pipe readWithFilter:^(id<AGFilterConfig> config) {
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> // set the filter args and override the given defaults
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> } success:^(id listOfObjects, id pageContext) {
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> // work with the listOfObjects reponse.
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> // for paging/query info, access the given pagecontext,
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> // of the CURRENT request
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> ...
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> } failure:^(NSError *error) {
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> // handle errorz
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> }];
>>>>>>>>> Any thoughts ?
>>>>>>>>> 
>>>>>>>>> Not sure I like (or understand) the Pipe.getPageContext(List result)
>>>>>>>>> call. Current mindset is that thePageContext just (and only) belongs
>>>>>>>>> to the
>>>>>>>>> previous (executed) request... Not sure I want to support something
>>>>>>>>> like
>>>>>>>>> 
>>>>>>>>> // first call:
>>>>>>>>> List<SomeType> first;
>>>>>>>>> myPipe.readWithFilter(.....) // set first inside of callback
>>>>>>>>> ...
>>>>>>>>> // second call:
>>>>>>>>> List<SomeType> second;
>>>>>>>>> myPipe.readWithFilter(.....) // set second inside of callback
>>>>>>>>> ...
>>>>>>>>> // third call:
>>>>>>>>> List<SomeType> third;
>>>>>>>>> myPipe.readWithFilter(.....) // set third inside of callback
>>>>>>>>> ...
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> /// A BIT LATER ....:
>>>>>>>>> myPipe.getPageContext(first);
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> I am not sure if that (myPipe.getPageContext(first);) is really
>>>>>>>>> desired
>>>>>>>>> (or would even easily work, as it would need to store the
>>>>>>>>> "metadata").....
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Perhaps I am just wrong.
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> --
>>>>>>>>> Matthias Wessendorf
>>>>>>>>> 
>>>>>>>>> blog: http://matthiaswessendorf.wordpress.com/
>>>>>>>>> sessions: http://www.slideshare.net/mwessendorf
>>>>>>>>> twitter: http://twitter.com/mwessendorf
>>>>>>>>> _______________________________________________
>>>>>>>>> aerogear-dev mailing list
>>>>>>>>> aerogear-dev at lists.jboss.org
>>>>>>>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>>>>>>> 
>>>>>>>> 
>>>>>>>> _______________________________________________
>>>>>>>> aerogear-dev mailing list
>>>>>>>> aerogear-dev at lists.jboss.org
>>>>>>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> _______________________________________________
>>>>>>> aerogear-dev mailing list
>>>>>>> aerogear-dev at lists.jboss.org
>>>>>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> --
>>>>>> Matthias Wessendorf
>>>>>> 
>>>>>> blog: http://matthiaswessendorf.wordpress.com/
>>>>>> sessions: http://www.slideshare.net/mwessendorf
>>>>>> twitter: http://twitter.com/mwessendorf
>>>>> 
>>>>> 
>>>>> 
>>>>> --
>>>>> Matthias Wessendorf
>>>>> 
>>>>> blog: http://matthiaswessendorf.wordpress.com/
>>>>> sessions: http://www.slideshare.net/mwessendorf
>>>>> twitter: http://twitter.com/mwessendorf
>>>>> _______________________________________________
>>>>> aerogear-dev mailing list
>>>>> aerogear-dev at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>>> 
>>>> 
>>>> _______________________________________________
>>>> aerogear-dev mailing list
>>>> aerogear-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>>> 
>>>> 
>>>> 
>>>> _______________________________________________
>>>> aerogear-dev mailing list
>>>> aerogear-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>>>> 
>>> 
>>> 
>>> 
>>> --
>>> Matthias Wessendorf
>>> 
>>> blog: http://matthiaswessendorf.wordpress.com/
>>> sessions: http://www.slideshare.net/mwessendorf
>>> twitter: http://twitter.com/mwessendorf
>>> 
>>> _______________________________________________
>>> aerogear-dev mailing list
>>> aerogear-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
>> 
>> 
>> _______________________________________________
>> aerogear-dev mailing list
>> aerogear-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/aerogear-dev
> 
> 
> 
> -- 
> Matthias Wessendorf
> 
> blog: http://matthiaswessendorf.wordpress.com/
> sessions: http://www.slideshare.net/mwessendorf
> twitter: http://twitter.com/mwessendorf
> 
> _______________________________________________
> aerogear-dev mailing list
> aerogear-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/aerogear-dev




More information about the aerogear-dev mailing list