JSF - How to get old and new value when using Primefaces RowEditEvent? - java

I have a datatable with 2 columns(name and description) and I want to update my database when a person updates a row and clicks the checkmark which triggers the execBacking.update method.
In this method, I get the new values by casting event.getObject(), but how can i also get the old values? The name is my primary key so i need the old value to know which row to update in the db.
xhtml page
<p:ajax event="rowEdit" listener="#{execBacking.update}" update=":execForm:execMessages" />
<p:column headerText="Name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{exec.name}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{exec.name}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Description">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{exec.description}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{exec.description}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Actions">
<p:rowEditor />
<p:commandLink styleClass="ui-icon ui-icon-trash" type="submit" actionListener="#{execBacking.delete}" update=":execForm:execMessages" >
<f:attribute name="execName" value="#{exec.name}" />
</p:commandLink>
</p:column>
</p:dataTable>
Backing bean
public void update(RowEditEvent event) {
Dao dao = new Dao(ds);
Exec exec = (Exec) event.getObject();
System.out.println("name = "+exec.getName()); //New name
System.out.println("desc = "+exec.getDescription()); //New desc
try {
// If the new exec was updated successfully
if(dao.updateExec(accessBacking.getUsername(), null, exec.getName(), exec.getDescription())) {
FacesContext.getCurrentInstance().addMessage("growl", new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "Exec Updated Successfully!"));
} else {
FacesContext.getCurrentInstance().addMessage("messages", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Error Updating Exec!"));
}
} catch (Exception e) {
FacesContext.getCurrentInstance().addMessage("messages", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", e.getMessage()));
}
}

I would recommend not having name be your primary key, but instead add an auto-incrementing id field and make that your primary key, and don't make that field editable by the user. This guarantees you always have access to the record that you want to update.
Generally speaking it's bad practice to attempt to modify the primary key in a database the way you're trying to do it.

You can register a ValueChangeListener on the component you're interested in using:
<p:column headerText="Description">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{exec.name}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{exec.name}">
<f:valueChangeListener binding="#{keyChangedListener}"/>
<f:ajax/>
</h:inputText>
</f:facet>
</p:cellEditor>
</p:column>
keyChangeListener will correspond to an implementation of ValueChangeListener and we're using <f:ajax/> here to ensure that the valueChanged event is fired on the textbox. Otherwise the listener will not be notified. Your listener should look something like:
#ManagedBean(name="keyChangedListener")
#ViewScoped
public class KeyChangeListener implements ValueChangeListener{
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException{
Object oldValue = event.getOldValue(); //get the old value
Object newValue = event.getNewValue(); //get the new value
}
I'm using the #ViewScopedhere as advised by the JSF Spec, to avoid unwanted side effects.

Related

How to get the pre edited value from a dataTable column in Primefaces?

When clicking on the edit button in PrimeFaces I want my listener to get the new value of the column as well as the old one. I am currently only getting the new value:
public void onLicenseEdit(RowEditEvent event) {
selectedItemLicense = (ItemLicense) event.getObject();
}
This is my xhtml:
<p:dataTable id="licenses" var="license"
value="#{itemShowView.itemReference.lastVersionItemLicenses}"
emptyMessage="#{messages['common.emptymessage']}"
class="itemLicensesTable"
selection="itemShowView.selectedLicense"
editable="true">
<p:ajax event="rowEdit" update="#(.itemLicensesTable)" listener="#{itemShowView.onLicenseEdit}" />
<f:facet name="header">
<p:column headerText="#{messages['license.licensenumber']}">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{license.licensePK.licenseNumber}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{license.licensePK.licenseNumber}" />
</f:facet>
</p:cellEditor>
</p:column>
...
<p:column>
<p:rowEditor />
</p:column>
...
</p:dataTable>
Please help. Thanks in advance.
Thank you for your comment. I modified the code using valueChangeListener. This is my solution:
<f:facet name="input">
<p:inputText value="#{itemLicense.itemLicensePK.licenseNumber}" valueChangeListener="#{itemShowView.onLicenceChange}"/>
</f:facet>
and the Java code:
private ItemLicense selectedItemLicenseForModification;
...
public void onLicenceChange() {
selectedItemLicenseForModification = (ItemLicense) FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("itemLicense");
}

Changing assigned user using p:selectOneMenu

I have been searching for similar issue but I could not find any.
so here is the thing
I am trying to create a web application that deals with HR stuff, like employee requests (Resign, loan, vacation, etc..)
I am using primeface and I have the following problem that I cant figure out.
The thing is I am trying to do is :
1- When user first creates the request and assigns the user and submit the form
the next step is
2- the manager would sees the request and then change the "Person responsible for the request" to a new one using the drop menu in the datatable and I have been trying to solve this problem with no luck.
Here is the dialog script
<h:form id='resignf'>
<p:dialog id='res' header="Resign Request" widgetVar="resign" minHeight="40">
<p:outputLabel value="Employee name" />
<p:inputText value="#{controller.resignName}" required="true" requiredMessage="This field is required" />
<p:outputLabel value="Employee Number" />
<p:inputText value="#{controller.resignEmployeNum}" required="true" />
<p:inputText value="#{controller.resignNationalIDNum}" required="true" />
<p:inputText value="#{controller.resignNotes}" required="true" />
<p:outputLabel for="AssignUser" value="User" />
<p:selectOneMenu id="AssignUser" value="#{controller.assignUser}" style="width:150px" converter="UConverter">
<f:selectItems value="#{controller.usersList}" var="user" itemLabel="#{user.username}"/>
</p:selectOneMenu >
<p:commandButton action="#{controller.createResignRequest()}" onclick="PF('resign').hide();" update="#all"/>
</p:dialog>
And the code is my controller.java file below to create the request in the table
/* Request to resign*/
private List<ResignationRequest> resignList;
private ResignationRequestController rController = new ResignationRequestController();
private String resignName;
private String resignEmployeNum;
private String resignNationalIDNum;
private String ResignNotes;
private int AutoAssignToIDNUM;
/* end of request to resign*/
public void createResignRequest() {
System.out.println("createResignRequest");
ResignationRequest newResign = new ResignationRequest();
newResign.setName(resignName);
newResign.setEmployeeNum(resignEmployeNum);
newResign.setNationalID(resignNationalIDNum);
newResign.setNotes(ResignNotes);
newResign.setUserID(AssignUser);
rController.create(newResign);
resignList = rController.findResignationRequestEntities(); //retrieves all the resigns from the database
}
Now all that is working perfectly, but when I try to change the old user with the new one here I get confused! so far what I have been thinking is I need to find the old user and then switch him, but I could not figure a way to do it using the select list. The script for for changing the "User responsible for the request" below
<p:dataTable id="resignTable1" cellSeparator="true" editMode="cell" editable="true" var="resign" value="#{controller.resignList}" paginator="true" rows="10" rowIndexVar="index1">
<p:ajax id="aj" event="cellEdit" listener="#{controller.editUser(user)}" update="resignTable1"/>
<p:column headerText="Employee number">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.employeeNum}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.employeeNum}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="name">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.name}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.name}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Request Number">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.id}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.id}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="User responsible for the request">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.userID}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.userID}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Comments">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.notes}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.notes}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Send the request to the next employee">
<p:selectOneMenu id="AssignUser" value="#{controller.assignUser}" style="width:150px" converter="UConverter" onchange="submit();">
<f:selectItems value="#{controller.usersList}" var="user" itemLabel="#{user.username}" actionListener="#{controller.editRequestStep(resign)}" >
</f:selectItems>
</p:selectOneMenu >
In my controller file
public void editRequestStep(ResignationRequest r) {
System.out.println("Edit resign");
try {
System.out.println("Edit resign");
rController.edit(r);
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
I tried to get as much as I could from the code but I have a lot of stuff that I am not sure if I should submit. I tried ajax
NOTE: I am using mySQL, apache tomcat in case if it matters.
Solved it.
public void editRequestStep(ResignationRequest r) {
System.out.println("Edit resign " + EditAssignUser +" this is userthig" + r.getName());
try {
System.out.println("Edit resign");
r.setUserID(EditAssignUser);
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
<p:selectOneMenu id="AssignUser" value="#{controller.editAssignUser}" style="width:150px" converter="UConverter">
<p:ajax listener="#{controller.editRequestStep(resign)}" update="#all"/>
<f:selectItems value="#{controller.usersList}" var="user" itemLabel="#{user.username}" >
</f:selectItems>
I did not notice that I used the variable assignUser 2 times, which actually missed me up. So what I did is I created new Users variable called "editAssignUser" then in my controller I just set the user look at the code below
public void editRequestStep(ResignationRequest r) {
System.out.println("Edit resign " + EditAssignUser +" this is userthig" + r.getName());
try {
System.out.println("Edit resign");
r.setUserID(EditAssignUser);
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}

JSF <h:inputText> / <h:outputText> not rendering according to boolean value

I have a <h:dataTable> that is populated from an Entity class and displays different products. I want to be able to click a <h:commandLink> and edit row that the link belongs to. I have structured it mostly the same way as this nice example and article at mkyong.
The table (with some columns excluded):
<h:form>
<h:dataTable id="gnomeTable" value="#{gnome.productList}"
var="item"
styleClass="gnomeTable"
headerClass="gnomeTableHeader"
rowClasses="gnomeTableOddRow,gnomeTableEvenRow"
bgcolor="#F1F1F1" border="10" cellspacing="2"
rules="all" >
<f:facet name="header">
<h:outputText value="List of available gnomes for sale" />
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="GnomeID" />
</f:facet>
<h:outputText value="#{item.id}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{item.name}" rendered="#{not item.editable}"></h:outputText>
<h:inputText value="#{item.name}" rendered="#{item.editable}"></h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Available"/>
</f:facet>
<h:outputText value="#{item.available}" rendered="#{not item.editable}"></h:outputText>
<h:inputText value="#{item.available}" rendered="#{item.editable}"></h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Edit"/>
</f:facet>
<h:commandLink value="Edit" action="#{gnome.editAction(item)}" rendered="#{not item.editable}" />
</h:column>
</h:dataTable>
<h:commandButton value="Save Changes" action="#{gnome.saveAction}" />
</h:form>
The Bean methods:
public String saveAction() {
for (Gnome g : productList) {
g.setEditable(false);
}
return null;
}
public String editAction(Gnome gnome) {
gnome.setEditable(true);
return null;
}
The property boolean editable in the entity class is annotated as #Transient since it's not a part of the persistant data and I don't want the entity manager to touch it:
#Transient
private boolean editable;
I thought this would result in the boolean variable being set to true when the Edit-button is clicked, the row re-renders with the fields now as <h:inputText>, but nothing happens. I have debugged it and made sure that the variable is set to true, which it is.
I also found this SO question that I thought perhaps could be something similar to the problem I am experiencing. The difference though is that a refresh of the page doesn't change anything.
What am I missing?
Edit 1:
In the first version of this question I had by mistake pasted the wrong code. The one that is included now is my current code, that in theory should work but does not.
Edit 2:
Initialization of productList, where Gnome is the entity class.
private List<Gnome> productList = new ArrayList<>();
public List<Gnome> getProductList() {
productList = gnomeFacade.findAll();
return productList;
}
public void setProductList(List<Gnome> productList) {
this.productList = productList;
}
After testing your example, the only possible error is that you are using a RequestScoped bean. In order to make it work, you need at least ViewScoped or SessionScoped. Ortherwise, the productList changed content is lost at every requests (button action).
According to the edit, the second mistake is how data is took. You need to load your data somewhere else than getter like this :
#PostConstruct
public void init()
{
productList = gnomeFacade.findAll();
}
public List<Gnome> getProductList()
{
return productList;
}
Ortherwise, at every actions your list is reset.

Bind property of property - JSF2 - <h:dataTable>

(Please view edit down below)
As a continuation of the code from this SO question, I am now trying to save the modified values of a <h:dataTable> using the persistance of the entity class.
I have a dataTable as follows:
<h:form>
<h:dataTable id="userTable" value="#{admin.customerList}"
var="c"
binding="#{admin.customerTable}"<!-- Not sure if this is necessary -->
styleClass="gnomeTable"
headerClass="gnomeTableHeader"
rowClasses="gnomeTableOddRow,gnomeTableEvenRow"
bgcolor="#F1F1F1" border="10" cellspacing="2"
rules="all" >
<f:facet name="header">
<h:outputText value="All registered customers" />
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="User ID" />
</f:facet>
<h:outputText value="#{c.id}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Username"/>
</f:facet>
<h:outputText value="#{c.username}" rendered="#{not c.editable}"></h:outputText>
<h:inputText value="#{c.username}" rendered="#{c.editable}"></h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Email"/>
</f:facet>
<h:outputText value="#{c.email}" rendered="#{not c.editable}"></h:outputText>
<h:inputText value="#{c.email}" rendered="#{c.editable}"></h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Banned?"/>
</f:facet>
<h:selectBooleanCheckbox value="#{c.banned}" rendered="#{not c.editable}" disabled="true"></h:selectBooleanCheckbox>
<h:selectBooleanCheckbox value="#{c.banned}" rendered="#{c.editable}" disabled="false"></h:selectBooleanCheckbox>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Admin?"/>
</f:facet>
<h:selectBooleanCheckbox value="#{c.admin}" rendered="#{not c.editable}" disabled="true"></h:selectBooleanCheckbox>
<h:selectBooleanCheckbox value="#{c.admin}" rendered="#{c.editable}" disabled="false"></h:selectBooleanCheckbox>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Edit"/>
</f:facet>
<h:commandLink value="Edit" action="#{admin.editAction(c)}" rendered="#{not c.editable}" />
<h:commandButton value="Save" action="#{admin.saveAction(c)}" rendered="#{c.editable}" />
</h:column>
</h:dataTable>
</h:form>
The table is populated successfully, and when I click the edit button in the last column, I am able to modify the values of the columns. If I then click the Save button of the last column, #{admin.saveAction(c)}, is called with the parameter c, which is the customer that I believe I have just modified.
The method is called, though no changes are being made.
saveAction(Customer c) looks like this:
public String saveAction() {
for (Customer customer : customerList) {
System.out.println("Trying to update customer with ID: " + customer.getId());
customerFacade.updateCustomer(customer);
}
return null;
}
and updateCustomer(Customer c) looks like this:
public void updateCustomer(Customer c) {
em.merge(c);
}
Either I have not understood how the variable c corresponds to a Customer object in the list of customers customerList, or I have not successfully bound it to it's property. Simply put, no changes are made to the Customer object when I modify any of the fields.
Is there a way to bind the properties of each Customer object c in customerList, so that the values are being updated when the fields in the datatable connected to the current object is being changed?
Must I use a listener that monitors if a field is being modified, and then calls the setter of the objects property?
Edit:
Summarize of the changes to the code that I've made.
The main issue seems to be the fact that the customer object (entity class) doesn't get modified when I modify the field values in the datatable.
The saveAction method now look as follows
public String saveAction() {
for (Customer customer : customerList) {
System.out.println("Trying to update customer with ID: " + customer.getId());
customerFacade.updateCustomer(customer);
}
return null;
}
The bean class:
#ManagedBean(name = "admin")
#ViewScoped
public class AdminBean implements Serializable {
#EJB
CustomerFacade customerFacade;
private List<Customer> customerList = new ArrayList<>();
#PostConstruct
public void init() {
customerList = customerFacade.findAll();
}
...
So, the main question is now only why my values aren't being updated?

Saving data after editing primefaces datatable to database in integration of hibernate spring jsf and primefaces

i want to edit a row in primfaces datatable. i am using integration of jsf hibernate spring primefaces. but i have following error.
javax.el.ELException: /personel.xhtml #60,83 listener="#{personelMB.updatePersonel(personel.personel_id)}": org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
personelmanagedbean:
#ManagedBean(name="personelMB")
#ViewScoped
public class PersonelBean implements Serializable{
private static final long serialVersionUID = 1L;
#ManagedProperty(value="#{PersonelService}")
IPersonelService personelservice;
List<Personel> personelList;
private int personel_id;
private String pname;
private String pfamily;
private String paddress;
private String pphone;
//getter and setter
public void updatePersonel(int personel_id){
Personel personel=(Personel)personelservice.getPersonelId(personel_id);
getPersonelservice().updatePersonel(personel);
}
}
personel.xhtml:
<h:form prependId="false">
<p:dataTable id="pdataTable" var="personel" value="#{personelMB.personelList}" rowKey="#{personelMB.personel_id}" editable="true"
>
<p:ajax event="rowEdit" update="#this" listener="#{personelMB.updatePersonel(personel.personel_id)}"/>
<f:facet name="header">
اطلاعات پرسنل
</f:facet>
<p:column>
<f:facet name="header">
شماره پرسنلی
</f:facet>
<h:outputText value="#{personel.personel_id}" />
<f:facet name="footer">
کدملی
</f:facet>
</p:column>
<p:column headerText="نام">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{personel.pname}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{personel.pname}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="نام خانوادگی">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{personel.pfamily}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{personel.pfamily}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="آدرس">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{personel.paddress}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{personel.paddress}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="تلفن">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{personel.pphone}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{personel.pphone}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="ويرايش">
<p:rowEditor />
</p:column>
<f:facet name="footer">
تعداد رکورد#{fn:length(personelMB.getPersonelList())} میباشد.
</f:facet>
</p:dataTable>
</h:form>
personelservice:
#Transactional(readOnly=true)
public class PersonelService implements IPersonelService{
IPersonelDao personeldao;
//getter and setter
#Transactional(readOnly=false)
#Override
public void updatePersonel(Personel personel) {
getPersoneldao().updatePersonel(personel);
}
personeldao:
public class PersonelDao implements IPersonelDao {
private SessionFactory sessionFactory;
//getter and setter
#Override
public void updatePersonel(Personel personel) {
getSessionFactory().getCurrentSession().update(personel);
}
please help me how to edit my data table and save it in database.
This is a problem of fetching a Hibernate entity in one Transaction and attempting to update it in another Transaction with a different Hibernate session.
To do this properly you need to fetch and then update your Personel object in the same Transaction. This means that you need to have one #Transactional business logic method that you call from your ManagedBean that does both.
In IPersonelService implementation class:
#Transactional
public void updatePersonel(int personel_id, String pname, String pfamily ...){
Personel personel = personelDao.getPersonel(personel_id);
personel.setPName(pname);
....
getSessionFactory().getCurrentSession().saveOrUpdate(personel);
}
This will seperate, your business logic from your presentation logic as well as make all of your database calls behind a single Transaction.

Categories