简体   繁体   中英

Primefaces datatable pagination not working

I have a application using JSF2.0, Spring3 and Hibernate4.

I am displaying values in Primefaces 3.4.2 datatable, the problem is when I click the pagination, datatable rows always remain in first 10 records. It doesn't displays next 10 records.

My datatable code

<h:form>
        <p:dataTable id="dataTable" var="req" value="#{reqMB.myList}"
            paginator="true" rows="10"
            paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
            rowsPerPageTemplate="5,10,15">
            <f:facet name="header">          

        </f:facet>
            <p:column>
                <f:facet name="header">
                    <h:outputText value="XXX" />
                </f:facet>
                <h:outputText value="#{req.bbbb}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="XXXXS" />
                </f:facet>
                <h:outputText value="#{req.kkjj}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="XXXXXOO" />
                </f:facet>
                <h:outputText value="#{req.nnnn}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="XXXXKK" />
                </f:facet>
                <h:outputText value="#{req.kkkk}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="XKKKK" />
                </f:facet>
                <h:outputText value="#{req.pppp}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="LLLL" />
                </f:facet>
                <h:outputText value="#{req.llll}" />
            </p:column>
        </p:dataTable>
    </h:form>

ManagedBean

@Named("reqMB")
@Scope("request")
public class MyBean implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    MyService myService;

    List<MyClass> myList;


    public List<MyClass> getMyList() {
        try {
            myList= new ArrayList<MyClass>();
            myList.addAll(getMyService().getMymethod());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return myList;
    }

How can I resolve this issue?

Update 1

I have noticed that when I display few number of records pagination works fine, but when I display records more than 1300, then pagination doesn't work.

I just tried 30000 records and it worked ok. One thing worth noticing though is that the getMyList method gets called many times (6 in my case in render response phase)and each time it is called your bean fetch/generate a brand new list, and that may be the part that is causing the problem (Although I tried to generate a new list in my getter method but it worked OK).

Generally speaking it is recommended not to put any business logic related codes there. Instead in many cases it would be better to populate the list in your @PostConstruct method or somewhere else. Please see the post made by BalusC and it may be helpful. Why JSF calls getters multiple times Also you can read this for lazy loading Efficient JSF Pagination

Below are my test codes:

<h:body>
    <h:form>
        <p:dataTable id="dataTable" var="car" value="#{tableBean.cars}"
                     paginator="true" rows="10"
                     paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                     rowsPerPageTemplate="5,10,15">
            <f:facet name="header">
                Ajax Pagination
            </f:facet>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="Model" />
                </f:facet>
                <h:outputText value="#{car.model}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="Manufacturer" />
                </f:facet>
                <h:outputText value="#{car.manufacturer}" />
            </p:column>

            <p:column>
                <f:facet name="header">
                    <h:outputText value="Other Information" />
                </f:facet>
                <h:outputText value="#{car.otherInformation}" />
            </p:column>
        </p:dataTable>
    </h:form>
    <ui:debug hotkey="x"/>
</h:body>

And this is the backing bean:

@ManagedBean
@RequestScoped
public class TableBean implements Serializable {

    private List<Car> cars;

    @PostConstruct
    public void init() {
        System.out.println("A new backing bean has been created");
        cars = new ArrayList<Car>();
        populateRandomCars(cars, 300000);
    }

    private void populateRandomCars(List<Car> list, int size) {
        for (int i = 0; i < size; i++) {
            list.add(new Car(i, i, UUID.randomUUID().toString()));
        }
    }

    public List<Car> getCars() {
//If i populate the list here I can still get the correct result.
//        cars = new ArrayList<Car>();
//        populateRandomCars(cars, 30000);
        return cars;
    }

    public void setCars(List<Car> cars) {
        this.cars = cars;
    }
}

And finally the model class:

public class Car {
    private int manufacturer;
    private int model;
    private String otherInformation;

    public Car(int manufacturer, int model, String otherInformation){
        this.manufacturer = manufacturer;
        this.model = model;
        this.otherInformation = otherInformation;
    } 

    //Getters and Setters 
}

The problem is that you are creating everytime the datatable when you use in this way:

public List<MyClass> getMyList() { 
  ...
  myList= new ArrayList<MyClass>();
  ...
}

you need to initialize first myList attribute for example you can use @PostContruct

@PostConstruct
public void init() {
   myList= new ArrayList<MyClass>();
}

then, you can use:

public List<MyClass> getMyList() { 
   return myList
}

This will works even with Lazy datatables

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM