使用未知数量的项目抛出LazyDataModel抛出IllegalArgumentException

时间:2015-07-02 14:15:37

标签: jsf-2 primefaces lazy-loading

我正在尝试使用LazyDataModel向<p:dataScroller>提供未知数量的项目。我在请求时从存储中读取它们(来自用户交互),然后将所需数量发送回模型。

这些项目确实结束了,但在我全部阅读之前我不知道数量,因此我在DataModel上设置了1,000个项目的上限。

模型中的load()实现:

@Override
public List<MyPojo> load(int first, int pageSize, String sortField,
        SortOrder sortOrder,
        Map<String, Object> filters) {
    return managedBean.loadMoreItens(first, pageSize);
}   

loadMoreItens(int, int)

List<MyPojo> loadMoreItens(int first, int pageSize) {

    int amountLoaded = 0;
    while(first+pageSize > this.list.size()) {
        if (this.endReached) {
            break;
        }
        amountLoaded++;
        list.add(readNewItem()); //readNewItem sets boolean if it reaches the end.
    }
    int end = first + pageSize;

    // do some other unrelated stuff like logging and such.

    return list.subList(first, Math.min(end, list.size()));
}

它运行正常,每次用户滚动组件时都会加载chunkSize itens(因此我将跳过在这里发布JSF),但是当到达终点时,会抛出一个令人讨厌的异常:

Jul 02, 2015 10:58:51 AM com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback visit
SEVERE: java.lang.IllegalArgumentException: fromIndex(380) > toIndex(371)

这里的380/371数字是随机生成的测试质量,因此数量可能会发生变化。问题是要达到要读取的项目的结束,但模型仍然认为少于1,000。

如何避免抛出该异常?

P.S。:

  1. 这些项目不是来自数据库。没有办法进行轻度查询&#34;在不获取所有物品的情况下了解数量。
  2. 获取新项目的过程非常昂贵(无法说明它们是什么),除非有必要,否则不应该这样做。
  3. 使用前两个项目初始化managedBean,这些项目位于需求规范中。可能有数百个或几十个。有1000个硬件上限。
  4. 托管bean尝试在初始化lazyModel之前获得20个itens,因此如果少于20个项目,我可以设置正确的数量,但是它将少于0.1%的情况。

1 个答案:

答案 0 :(得分:1)

正如@Kukeltje指出的那样,PF项目负责人已经将这个问题标记为new-feature,因此在Primefaces发布该功能之前没有解决方案。

https://code.google.com/p/primefaces/issues/detail?id=5750

https://github.com/primefaces/primefaces/issues/51

变通方法对我不起作用,因为问题出在分页数据表中,而我使用的是dataScroller。

问题在于subList()命令;我不得不将两个索引限制为list.size()

List<MyPojo> loadMoreItens(int first, int pageSize) {

    int amountLoaded = 0;
    while(first+pageSize > this.list.size()) {
        if (this.endReached) {
            break;
        }
        amountLoaded++;
        list.add(readNewItem()); //readNewItem sets boolean if it reaches the end.
    }
    int end = first + pageSize;

    // do some other unrelated stuff like logging and such.

    return list.subList(Math.min(first,list.size()), Math.min(end, list.size()));
}

它会跳过其余部分并避免异常,但负载控制不会从页面中消失。

然后我添加了一个javascript代码,以便在通过remoteCommand到达目的地时隐藏它。