Edit row in PrimeFaces dataTable does not update object - jsf

With a PrimeFaces dataTable I try to edit a row. But when I click on the 'Save Row' button, the old value is send to the bean.
I tried to copy the database object to a normal pojo, but still the old value is send to the bean.
I use PrimeFaces 12
XHTML:
<h:form id="form">
<p:growl id="msgs" showDetail="true"/>
<div class="container-fluid">
<h1><h:outputText value="#{txt['rider.title']}"/></h1>
<p:dataTable id="dt_riders" class="table table-striped" value="#{riderView.allRiders}"
var="rider" editable="true">
<p:ajax event="rowEdit" listener="#{riderView.onRowEdit}" update=":form:msgs"/>
<p:ajax event="rowEditCancel" listener="#{riderView.onRowCancel}" update=":form:msgs"/>
<p:column headerText="#{txt['rider.header.id']}">
<h:outputText value="#{rider.id}"/>
</p:column>
<p:column headerText="#{txt['rider.header.name']}">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{rider.name}"/>
</f:facet>
<f:facet name="input">
<p:inputText id="nameInp" value="#{rider.name}"/>
</f:facet>
</p:cellEditor>
</p:column>
<!-- and a few more -->
<p:column>
<p:rowEditor editTitle="Edit Row" cancelTitle="Cancel Edit" saveTitle="Save Row"/>
</p:column>
</p:dataTable>
</div>
</h:form>
The bean:
#ViewScoped
#Named("riderView")
public class RiderView implements Serializable {
private final RiderEjb riderEjb;
private final SecurityOfficer securityOfficer;
public RiderView() {
this(null, null);
}
#Inject
public RiderView(RiderEjb riderEjb, SecurityOfficer securityOfficer) {
this.riderEjb = riderEjb;
this.securityOfficer = securityOfficer;
}
public List<Rider> getAllRiders() {
return riderEjb.findAll(securityOfficer.getTeam());
}
public void onRowEdit(RowEditEvent<Rider> event) {
FacesMessage msg = new FacesMessage("Rider Edited", String.valueOf(event.getObject().getName()));
FacesContext.getCurrentInstance().addMessage(null, msg);
riderEjb.addOrUpdate(event.getObject());
}
public void onRowCancel(RowEditEvent<Rider> event) {
FacesMessage msg = new FacesMessage("Edit Cancelled", String.valueOf(event.getObject().getName()));
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
The Java object (getters and setters are generated by Lombok):
#Entity
#Getter
#Setter
public class Rider extends AbstractEntity {
#Id
private Long id;
private String name;
private Double weight;
private String gpxNames;
}

The problem was the method getAllRiders(). That calls the bean to gather the riders from the database. I changed it to retrieve all those riders from the database in a new #PostConstruct init() method.
Thanks to Jasper de Vries, I used the primefaces-test to pinpoint the problem.

Related

Problems after using Primefaces filter

I have a datatable where one of the columns is editable.
As long as i dont use my filter i can navigate through my list and can edit the entry in any row i want. I dont get any errors and my changes are persisted in the DB correctly.
But after i once used any of the filter everything goes sideways. The filter itself works properly.
But when i now try to edit any entry the event.oldValue() from my CellEditEvent is always null and i cant persist my entries.
And only the first page of my paginator is filled with data. Every other page is empty.
Here is the view:
<div class="Container100">
<p:dataTable paginator="true" rows="15" var="listReportingParticipantOverview" value="#{reportingBean.listReportingParticipantOverview}"
id="participantOverviewId" widgetVar="participantOverviewId"
editable="true" editMode="cell" editInitEvent="dblclick"
emptyMessage="#{msg['system.no_result']}"
filteredValue="#{reportingBean.filteredListReportingParticipantOverview}">
<p:ajax event="cellEdit" listener="#{reportingBean.onCellEdit}" update=":reportingForm:msgs"/>
<p:column headerText="#{msg['model.reporting.participant_overview.name']}" filterBy="#{listReportingParticipantOverview.name}" filterMatchMode="contains">
<h:outputText value="#{listReportingParticipantOverview.name}" />
</p:column>
<p:column headerText="#{msg['model.reporting.participant_overview.dateOfBirth']}" filterBy="#{listReportingParticipantOverview.dateOfBirth}" filterMatchMode="contains">
<h:outputText value="#{listReportingParticipantOverview.dateOfBirth}" />
</p:column>
<p:column headerText="#{msg['model.reporting.participant_overview.email']}" filterBy="#{listReportingParticipantOverview.email}" filterMatchMode="contains">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{listReportingParticipantOverview.email}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{listReportingParticipantOverview.email}" style="width:100%" label="name"/>
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</div>
Here is the bean:
#SessionScoped
#ManagedBean(name = "reportingBean2")
public class ReportingBean2 extends BeanController implements Serializable {
List<ReportingParticipantOverview> listReportingParticipantOverview = new ArrayList<ReportingParticipantOverview>();
List<ReportingParticipantOverview> filteredListReportingParticipantOverview;
ContactRepository contactRepository;
ContactRepository contactRepositoryOtherDBContext;
CommunicationRepository communicationRepositoryOtherDBContext;
private AbstractApplicationContext otherDBContext;
public void initData() {
this.listReportingParticipantOverview = this.contactRepositoryOtherDBContext
.selectParticipantOverviewReporting();
}
#PostConstruct
public void init() {
otherDBContext = new ClassPathXmlApplicationContext("applicationContext_otherDB.xml");
this.contactRepository = this.getApplicationContext().getBean(ContactRepository.class);
this.contactRepositoryOtherDBContext = otherDBContext.getBean(ContactRepository.class);
this.communicationRepositoryOtherDBContext = otherDBContext.getBean(CommunicationRepository.class);
}
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
// ...
}
public List<ReportingParticipantOverview> getListReportingParticipantOverview() {
return listReportingParticipantOverview;
}
public void setListReportingParticipantOverview(
List<ReportingParticipantOverview> listReportingParticipantOverview) {
this.listReportingParticipantOverview = listReportingParticipantOverview;
}
public List<ReportingParticipantOverview> getFilteredListReportingParticipantOverview() {
return filteredListReportingParticipantOverview;
}
public void setFilteredListReportingParticipantOverview(
List<ReportingParticipantOverview> filteredListReportingParticipantOverview) {
this.filteredListReportingParticipantOverview = filteredListReportingParticipantOverview;
}
}
}
I am using Java 8, Eclipse 2021-03 and Primefaces 10.0.0.
Any help appreciated :-)

Error while perfoming Row Edit in p:dataTable

I am trying to perform a row edit in primefaces databable. My problem is when I key in new value in inputText in CellEditor
and click edit (primefaces icon) onCellEdit method is calledsuccessfully but does not pick the newly value in the inputText it pick value that was initially in the datatable. What Am I doing wrong? I am using primefaces 3.5
Here in jsf code
<h:form id="form1">
<p:growl id="messages" showDetail="true"/>
<p:panel header="Registered Devices" style="min-height: 400px;" id="paneldevices">
<p:dataTable emptyMessage="No Device Registered" editable="true" widgetVar="deviceTable" id="idGrid" value="#{deviceMgdBean.devices}" var="item" >
<p:ajax event="rowEdit" listener="#{deviceMgdBean.onCellEdit()}" update=":form1:messages"/>
<p:ajax event="rowEditCancel" listener="#{deviceMgdBean.onCancel}" update=":form1:messages" />
<p:column headerText="Options" style="width:50px">
<p:rowEditor />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Device_name"/>
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item.device_name}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.device_name}" style="width:80%" />
</f:facet>
</p:cellEditor>
</p:column>
</h:form>
Here is my managed Bean
#ManagedBean
#ViewScoped
public class DeviceMgdBean implements Serializable {
public List<Devices> getDevices()
{
List<Devices> l=getDevdao().getDevices();//devices fetched from database
return l;
}
public void onCellEdit(RowEditEvent event)
{
Devices devo=(Devices) event.getObject();
FacesMessage msg = new FacesMessage("Device Edit","Test:"+devo.getDeviceName());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onCancel(RowEditEvent event)
{
FacesMessage msg = new FacesMessage("Item Cancelled");
FacesContext.getCurrentInstance().addMessage(null, msg);
Devices devo=(Devices) event.getObject();
}
}
class Devices {
private int device_id;
private String device_name;
//getter and setters
}
private List<Devices> l;
public List<Devices> getDevices() {
if(l==null) l=getDevdao().getDevices();//devices fetched from database
return l;
}

Update a row in p:dataTable

I'm working with JSF and primefaces. I want to update a row when I click on the button (pencil). I used the first code from this tutorial (Primefaces docs), but dosent work in my case.
the problem is : when i click the button (pencil) to update a row, nothing change. i have always the old values
This is my JSF code :
<f:view>
<h:form id="form">
<p:growl id="msgs" showDetail="true"/>
<p:dataTable id="tservice" var="item" value="#{serviceMBean.services}" editable="true" style="margin-bottom:20px">
<f:facet name="header"> edit </f:facet>
<p:ajax event="rowEdit" listener="#{serviceMBean.onRowEdit}" update=":form:msgs" />
<p:ajax event="rowEditCancel" listener="#{serviceMBean.onRowCancel}" update=":form:msgs" />
<p:column headerText="Libelle du service">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{item.libelleservice}" /></f:facet>
<f:facet name="input">
<p:inputText value="#{item.libelleservice}" style="width:100%" label="Libelle"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Utilisateurs/Service">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{item.nbruserservice}" /></f:facet>
<f:facet name="input">
<p:inputText value="#{item.nbruserservice}" style="width:100%" label="Nbre Users"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style="width:32px">
<p:rowEditor />
</p:column>
And this is my managed bean code:
#Named(value = "serviceMBean")
#ViewScoped
public class ServiceMBean implements Serializable {
private List<Service> serviceList;
private Service s;
#EJB
private ServiceManager serviceManager;
public ServiceMBean() {}
public void modifierService(Service s1) {
this.serviceManager.updateService(s1);
}
public void onRowEdit(RowEditEvent event) {
Service s2 = (Service) event.getObject();
System.out.println("--->" + s2.getNbruserservice());
FacesMessage msg = new FacesMessage("Service Modifié", ((Service) event.getObject()).getLibelleservice());
this.modifierService(s2);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowCancel(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Modification annulée", ((Service) event.getObject()).getLibelleservice());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
And this is my code for ServiceManager:
public void updateService(Object service) {
em.merge(service);
}
I think the setter in my JSF page doesn't work. Any solutions or suggestions?
Solution : Add a void method with #PostConstruct.
Example : #PostConstruct
#PostConstruct
public void initialiser() {
serviceList = this.getServices();
}
Don't forget the getter and setter of serviceList
In the JSF page, the value of datatable will be : value="#{ServiceMBean.serviceList}"

Edit row using Radio button and commandButton

Can I use radio button to select a single row then edit some of data on that row then use
commandButton to submit what I edit it in that row. I'm trying to edit username cell for now as test.
this a snap of my code:
Xadmin.xhtml
<h:form id="form" enctype="multipart/form-data">
<p:growl id="msgs" showDetail="true" />
<p:dataTable id="DT" value="#{Jadmin.messages}"
var="o"
selection="#{Jadmin.selectedUser}"
rowKey="#{o.id}"
style="margin-bottom:20px">
<f:facet name="header">
Users List
</f:facet>
<p:column selectionMode="single" />
<p:column>
<f:facet name="header">
<h:outputText value="id" />
</f:facet>
<h:outputText value="#{o.id}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="username" />
</f:facet>
<p:inputText value="#{o.username}" />
</p:column>
<f:facet name="footer">
<h:commandButton value="Update" action="#{Jadmin.update}" />
<p:commandButton value="Delete"
action="#{Jadmin.delete}"
ajax="false"
update=":form:msgs"/>
</f:facet>
</p:dataTable>
JadminBeans.java
#ManagedBean(name = "Jadmin")
#SessionScoped
public class JadminBeans implements Serializable {
private static final long serialVersionUID = 1L;
private JadminController selectedUser;
List<JadminController> userslist = new ArrayList<JadminController>();
public List<JadminController> getMessages() {
System.out.println("List<JadminController> getMessages()");
userslist = JadminDAO.getAllUsers();
return userslist;
}
public void delete() {
//System.out.println(usr);
//System.out.println(itemList.remove(item)+"!!");
System.out.println("JadminBeans >> delete() ---------- id= ");
JadminDAO.deleteUser(selectedUser);
}
public JadminController getSelectedUser() {
return selectedUser;
}
public void setSelectedUser(JadminController selectedUser) {
this.selectedUser = selectedUser;
}
public void update() {
//o=(JadminBeans) objct;
JadminDAO.updateUser(selectedUser);
}
}
JadminDAO.java
public static void deleteUser(JadminController user) {
try {
PreparedStatement preparedStatement = connection.prepareStatement("delete from users where id=?");
// Parameters start with 1
preparedStatement.setLong(1, user.getId());
preparedStatement.executeUpdate();
System.out.println("JadminDAO >> deleteUser ----------");
} catch (SQLException e) {
System.out.println("JadminDAO >> deleteUser----------- SQLException :(");
e.printStackTrace();
}
}
public static void updateUser(JadminController user) {
try {
PreparedStatement preparedStatement = connection.prepareStatement("update users username=?, password=?, permission=? where username=?");
// Parameters start with 1
//System.out.println(new java.sql.Date(user.getRegisteredon().getTime()));
preparedStatement.setString(1, user.getUsername());
preparedStatement.setString(2, user.getPassword());
preparedStatement.setString(3, user.getPermission());
//preparedStatement.setDate(3, new java.sql.Date(user.getRegisteredon().getTime()));
preparedStatement.setString(4, user.getUsername());
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
JadminController.java
public class JadminController implements Serializable {
private static final long serialVersionUID = 1L;
private String username, password, permission;
private long id;
// Getters and setters.
}
If you use Editable Datatable you don't need any command button to submit what you've edited.
As shown in the same link, inside in datatable is usually used a selectOneMenu instead of radioButton for making choices.
To use input element inside your datatable don't forget to put <f:facet name="output"></f:facet> and <f:facet name="input"></f:facet>
I hope it helps.

JSF Primefaces datatable doesn't show the right values

I have a problem with primefaces datatable. I'm getting the data from my database and it's saved in a list. That's works great! But the datatable just displays one column instead of four and this column is copied in every row.
<h:form id="userslistform">
<p:dataTable id="userlist" var="users" value="#{userBean.usersList}"
rowKey="#{userBean.username}">
<p:column headerText="ID">
<h:outputText value="#{userBean.id}" />
</p:column>
<p:column headerText="Username">
<h:outputText value="#{userBean.username}" />
</p:column>
<p:column headerText="Firstname">
<h:outputText value="#{userBean.firstname}" />
</p:column>
<p:column headerText="Surname">
<h:outputText value="#{userBean.surname}" />
</p:column>
</p:dataTable>
</h:form>
Bean:
#Named
#SessionScoped
#ManagedBean(name = "userBean")
public class UserBean implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private String firstname;
private String surname;
private Long id;
private String email;
private Long treeId;
private Boolean isadmin;
private List<User> usersList;
private User selectedUser;
private UserDataQuery query = new UserDataQuery();
//getter and setters of every attribute
...
#PostConstruct
public void init() {
usersList = query.getAllUsers();
}
}
DAO:
public class UserDataQuery {
private EntityManagerFactory enf;
private EntityManager em;
public UserDataQuery() {
enf = Persistence.createEntityManagerFactory("xxxx");
em = enf.createEntityManager();
em.getTransaction().begin();
}
public List<User> getAllUsers() {
List<User> usersList = em.createNamedQuery("User.findAll", User.class)
.getResultList();
return usersList;
}
...
}
You need to use value from var inside your table, to display the data
<h:form id="userslistform">
<p:dataTable id="userlist" var="users" value="#{userBean.usersList}"
rowKey="#{userBean.username}">
<p:column headerText="ID">
<h:outputText value="#{users.id}" />
</p:column>
<p:column headerText="Username">
<h:outputText value="#{users.username}" />
</p:column>
<p:column headerText="Firstname">
<h:outputText value="#{users.firstname}" />
</p:column>
<p:column headerText="Surname">
<h:outputText value="#{users.surname}" />
</p:column>
</p:dataTable>
</h:form>
var value represents a reference to current row, at the time the table is rendered. With #{userBean.<attribute>} you were always displaying values that were fixed. And, now you don't need those attributes in the bean itself, just the list (unless, of course, you need them for another purpose).

Resources