CptDayDreamer
CptDayDreamer

Reputation: 1794

getRowData and getRowKey never executed LazyDataModel

I tried many things know. This thread is related to another thread but now the problem is more specific. I found out that the methods getRowData() and also if I implement it getRowKey() don't get called.

What I've tried:

In my .xhtml I set the rowKey and it's fine. No Compiler Error. In the Controller I write down the getRowData(). I try to select something and this breaks the whole page. The setter doesn't get called. If I don't overwrite getRowData() the compiler still works.

When I try to implement getRowKey() and getRowData() in my Controller it tells me ... exception [getRowKey(T object) must be implemented by ...

Then I tried to implement SelectableDataModel to look if there is any difference but there's not.

When I delete the selectionMode so the whole selection everything is fine. Pagination works great. Also editing columns works. But my contextMenu which is needed to delete an entry does not work.

xhtml:

<h:form id="eintraegeList">
        <p:panel header="Liste aller Einträge">

            <p:dataTable id="table"
                         var="telefonbuch" 
                         lazy="true" 
                         widgetVar="tableWv" 
                         value="#{telefonbuchList.lazyModel}" 
                         editable="true" 
                         resizableColumns="true" 
                         liveResize="true" 
                         style="margin-bottom:20px" 
                         paginator="true" 
                         rows="#{telefonbuchList.pageSize}" 
                         emptyMessage="Keine Telefonbucheinträge vorhanden" 
                         selectionMode="single"
                         selection="#{telefonbuchList.selectedEntry}" 
                         rowKey="#{telefonbuch.id}"
                         currentPageReportTemplate="{startRecord}-{endRecord} von {totalRecords}"
                         paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
                         rowsPerPageTemplate="5,8,10">

            <f:facet name="header">
                <p:commandButton id="toggler" type="button" value="Anzeige" style="float:right" icon="pi pi-align-justify" />
                <p:columnToggler datasource="table" trigger="toggler" />    
            </f:facet>

            <p:ajax event="rowEdit" listener="#{telefonbuchList.onRowEdit}" update="table" />
            <p:ajax event="rowEditCancel" listener="#{telefonbuchList.onRowCancel}" update="table" />
            <p:ajax event="cellEdit" listener="#{telefonbuchList.onCellEdit}" update="table" />
            <p:ajax event="rowSelect" listener="#{telefonbuchList.onRowSelect}" update="table" />

            <p:separator />

                <p:column headerText="ID" sortBy="#{telefonbuch.id}">
                    <h:outputText value="#{telefonbuch.id}" />
                </p:column>
                <p:column headerText="Vorname" sortBy="#{telefonbuch.vorname}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.vorname}" /></f:facet>
                        <f:facet name="input"><p:inputText id="vornameInput" value="#{telefonbuch.vorname}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="Nachname" sortBy="#{telefonbuch.nachname}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.nachname}" /></f:facet>
                        <f:facet name="input"><p:inputText id="nachnameInput" value="#{telefonbuch.nachname}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="Telefonnummer" sortBy="#{telefonbuch.telefonnummer}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.telefonnummer}" /></f:facet>
                        <f:facet name="input"><p:inputText id="telefonnummerInput" value="#{telefonbuch.telefonnummer}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                 <p:column headerText="Handynummer" sortBy="#{telefonbuch.handynummer}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.handynummer}" /></f:facet>
                        <f:facet name="input"><p:inputText id="handynummerInput" value="#{telefonbuch.handynummer}" style="width:100%"/></f:facet>
                    </p:cellEditor>
                </p:column>
                 <p:column headerText="Geschäftsstelle" sortBy="#{telefonbuch.geschaeftsstelle}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.geschaeftsstelle}" /></f:facet>
                        <f:facet name="input">
                            <p:selectOneMenu value="#{telefonbuch.geschaeftsstelle}" style="width:100%">
                                <f:selectItems value="#{telefonbuchController.geschaeftsstellen}" var="c" itemLabel="#{geschaeftsstelle}" itemValue="#{geschaeftsstelle}"/>
                            </p:selectOneMenu>
                        </f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column headerText="Geschlecht" sortBy="#{telefonbuch.gender.shortGender}">
                    <p:cellEditor>
                        <f:facet name="output"><h:outputText value="#{telefonbuch.gender.shortGender}" /></f:facet>
                        <f:facet name="input">
                            <p:selectOneMenu id="gender" value="#{telefonbuch.gender}" style="width:100%">
                                <f:selectItem itemLabel="Keine Angabe" itemValue="" />
                                <f:selectItems value="#{telefonbuch.genders}" var="gender" itemLabel="#{gender.shortGender}" itemValue="#{gender}"/>
                            </p:selectOneMenu>
                        </f:facet>
                    </p:cellEditor>
                </p:column>
                <p:column exportable="false" style="width:20px;text-align:center;">
                    <p:rowEditor />
                </p:column>
            </p:dataTable>

            <p:growl id="growl" showDetail="true" for="eintraege-list">
                <p:autoUpdate />
            </p:growl> 

            <p:separator />

            <p:contextMenu for="table">   
                <p:menuitem value="Löschen" update="table" icon="fas fa-eraser" action="#{telefonbuchList.deleteEntry}"/>
                <p:menuitem value="Edit Cell" icon="pi pi-search" onclick="PF('tableWv').showCellEditor();return false;"/>  
            </p:contextMenu>

        </p:panel>
    </h:form>

Controller:

@Scope(value = "session")
@Component(value = "telefonbuchList")
@ELBeanName(value = "telefonbuchList")
@Join(path = "/", to = "/eintraege-liste.jsf")
public class TelefonbuchListController extends LazyDataModel<Telefonbuch> {

    private static final long serialVersionUID = 1L;
    @Autowired
    private TelefonbuchRepository telefonbuchRepository;
    private List<Telefonbuch> selectedEntries;

    private Telefonbuch selectedEntry;

    private LazyDataModel<Telefonbuch> lazyModel;

    private int pageSize = 5;

    public void deleteEntry() {
        telefonbuchRepository.deleteAll(selectedEntries);
        lazyModel.getWrappedData().removeAll(selectedEntries);
        selectedEntries.clear();
    }

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

    @Override
    public int getPageSize() {
        return pageSize;
    }

    @Override
    public Telefonbuch getRowData(String rowKey) {
        System.out.println("rowKey: " + rowKey);
        List<Telefonbuch> list = getWrappedData();

        for (Telefonbuch telefonbuch : list) {

            if (telefonbuch.getId().toString().equals(rowKey)) {
                return telefonbuch;
            }
        }

        return null;
    }

    @Override
    public Object getRowKey(Telefonbuch telefonbuch) {
        return telefonbuch != null ? telefonbuch.getId() : null;
    }

    public List<Telefonbuch> getSelectedEntries() {
        return selectedEntries;
    }

    public Telefonbuch getSelectedEntry() {
        return selectedEntry;
    }

    @Deferred
    @RequestAction
    @IgnorePostback
    public void loadData() {
        lazyModel = new LazyDataModel<Telefonbuch>() {

            private static final long serialVersionUID = 1L;

            @Override
            public List<Telefonbuch> load(int first, int pageSize, String sortField, SortOrder sortOrder,
                    Map<String, Object> filters) {

                List<Telefonbuch> result = new ArrayList<Telefonbuch>();

                if (first == 0) {
                    if (sortField != null && !sortField.isEmpty()) {
                        if (sortOrder.name().equalsIgnoreCase("ascending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).ascending()))
                                    .getContent();
                        } else if (sortOrder.name().equalsIgnoreCase("descending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).descending()))
                                    .getContent();
                        }

                    } else {
                        result = telefonbuchRepository.findAll(PageRequest.of(first, pageSize)).getContent();
                    }
                } else {
                    first = first / pageSize;
                    if (sortField != null && !sortField.isEmpty()) {
                        if (sortOrder.name().equalsIgnoreCase("ascending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).ascending()))
                                    .getContent();
                        } else if (sortOrder.name().equalsIgnoreCase("descending")) {
                            result = telefonbuchRepository
                                    .findAll(PageRequest.of(first, pageSize, Sort.by(sortField).descending()))
                                    .getContent();
                        }
                    } else {
                        result = telefonbuchRepository.findAll(PageRequest.of(first, pageSize)).getContent();
                    }
                }

                return result;
            }
        };

        lazyModel.setRowCount((int) telefonbuchRepository.count()); // Aufruf auslagern, aber bei gemeinsamen Arbeiten kann neue Row hinzukommen
        lazyModel.setPageSize(pageSize);
    }

    public void onCellEdit(CellEditEvent event) {
        Object oldValue = event.getOldValue();
        Object newValue = event.getNewValue();
        telefonbuchRepository.save((Telefonbuch) newValue);
    } 

    public void onRowEdit(RowEditEvent event) {
        Object oldValue = event.getObject();
        telefonbuchRepository.save((Telefonbuch) oldValue);
        FacesMessage msg = new FacesMessage("Eintrag geändert",
                ((Telefonbuch) event.getObject()).getVorname() + " " + ((Telefonbuch) event.getObject()).getNachname());
        FacesContext.getCurrentInstance().addMessage("eintraege-list", msg);
    }

    public void onRowSelect(SelectEvent event) {
        FacesMessage msg = new FacesMessage("Eintrag ausgewählt",
                ((Telefonbuch) event.getObject()).getVorname() + " " + ((Telefonbuch) event.getObject()).getNachname());
        FacesContext.getCurrentInstance().addMessage("eintraege-list", msg);
    }

    @Override
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public void setSelectedEntries(List<Telefonbuch> selectedEntries) {
        this.selectedEntries = selectedEntries;
    }

    public void setSelectedEntry(Telefonbuch selectedEntry) {
        this.selectedEntry = selectedEntry;
    }

Model:

@Data
@Entity
public class Telefonbuch {

    public enum Gender {
        MALE("Männlich"), FEMALE("Weiblich");

        private String shortGender;

        private Gender(String shortGender) {
            this.shortGender = shortGender;
        }

        public String getShortGender() {
            return shortGender;
        }
    }

    @Column
    @Enumerated(EnumType.STRING)
    private Gender gender;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String vorname;

    @Column
    private String nachname;

    @Column
    private String telefonnummer;

    @Column
    private String handynummer;

    @Column
    private String geschaeftsstelle;

    protected Telefonbuch() {
    }

    public Telefonbuch(String vorname, String nachname, String telefonnummer, String handynummer) {
        this.vorname = vorname;
        this.nachname = nachname;
        this.telefonnummer = telefonnummer;
        this.handynummer = handynummer;
    }

Upvotes: 1

Views: 1554

Answers (1)

Selaron
Selaron

Reputation: 6184

In your method

TelefonbuchListController.loadData() {
    lazyModel = new LazyDataModel<Telefonbuch>() {
     //...
    }

you create a new anonymous instance of the abstract class LazyDataModel. This is then assigned to the lazyModel field which is later returned to your p:dataTable value attribute.

Obviously it does not override the non operative getRowKey nor getRowData methods from the abstract class LazyDataModel.

You will have to override them like this:

public void loadData() {
    lazyModel = new LazyDataModel<Telefonbuch>() {

        // ...

        @Override
        public Telefonbuch getRowData(String rowKey) {
            // your implementation here
        }

        @Override
        public Object getRowKey(Telefonbuch telefonbuch) {
            // your implementation here
        }

        // ...

}

Both methods getRowKey and getRowData you presented in your questions belong to a LazyDataModel implementaion that is not assigned to the p:dataTable value attribute. Hence both never get invoked. If it was the LazyDataModel assigned to the p:dataTable value attribute, your p:dataTable would probably look somehow like this:

<p:dataTable id="table"
    var="telefonbuch" 
    lazy="true" 
    widgetVar="tableWv" 
    value="#{telefonbuchList}" 
...

Upvotes: 3

Related Questions