【问题标题】:Primefaces lazy datascroller calling load twicePrimefaces 惰性数据滚动器调用两次加载
【发布时间】:2015-03-27 14:34:48
【问题描述】:

我正在尝试将 Datascroller 与 LazyDataModel 一起使用,并且来自惰性数据模型的加载方法被调用了两次。

由于我的惰性数据模型不是幂等的(意味着在同一个窗口上连续两次调用模型/page size 返回不同的结果)它被调用两次的事实意味着:呈现的结果不正确。

datascroller中的load方法被调用两次正常吗? 如果是这样,建议我的替代方案正常工作的任何解决方法? (除了从有状态数据模型到无状态数据模型)

使用 Primefaces 5.1、JSF2、Glassfish 4.1

【问题讨论】:

  • 我不是专家,但我不明白有状态与无状态与此有什么关系(甚至认为它是相反的)。其次,它何时被多次调用。在底部移动鼠标?然后查看 PF 版本说明,Elite 版本中引入了一个非常相关问题的修复程序。
  • 错误发生在页面加载时,即在组件渲染阶段。当我通过 PF 源代码 (DataScrollerRenderer) 进行调试时,我看到loadChunk 方法在处理惰性时被有效地调用了两次。将尝试提供 DataScrollerRenderer 的更改版本
  • 顺便说一句,在我的情况下,statefull 意味着多次调用 load 是不安全的——第一次调用返回的数据与第二次调用不同。如果它返回相同的数据就没有问题 - 除了执行冗余数据库调用
  • 这比有状态/无状态更相关indempotent。我会假设您在加载方法中获得的参数两次都是相同的,因此您应该返回相同的结果。如果它们是但你不使用它们(或没有以前的),那么你现在有一个无状态组件,只能在创建有状态组件时解决这个问题(或者我错过了什么)。在实际问题仍然存在的情况下,创建/覆盖渲染器似乎是一种解决方法
  • 我将 statefull 术语更改为 notìdempotent

标签: jsf-2 primefaces


【解决方案1】:

不,这不正常。这确实是 PrimeFaces 中的一个错误。我们不久前在 zeef.com 上使用它时也发现了它。我们通过创建一个自定义渲染器来绕过它,扩展 DataScrollerRenderer 并仅覆盖 encodeMarkup() 方法并复制粘贴原始实现,然后仅删除以下部分:

// BUGFIX: outcommented as this is already done in loadChunk() later on.
/*if(ds.isLazy()) {
    loadLazyData(ds, 0, chunkSize);
}*/

您可以通过如下方式在 webapp 的faces-config.xml 中注册它来运行它:

<render-kit>    
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.DataScrollerRenderer</renderer-type>
        <renderer-class>com.example.YourDataScrollerRenderer</renderer-class>
    </renderer>
</render-kit>

【讨论】:

  • 如果第一次加载(注释部分)未运行,则无法正确呈现标题构面。将在下面提供替代实现
  • 对,我们没有使用标题方面。你的实现看起来很合理。
【解决方案2】:

由于如果第一次加载(注释部分)未运行,则 BalusC 帖子中的标题方面不会正确呈现,因此需要稍微不同的实现

public class DataScrollerRenderer2 extends DataScrollerRenderer {

    @Override
    protected void encodeMarkup(FacesContext context, DataScroller ds, int chunkSize) throws IOException {
        // ... 
        boolean alreadyLoaded = false;
        if (ds.isLazy()) {            
            alreadyLoaded = true;
            loadLazyData(ds, 0, chunkSize);
        }
        // ... 
        loadChunk(context, ds, 0, chunkSize, alreadyLoaded);
        // ... 
    }

    @Override
    protected void loadChunk(FacesContext context, DataScroller ds, int start, int size) throws IOException {
        loadChunk(context, ds, start, size, false);
    }

    private void loadChunk(FacesContext context, DataScroller ds, int start, int size, boolean alreadyLoaded) throws IOException {
        // ... 
        if (ds.isLazy() && !alreadyLoaded) {
            loadLazyData(ds, start, size);
        }
        // ... 
    }

}

不确定这是否是最好的实现,但它确实有效。

编辑:PrimeFaces GitHub 中已提交问题

【讨论】:

  • 刚刚尝试使用 PF 5.3,似乎已修复。至少我的加载​​方法只被调用一次。
  • @Sinclair:你能分享你的代码吗?豆和JSF。非常感谢
猜你喜欢
  • 1970-01-01
  • 2015-09-18
  • 2022-01-23
  • 1970-01-01
  • 2014-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多