5

Primefaces Datascrollerコンポーネントの遅延読み込みに問題があります。

ページの読み込み時に 10 個のイベントを表示する jsf ページがあります。ユーザーがさらに見たい場合は、[詳細] ボタンをクリックして、次の 10 個のイベントを読み込んで表示できます。各イベント行には、イベントの詳細を表示するために使用できるリンクがあります。

    <h:form id="mainForm" >
        <p:dataScroller value="#{backing.lazyModel}" var="event" lazy="true" chunkSize="10" rowIndexVar="index">
            #{event.name}
            <p:commandLink class="view-trigger"
                value="View Event Details"
                actionListener="#{backing.initViewEventDetails(index, event)}"/>
            <f:facet name="loader">
                <p:outputPanel 
                        visible="#{backing.lazyModel.rowCount gt 10}"
                        rendered="#{backing.lazyModel.rowCount gt 10}">
                    <p:commandLink value="More" />
                </p:outputPanel>
            </f:facet>
        </p:dataScroller>
    </h:form>

最初の検索は正常に機能します。つまり、[イベントの詳細を表示] リンクをクリックすると、バッキング Bean が呼び出され、受信したインデックスとイベントがクリックした行に対応していることがわかります。

ただし、1 つの余分なイベントで構成される次のチャンクを読み込むと、ページには 11 個のイベントが表示されますが、[イベントの詳細を表示] リンクをクリックすると、適切なインデックスが送信されますが、適切なイベントは送信されません。たとえば、インデックス 0 のイベントをクリックすると、インデックス 10 のイベントが取得されます。インデックス 1 のイベントをクリックすると、バッキング Bean は呼び出されません。

[詳細] ボタンをクリックすると、データスクローラーが最後の 10 個のイベントを忘れているように見えますが、遅延データ モデルはまだ記憶しています。

バッキング Bean:

@ManagedBean(name="backing")
@ViewScoped
public class DataScrollerBacking implements Serializable {

private static final long serialVersionUID = 4012320411042043677L;
private static final Logger LOGGER = Logger.getLogger(DataScrollerBacking.class);

@ManagedProperty("#{settings.dataSource}")
private String dataSource;

private WebEventDAO webEventDAO;

private LazyDataModel<Event> lazyModel;

@PostConstruct
public void init() {
    webEventDAO = CommonDAOFactory.getInstance(dataSource).getWebEventDAO();
    search();
}

public void search() {
    DateTime start = new DateTime(2014, 1, 1, 0, 0 ,0);
    final Date startDate = start.toDate();
    final Date endDate = start.plus(Years.ONE.toPeriod()).minus(Seconds.ONE.toPeriod()).toDate();

    lazyModel = new LazyDataModel<Event>() {

        private static final long serialVersionUID = 1231902031619933635L;
        private LinkedHashSet<Event> eventCache; // Ordered set of all retrieved events so far.
        // I'm using a set because the load method is called twice on page load (any idea why???) and I don't want duplicates in my cache.

        @Override
        public List<Event> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
            List<Event> events = new ArrayList<Event>(10);
            try {
                if(eventCache == null){
                    int count = webEventDAO.getSearchByPeriodRaceTypeAndRaceStatusForCompanyCount(Collections.singletonList(1), startDate, endDate, null, null);
                    this.setRowCount(count);
                    eventCache = new LinkedHashSet<Event>(count);
                }
                events = webEventDAO.searchByPeriodRaceTypeAndRaceStatusForCompany(Collections.singletonList(1), startDate, endDate, null, null, true, first, pageSize);
                eventCache.addAll(events);
            } catch (DAOException e) {
                LOGGER.error("An error occurred while retrieving events.", e);
            }
            return events;
        }
    };

}

public void initViewEventDetails(Integer index, Event event){
    LOGGER.info("index=" + index + " eventname=" + event.getName());
}

public String getDataSource() {
    return dataSource;
}

public void setDataSource(String dataSource) {
    this.dataSource = dataSource;
}

public LazyDataModel<Event> getLazyModel() {
    return lazyModel;
}

public void setLazyModel(LazyDataModel<Event> lazyModel) {
    this.lazyModel = lazyModel;
}}

ページには適切な情報が表示され、受け取ったインデックスは常に有効であるため、現在の回避策は、レイジー データ モデルのイベントをインデックスでフェッチすることです。

ただし、受信したイベントがクリックしたものではない理由を理解したいと思います。

私は何か間違ったことをしていますか、それともスクローラーの実装方法ですか?

Mojarra 2.2、Tomcat 7、Primefaces 5、Omnifaces 1.8 で実行

4

3 に答える 3