But the implementation to make paging stateless is not presented.
I wrote the following simple implementation.
public class BookmarkableNavigator extends PagingNavigator { private static final long serialVersionUID = 1117219289688557460L; private static final String DEFAULT_KEYNAME = "page"; private final String keyName; public BookmarkableNavigator(String id, IPageable pageable) { this(id, pageable, DEFAULT_KEYNAME); } public BookmarkableNavigator(String id, IPageable pageable, String keyName) { super(id, pageable); this.keyName = keyName; } @Override protected void onInitialize() { super.onInitialize(); int currentPage; try { currentPage = getPage().getPageParameters().get(keyName).toInt(); }catch (StringValueConversionException e) { currentPage = 0; } getPageable().setCurrentPage(currentPage); } private PageParameters getParams(int page) { PageParameters params = new PageParameters(getPage().getPageParameters()); // copy params.set(keyName, page); return params; } @Override protected AbstractLink newPagingNavigationIncrementLink(String id, final IPageable pageable, final int increment) { int idx = pageable.getCurrentPage() + increment; int page = Math.max(0, Math.min(pageable.getPageCount() - 1, idx)); return new BookmarkablePageLink<void>(id, getPage().getClass(), getParams(page)) { private static final long serialVersionUID = 4583210927959068500L; private boolean isFirst() { return pageable.getCurrentPage() <= 0; } public boolean isLast() { return pageable.getCurrentPage() >= (pageable.getPageCount() - 1); } @Override public boolean linksTo(final Page page) { pageable.getCurrentPage(); return ((increment < 0) && isFirst()) || ((increment > 0) && isLast()); } }.setAutoEnable(true); } // copy from PagingNavigationLink#cullPageNumber private int cullPageNumber(int pageNumber) { int idx = pageNumber; IPageable pageable = getPageable(); if (idx < 0) idx = pageable.getPageCount() + idx; if (idx > (pageable.getPageCount() - 1)) idx = pageable.getPageCount() - 1; if (idx < 0) idx = 0; return idx; } private class BookmarkableNavigationLink extends BookmarkablePageLink<void< { private static final long serialVersionUID = 7905210383154082192L; private final int pageNumber; private final IPageable pageable; public <c extends page> BookmarkableNavigationLink( String id, Class<c> pageClass, IPageable pageable, int pageNumber) { super(id, pageClass, getParams(pageNumber)); this.pageNumber = pageNumber; this.pageable = pageable; setAutoEnable(true); } @Override public final boolean linksTo(final Page page) { return cullPageNumber(pageNumber) == pageable.getCurrentPage(); } } @Override protected AbstractLink newPagingNavigationLink(String id, final IPageable pageable, final int pageNumber) { return new BookmarkableNavigationLink(id, getPage().getClass(), pageable, cullPageNumber(pageNumber)); } @Override protected PagingNavigation newNavigation(String id, IPageable pageable, IPagingLabelProvider labelProvider) { return new PagingNavigation(id, pageable, labelProvider) { private static final long serialVersionUID = -4044262294210880251L; @Override protected AbstractLink newPagingNavigationLink(String id, IPageable pageable, int pageIndex) { return new BookmarkableNavigationLink(id, getPage().getClass(), pageable, pageIndex); } }; } }