问题
I am brand new to cursors and have the following method:
public List<Venue> findPage(Subject subject, Objectify ofy, int pageSize) {
final Business business = (Business) subject.getSession().getAttribute(BUSINESS_ATTRIBUTE);
final Query<Venue> query = ofy.query(Venue.class).filter(BUSINESS_ATTRIBUTE, business);
final String encodedCursor = (String) subject.getSession().getAttribute(VENUE_CURSOR_CONDITION);
if (encodedCursor != null) {
query.startCursor(Cursor.fromWebSafeString(encodedCursor));
}
final QueryResultIterator<Key<Venue>> iterator = query.fetchKeys().iterator();
final List<Key<Venue>> data = new ArrayList<Key<Venue>>(pageSize);
boolean more = false;
for (int i = 0; i < pageSize && (more = iterator.hasNext()); i++) {
data.add(iterator.next());
}
subject.getSession().setAttribute(VENUE_CURSOR_CONDITION, iterator.getCursor().toWebSafeString());
return get(ofy, data);
}
where get is the following method
public <T> List<T> get(Objectify ofy, List<Key<T>> keys) {
if (keys == null) {
return null;
}
final Map<Key<T>, T> map = ofy.get(keys);
final List<T> list = new ArrayList<T>();
for (T t : map.values()) {
list.add(t);
}
return list;
}
Now, here's what I'm doing currently - which is a little hackish. I am using Apache Shiro to track User's sessions - in the user's session I am keeping the last cursor that was used - if the user navigates away from the page i set the cursor to false (obviously - this is very, very brittle as it requires every method to have a code to invalidate the last cursor).
Now, here's where I'm getting caught. I made a simple HasCursor interface, and was going to pass back a List with Cursor in it to the client side - the only problem is RequestFactory can only handle passing certain types from server to client - this Custom type isn't one of them. So, right now with GWT RequestFactory - is there a good way to pass an Objectify Cursor from the Server to the Client?
Also - another issue I'm running into - if I populate the DataGrid with this data it shows the data fine in the grid - but that's it - the pager says 1-25 out of 25. So, what I'm wondering is, how do you actually tell the DataGrid that there is more data available on the server. I'm a little confused as it seems there isn't a whole lot of documentation / examples available for this.
Thank you very much
for anybody else that runs into this problem i found out the answer to one part of it - i forgot all about ValueProxies that allow you to map standard java beans to return to the client side from the server with RequestFactory.
Unfortunately, you can't use Generics with ValueProxies so I had to create a ListCursor wrapper for each individual type.
Here's the proxy:
@ProxyFor(value = VenueListCursorWrapper.class)
public interface VenueListCursorWrapperProxy extends ValueProxy {
List<VenueProxy> getVenues();
String getCursor();
boolean isMoreAvailable();
void setVenues(List<VenueProxy> venues);
void setCursor(String cursor);
void setMoreAvailable(boolean moreAvailable);
}
and here's the updated method on the server:
public VenueListCursorWrapper findPage(Subject subject, Objectify ofy, int pageSize, String cursor) {
final Business business = (Business) subject.getSession().getAttribute(BUSINESS_ATTRIBUTE);
final Query<Venue> query = ofy.query(Venue.class).filter(BUSINESS_ATTRIBUTE, business);
if (cursor != null) {
query.startCursor(Cursor.fromWebSafeString(cursor));
}
final QueryResultIterator<Key<Venue>> iterator = query.fetchKeys().iterator();
final List<Key<Venue>> data = new ArrayList<Key<Venue>>(pageSize);
boolean more = false;
for (int i = 0; i < pageSize && (more = iterator.hasNext()); i++) {
data.add(iterator.next());
}
return new VenueListCursorWrapper(get(ofy, data), iterator.getCursor().toWebSafeString(), more);
}
So - that's that part of it - the one thing I still haven't quite figured out how to do is get the pager set up correctly - I would like to show the total count of items in the pager to allow you to page through it but I'm not sure exactly how to do this yet - if I find a solution I will post it
回答1:
You can convert Cursor
to a serializable string - actually you already use this: iterator.getCursor().toWebSafeString()
.
Just return the serialized cursor (= a String) to the client together with all other list data and on the next request provide it as a parameter.
Optonaly use it in fragment identifier, aka GWT history token, so that user can actually bookmark the particular page in your list (depends on the use case, makes sense if list data does not change much).
来源:https://stackoverflow.com/questions/11058737/gwt-pass-objectify-cursor-from-server-to-client-with-requestfactory-and-show-mor