I implemented code that allows me to display a dropdown which depends on another. Everything works fine except when I try to retrieve and display the value of the two fields, it raises the following error:
form:parcours : erreur : de validation. la valeur est incrorrecte
in english :
form:parcours : validation error. value is not valid
I am using JSF 2.0, EJB 3.0, JPA 2.0 and PrimeFaces 3.2.
View:
<h:form id="form" >
<!-- <p:growl id="msgs" showDetail="true"/> -->
<h:messages globalOnly="true"/>
<p:growl id="msgs" showDetail="true" />
<p:panel header="Double Combo" style="margin-bottom:10px;">
<h:panelGrid columns="2" cellpadding="5">
<p:selectOneMenu id="countries" value="#{plansEtude.selectedDep}">
<f:selectItem itemLabel="Select Country" itemValue="" />
<f:selectItems value="#{plansEtude.depList}" var="c" itemLabel="#{c.nomDepFr}" itemValue="#{c.id}"/>
<p:ajax update="parcours,parcoursTab"
listener="#{plansEtude.handleDepChange}" />
</p:selectOneMenu>
<p:selectOneMenu id="parcours" value="#{plansEtude.selectedParcours}" >
<f:convertNumber maxFractionDigits="0"/>
<f:selectItem itemLabel="Select City" itemValue="" />
<f:selectItems value="#{plansEtude.parcoursList}" var="ct" itemLabel="#{ct.designParcours}" itemValue="#{ct.id}" />
</p:selectOneMenu>
</h:panelGrid>
<p:separator />
<p:commandButton value="Submit" update="msgs" actionListener="#{plansEtude.displayLocation}" id="btnSubmit"/>
</p:panel>
Controller :
#EJB
private DepartementFacade departementFacade;
#EJB
private ParcoursFacade parcoursFacade;
private List<Departement> depList;
private List<Parcours> parcoursList;
private Integer selectedDep;
private Integer selectedParcours;
public PlansEtude() {
}
public DepartementFacade getDepartementFacade() {
return departementFacade;
}
public void setDepartementFacade(DepartementFacade departementFacade) {
this.departementFacade = departementFacade;
}
public ParcoursFacade getParcoursFacade() {
return parcoursFacade;
}
public void setParcoursFacade(ParcoursFacade parcoursFacade) {
this.parcoursFacade = parcoursFacade;
}
public List<Departement> getDepList() {
depList = getDepartementFacade().findAll();
return depList;
}
public void setDepList(List<Departement> depList) {
this.depList = depList;
}
public List<Parcours> getParcoursList() {
return parcoursList;
}
public void setParcoursList(List<Parcours> parcoursList) {
this.parcoursList = parcoursList;
}
public Integer getSelectedDep() {
return selectedDep;
}
public void setSelectedDep(Integer selectedDep) {
this.selectedDep = selectedDep;
}
public Integer getSelectedParcours() {
return selectedParcours;
}
public void setSelectedParcours(Integer selectedParcours) {
this.selectedParcours = selectedParcours;
}
public void handleDepChange(){
if(selectedDep !=null && !selectedDep.equals(""))
parcoursList = parcoursFacade.findParcoursInDep(selectedDep);
else
parcoursList = new ArrayList<Parcours>();
}
public void handleParcoursChange(){
}
public void displayLocation() {
String monMessage="Departement :" + selectedDep + ", Parcours : " + selectedParcours;
FacesMessage msg = new FacesMessage("Selected", monMessage);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
parcoursFacade :
public List<Parcours> findParcoursInDep(Integer dep){
Query query = em.createNamedQuery("Parcours.findParcoursInDep");
query.setParameter("dep", dep);
return (List<Parcours>)query.getResultList();
}
Named query :
#NamedQuery(name = "Parcours.findParcoursInDep", query = "SELECT p FROM Parcours p WHERE p.departementid.id = :dep"),
Remove the <f:convertNumber maxFractionDigits="0"/> from your parcours dropdown. It makes no sense. It would only convert the number to BigDecimal while you need an Integer.
Another possible cause is that the #{plansEtude.parcoursList} has incompatibly changed during the form submit because the managed bean is request scoped. You need to make sure that the managed bean is placed in at least the view scope, so that the parcoursList is preserved for the submit.
Related
I am working on richfaces4,
when i am trying to edit details from a popup panel,i am not able to save/update the edited details into my database.can anybody help me to solve this.
My XHTML Page is as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:t="http://myfaces.apache.org/tomahawk">
<h:head>
</h:head>
<h:body>
<h:form id="dboperatorform">
<t:saveState value="#{dBOperator.empList}"></t:saveState>
<t:saveState value="#{dBOperator.edit}"></t:saveState>
<t:saveState value="#{dBOperator.rowNum}"></t:saveState>
<t:saveState value="#{dBOperator.employee}"></t:saveState>
<rich:panel style="width:1345px">
<f:facet name="header">
<h:outputText value="Search Panel" />
</f:facet>
<h:panelGrid id="searchPanel" columns="6">
<h:column>
<h:outputLabel value="First Name:" />
</h:column>
<h:column>
<h:inputText value="#{dBOperator.first_Name}" />
</h:column>
<h:column>
<h:outputLabel value="Last Name:" />
</h:column>
<h:column>
<h:inputText value="#{dBOperator.last_name}" />
</h:column>
<h:column>
<a4j:commandButton value="Search" action="#{dBOperator.search}"
render="richtable">
</a4j:commandButton>
</h:column>
<h:column>
</h:column>
</h:panelGrid>
</rich:panel>
<br />
<a4j:commandButton value="Add" action="#{dBOperator.editdetails}"
execute="#this" style="width:30px;height:30px;"
oncomplete="#{rich:component('popup1')}.show();"
render="richtable popup1">
<f:setPropertyActionListener target="#{dBOperator.edit}"
value="false"></f:setPropertyActionListener>
</a4j:commandButton>
<p></p>
<rich:dataTable value="#{dBOperator.employees}" var="emp"
id="richtable" cellpadding="0" cellspacing="0" style="width:1349px"
reRender="richtable" iterationStatusVar="it"
noDataLabel="No Records Found!" rows="5">
<rich:column>
<f:facet name="header">#</f:facet>
<h:outputText value="#{it.index}" />
</rich:column>
<rich:column>
<f:facet name="header">
<a4j:commandLink value="First Name"
action="#{dBOperator.sortByFirstName}" render="richtable"></a4j:commandLink>
</f:facet>
<h:outputText value="#{emp.first_Name}" />
</rich:column>
<rich:column>
<f:facet name="header">Last Name</f:facet>
<h:outputText value="#{emp.last_name}" />
</rich:column>
<rich:column>
<f:facet name="header">Edit</f:facet>
<a4j:commandButton image="images/edit.png"
action="#{dBOperator.editdetails}" execute="#this"
style="width:30px;height:30px;"
oncomplete="#{rich:component('popup1')}.show();"
render="richtable popup1">
<f:setPropertyActionListener target="#{dBOperator.rowNum}"
value="#{it.index}"></f:setPropertyActionListener>
<f:setPropertyActionListener target="#{dBOperator.edit}"
value="true"></f:setPropertyActionListener>
</a4j:commandButton>
</rich:column>
<f:facet name="footer">
<rich:dataScroller for="richtable" align="right"
status="ajaxProcessIcon" renderIfSinglePage="false" fastStep="5"
fastControls="auto" />
</f:facet>
</rich:dataTable>
<rich:popupPanel id="popup1" minHeight="300"
minWidth="300">
<t:saveState value="#{dBOperator.edit}"></t:saveState>
<t:saveState value="#{dBOperator.rowNum}"></t:saveState>
<f:facet name="header">
<h:outputText value="Simple popup panel" />
</f:facet>
<f:facet name="controls">
<h:outputLink
onclick="#{rich:component('popup1')}.hide(); return false;"
reRender="richtable">X</h:outputLink>
</f:facet>
<rich:toolbar itemSeparator="line" width="100%" id="qawq">
<rich:toolbarGroup location="left">
<h:outputText
value="#{dBOperator.edit?'Employee Edit':'Employee Add'}" />
</rich:toolbarGroup>
</rich:toolbar>
<h:panelGrid id="CancelGrid" columns="2" width="100%">
<rich:column width="30%" style="border:none;">
<h:outputText value="First Name" style="font-weight: bold;" />
<font class="star" color="red">*</font>
</rich:column>
<rich:column width="70%" style="border:none;">
<h:inputText value="#{dBOperator.employee.first_Name}"
style="width:100%" id="abbr" />
</rich:column>
<rich:column width="30%" style="border:none;">
<h:outputText value="Last Name" style="font-weight: bold;" />
<font class="star" color="red">*</font>
</rich:column>
<rich:column width="70%" style="border:none;">
<h:inputText value="#{dBOperator.employee.last_name}"
style="width:100%" id="abbr1" />
</rich:column>
</h:panelGrid>
<a4j:commandButton value="#{dBOperator.edit?'Edit':'Save'}"
action="#{dBOperator.savedetails}"
oncomplete="#{rich:component('popup1')}.hide();"
onclick="validateFields();"></a4j:commandButton>
</rich:popupPanel>
<script type="text/javascript">
function validateFields() {
alert('came inside validateFields');
var fn=document.getElementById('dboperatorform:abbr');
alert('fn '+fn.value);
var ln=document.getElementById('dboperatorform:abbr1');
alert('ln '+ln.value);
}
</script>
</h:form>
</h:body>
</html>
My Bean Class is as follows
package com.richfaces.db;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.management.MBeanServer;
import javax.swing.SortOrder;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.comparator.NameComparator;
import com.comparator.NameCompartor1;
import com.richfaces.Employee;
public class DBOperator {
String id;
String first_Name;
String last_name;
String fName;
String lName;
Employee employee;
int rowNum;
boolean edit;
Boolean search=Boolean.FALSE;
Boolean status = Boolean.FALSE;
List<Employee> list = new ArrayList<Employee>();
List<Employee> empList = new ArrayList<Employee>();
public boolean isEdit() {
return edit;
}
public void setEdit(boolean edit) {
this.edit = edit;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public int getRowNum() {
return rowNum;
}
public void setRowNum(int rowNum) {
this.rowNum = rowNum;
}
public String getFirst_Name() {
return first_Name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setFirst_Name(String first_Name) {
this.first_Name = first_Name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public List<Employee> getEmployees() {
System.out.println("hghhghhhhh");
String sql2="";
Query query = null;
String sql1 = "from Employee as emp where id is not null ";
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sf = cfg.buildSessionFactory();
Session sess = sf.openSession();
sess.beginTransaction();
if(status==false && search==false) {
System.out.println("Normal Query +++++++++++++++++++++++ " + sql1);
String appendedQuery = createCriteriaQuery(sql1);
System.out.println("Appended Query ++++++++++++++++++++++++ "
+ appendedQuery);
query = sess.createQuery(appendedQuery);
}else if(status==true && search==true) {
System.out.println("came inside when search and status is true");
String appendedQuery = createCriteriaQuery(sql1);
System.out.println("Appended Query ++++++++++++++++++++++++ "
+ appendedQuery);
query = sess.createQuery(appendedQuery);
}else if(status==false && search==true) {
System.out.println("came inside when search is true and status is false");
String appendedQuery = createCriteriaQuery(sql1);
System.out.println("Appended Query ++++++++++++++++++++++++ "
+ appendedQuery);
query = sess.createQuery(appendedQuery);
}else if(status==true && search==false) {
System.out.println("came inside when search is false and status is true");
String appendedQuery = createCriteriaQuery(sql1);
System.out.println("Appended Query ++++++++++++++++++++++++ "
+ appendedQuery);
query = sess.createQuery(appendedQuery);
}
list = query.list();
/*if (status) {
Collections.sort(list, new NameComparator());
} else {
Collections.sort(list, new NameCompartor1());
}*/
System.out.println(list.size());
this.empList = list;
return list;
}
public String createCriteriaQuery(String query) {
StringBuffer sb = new StringBuffer(query);
if (getFirst_Name() != null && !(getFirst_Name().equals(""))) {
sb.append(" and emp.first_Name='" + first_Name + "'");
}
if (getLast_name() != null && !(getLast_name().equals(""))) {
sb.append(" and emp.last_name='" + last_name + "'");
}
if(this.status) {
sb.append(" order by emp.first_Name desc");
}else {
sb.append(" order by emp.first_Name");
}
System.out.println(sb.toString());
return sb.toString();
}
public void editdetails() {
if (edit) {
System.out.println("rownum is " + rowNum);
System.out.println(empList.size());
employee = (Employee) empList.get((rowNum));
System.out.println(employee.getFirst_Name() + "\t"
+ employee.getLast_name() + "\t" + employee.getId());
System.out.println("end of edit details method");
} else {
employee = new Employee();
}
}
public List<Employee> getEmpList() {
return empList;
}
public void setEmpList(List<Employee> empList) {
this.empList = empList;
}
public void savedetails() {
System.out.println("came into savedetails");
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sf = cfg.buildSessionFactory();
Session sess = sf.openSession();
if(this.edit) {
System.out.println("EMPLOYEE DETAILS in IF "+getEmployee().getFirst_Name()+"\t"+getEmployee().getLast_name());
System.out.println("came inside if when edit is true");
sess.update(employee);
}else {
System.out.println("came inside else when edit is false");
System.out.println("EMPLOYEE DETAILS in ELSE "+getEmployee().getFirst_Name()+"\t"+getEmployee().getLast_name());
sess.save(employee);
}
}
public void search() {
System.out.println("came into search method");
search = true;
}
public void refreshData(ActionEvent ae) {
System.out.println("came into refreshdata");
getEmployees();
}
public void sortByFirstName() {
System.out.println("came inside sortByFirstName");
if (!status) {
status = Boolean.TRUE;
} else {
status = Boolean.FALSE;
}
//status=Boolean.TRUE;
getEmployees();
}
public String getfName() {
return fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getlName() {
return lName;
}
public void setlName(String lName) {
this.lName = lName;
}
}
My Entity class is as follows:
package com.richfaces;
import java.io.Serializable;
public class Employee implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
String id;
String first_Name;
String last_name;
public String getFirst_Name() {
return first_Name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setFirst_Name(String first_Name) {
System.out.println("came inside setter method of firstname");
this.first_Name = first_Name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
System.out.println("came inside setter method of lastname");
this.last_name = last_name;
}
}
if your exact problem is not seeing #{dBOperator.savedetails} action triggered:
i couldn't figure out the root cause yet, but this problem should be fixed by adding modal="true" to the rich:popupPanel attributes and moving validateFields() function into the popup panel. i faced this problem many times and saw it working properly on different popup components, including this one.
I want to develop a JSF Page which lets user edit a Employee from database. I loaded list of all employees in h:selectOneMenu. and second thing i want that with valueChangeEvent employee detail should be loaded in corresponding h:inputText. but nothing happens with every valueChangeEvent. So, where is the problem in codes.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<div id="hdr">
<h1>Vinweb Services</h1>
<hr/>
</div>
;
<div id="mnu" style="height: 50px; width: auto; background: skyblue;">
<h:form>
<h:commandLink value="Home" action="index"/>
<h:outputText value=" "/>
<h:commandLink value="Create" action="create"/>
<h:outputText value=" "/>
<h:commandLink value="View" action="view"/>
<h:outputText value=" "/>
<h:commandLink value="Edit" action="edit"/>
</h:form>
</div>
<div id="cnt">
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="Select an Employee"/>
<h:selectOneMenu value="#{esb.empName}" onchange="submit()" valueChangeListener="#{esb.loadEmployeeDetail}">
<f:selectItems value="#{esb.employeeList}"/>
</h:selectOneMenu>
<h:outputLabel value="Employee Code"/>
<h:inputText value="#{esb.empCode}" required="true"/>
<h:outputLabel value="Employee Name"/>
<h:inputText value="#{esb.empName}" required="true"/>
<h:outputLabel value="Joining Date"/>
<h:inputText value="#{esb.joinDate}" required="true">
<f:convertDateTime pattern="MM/yy"/>
</h:inputText>
<h:outputLabel value="Salary"/>
<h:inputText value="#{esb.salary}" required="true"/>
<h:commandButton value="Update" action="#{esb.updateEmployeeDetail}"/>
</h:panelGrid>
</h:form>
</div>
</h:body>
</html>
Backing Bean:
package ems.bean;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import javax.annotation.Resource;
import javax.faces.event.ValueChangeEvent;
import javax.sql.DataSource;
#Named(value = "esb")
#SessionScoped
public class EmployeeServiceBean implements Serializable {
#Resource(name = "JPA4A")
private DataSource ds;
// Member Declaration
private String empCode;
private String empName;
private Date joinDate;
private long salary;
private ArrayList empList;
// Service Code Segment
// This method will publish all emloyees in table to selectOneMenu
public ArrayList getEmployeeList() throws SQLException{
empList = new ArrayList();
Connection con = ds.getConnection();
try{
Statement stmt = con.createStatement();
ResultSet rslt = stmt.executeQuery("SELECT empName FROM Employee");
while(rslt.next()){
empList.add(rslt.getString("empName"));
}
}
catch(SQLException se) {
throw new SQLException();
}
finally{
con.close();
}
return empList;
}
// This method should load selected empoyee's details in inputText fields
public void loadEmployeeDetail(ValueChangeEvent evt) throws SQLException{
String emp = evt.getNewValue().toString();
Connection con = ds.getConnection();
try{
Statement stmt = con.createStatement();
String qry = "SELECT * FROM Employee WHERE empName = '"+emp+"'";
ResultSet rslt = stmt.executeQuery(qry);
rslt.next();
this.empCode = rslt.getString("empCode");
this.empName = rslt.getString("empName");
this.joinDate = rslt.getDate("joinDate");
this.salary = rslt.getLong("salary");
}
catch(SQLException se) {
se.printStackTrace();
}
finally{
con.close();
}
}
public void updateEmployeeDetail() throws SQLException{
Connection con = ds.getConnection();
try{
Statement stmt = con.createStatement();
boolean rs = stmt.execute("UPDATE Employee SET empCode='"+empCode+"', empName='"+empName+"', joinDate='"+joinDate+"', salary="+salary);
}
catch(SQLException se) {
throw new SQLException();
}
finally{
con.close();
}
}
// Property Getter & Setter code segment
public String getEmpCode() {
return empCode;
}
public void setEmpCode(String empCode) {
this.empCode = empCode;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Date getJoinDate() {
return joinDate;
}
public void setJoinDate(Date joinDate) {
this.joinDate = joinDate;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
}
The valueChangeListener is the wrong tool for the job.
You're here doing a onchange="submit()" which submits the entire form, including those required fields which in turn caused validation errors which in turn failed to reach your attention because you don't have any <h:message(s)> for them. If you have placed a <h:messages/> inside the form, or have paid more love and attention to server logs, you should have been notified of those required="true" validation errors.
You need <f:ajax listener>.
Replace
<h:selectOneMenu value="#{esb.empName}" onchange="submit()" valueChangeListener="#{esb.loadEmployeeDetail}">
<f:selectItems value="#{esb.employeeList}"/>
</h:selectOneMenu>
by
<h:selectOneMenu value="#{esb.empName}">
<f:selectItems value="#{esb.employeeList}"/>
<f:ajax listener="#{esb.loadEmployeeDetail}" render="#form" />
</h:selectOneMenu>
and replace
public void loadEmployeeDetail(ValueChangeEvent evt) throws SQLException{
String emp = evt.getNewValue().toString();
// ...
}
by
public void loadEmployeeDetail() throws SQLException{
String emp = empName; // You can also just use `empName` directly.
// ...
}
See also:
When to use valueChangeListener or f:ajax listener?
I am facing an issue with h:selectOneRadio's valueChangeListener="#{user.loadYesNo}"
(I use Mojarra 2-0-8 on Tomcat-7) .
If I remove both the panelGrid enclosing the 'h:selectOneRadio', then the value change litener is getting fired.
View:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head><title> Starting JSF</title></h:head>
<h:body>
<h:form>
<h:panelGrid column="2">
<h:outputLabel>User Name</h:outputLabel>
<h:inputText id="loginName" value="#{user.userName}"></h:inputText>
<h:outputLabel>Password</h:outputLabel>
<h:inputSecret id="loginPassword" value="#{user.password}"></h:inputSecret>
</h:panelGrid>
<h:commandButton value="Submit" action ="#{user.validateLogin}">
<f:ajax execute="#form" render="yesNoRadioGrid message"></f:ajax>
</h:commandButton>
<h:panelGrid>
<h:outputText id ="message" value="#{user.message}"></h:outputText>
</h:panelGrid>
<h:panelGrid id="yesNoRadioGrid">
<h:panelGrid columns="2" rendered="#{user.yesNoRadioGridFlag}">
<h:outputText id ="otherLbl" value="Select Yes or No"></h:outputText>
<h:selectOneRadio id="yesNoRadio" value ="#{user.yesNoRadio}" valueChangeListener="#{user.loadYesNo}">
<f:selectItem itemValue="1" itemLabel="YES"></f:selectItem>
<f:selectItem itemValue="0" itemLabel="NO"></f:selectItem>
<f:ajax event="change" execute="#form" render="userDetailsGrid "></f:ajax>
</h:selectOneRadio>
</h:panelGrid>
</h:panelGrid>
<h:message for ="yesNoRadio"> </h:message>
<h:panelGrid id="userDetailsGrid">
<h:panelGrid columns="2" rendered="#{user.userDetailsGridFlag}">
<h:outputLabel>Name :</h:outputLabel>
<h:inputText id="customerName" value="#{user.customerName}"></h:inputText>
<h:outputLabel>Salary: </h:outputLabel>
<h:inputText id="customerSalary" value="#{user.customerSalary}"></h:inputText>
</h:panelGrid>
</h:panelGrid>
</h:form>
</h:body>
</html>
Model+Controller mingled:
package com.jsf.test;
import javax.faces.bean.*;
import javax.faces.event.ValueChangeEvent;
#ManagedBean
public class User {
private String userName;
private String password;
private String message;
private String customerName;
private String customerSalary;
private Integer yesNoRadio;
private Boolean yesNoRadioGridFlag;
private Boolean userDetailsGridFlag;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getCustomerSalary() {
return customerSalary;
}
public void setCustomerSalary(String customerSalary) {
this.customerSalary = customerSalary;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getYesNoRadio() {
return yesNoRadio;
}
public void setYesNoRadio(Integer yesNoRadio) {
this.yesNoRadio = yesNoRadio;
}
public Boolean getUserDetailsGridFlag() {
return userDetailsGridFlag;
}
public void setUserDetailsGridFlag(Boolean userDetailsGridFlag) {
this.userDetailsGridFlag = userDetailsGridFlag;
}
public Boolean getYesNoRadioGridFlag() {
return yesNoRadioGridFlag;
}
public void setYesNoRadioGridFlag(Boolean yesNoRadioGridFlag) {
this.yesNoRadioGridFlag = yesNoRadioGridFlag;
}
public String validateLogin() {
if (userName.equals("xyz") && password.equals("xyz")) {
message = "Login Success";
yesNoRadioGridFlag = true;
} else {
yesNoRadioGridFlag = false;
message = "Login Failure";
}
return message;
}
public void loadYesNo(ValueChangeEvent evt){
Integer yesNoValue = (Integer)evt.getNewValue();
setYesNoRadio(yesNoValue);
userDetailsGridFlag = true;
}
}
You need to put the bean in the view scope in order to retain the underlying condition of the rendered attribute for the subsequent requests.
#ManagedBean
#ViewScoped
public class User {
// ...
}
Unrelated to the concrete problem, the valueChangeListener is intended to be used whenever you want to have a hook on the server side value change event which allows you to have both the old value and the new value at your hands. For example, to log an event. It's not intended to perform business actions based on the change. For that you should be using the listener attribute of <f:ajax> instead.
So, replace
<h:selectOneRadio id="yesNoRadio" value ="#{user.yesNoRadio}" valueChangeListener="#{user.loadYesNo}">
<f:selectItem itemValue="1" itemLabel="YES"></f:selectItem>
<f:selectItem itemValue="0" itemLabel="NO"></f:selectItem>
<f:ajax event="change" execute="#form" render="userDetailsGrid "></f:ajax>
</h:selectOneRadio>
with
<h:selectOneRadio id="yesNoRadio" value ="#{user.yesNoRadio}">
<f:selectItem itemValue="1" itemLabel="YES"></f:selectItem>
<f:selectItem itemValue="0" itemLabel="NO"></f:selectItem>
<f:ajax execute="#form" listener="#{user.loadYesNo}" render="userDetailsGrid"></f:ajax>
</h:selectOneRadio>
and remove the ValueChangeEvent attribute from the method.
In my .xhtml file, I have the following SelectOneMenu component:
<ui:define name="formContent">
<h:selectOneMenu value="#{mrBean.itemCategoryID}">
<f:ajax render="abc def" execute="#this" listener="#{mrBean.getListOfItems}"></f:ajax>
<f:selectItem itemLabel="Choose one .." itemValue="0" noSelectionOption="true" />
<f:selectItems value="#{mrBean.itemCategories}" var="ic"
itemLabel="#{ic.name}" itemValue="#{ic.id}" />
</h:selectOneMenu>
<h:panelGrid id="abc" columns="3" border="1">
<h:outputText style="font-weight: bold" value="Name"/>
<h:outputText style="font-weight: bold" value="Producer" />
<h:outputText />
</h:panelGrid>
<h:panelGroup id="def" >
<ui:repeat value="#{mrBean.items}" var="i">
<h:form id="BuyItemForm">
<h:panelGrid columns="3" border="1">
<h:outputText style="font-weight: normal" value="#{i.name}" />
<h:outputText style="font-weight: normal" value="#{i.producer.name}" />
<h:commandButton value="Buy" actionListener="#{mrBean.buyItem}" >
<f:param name="itemID" value="#{i.id}" />
</h:commandButton>
</h:panelGrid>
</h:form>
</ui:repeat>
</h:panelGroup>
</ui:define>
When I open the page, it can load normally with the menu populated properly. However, when I choose 1 of the option, I ran into the following error:
SEVERE: javax.faces.component.UpdateModelException: javax.el.ELException: /partner/BuyItem.xhtml #53,81 value="#{mrBean.itemCategoryID}": Can't set property 'itemCategoryID' on class 'managedBean.MrBean' to value 'null'.
...
Caused by: javax.el.ELException: /partner/BuyItem.xhtml #53,81 value="#{mrBean.itemCategoryID}": Can't set property 'itemCategoryID' on class 'managedBean.MrBean' to value 'null'.
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:139)
at javax.faces.component.UIInput.updateModel(UIInput.java:818)
... 47 more
Caused by: java.lang.IllegalArgumentException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.el.BeanELResolver.setValue(BeanELResolver.java:381)
at com.sun.faces.el.DemuxCompositeELResolver._setValue(DemuxCompositeELResolver.java:255)
at com.sun.faces.el.DemuxCompositeELResolver.setValue(DemuxCompositeELResolver.java:281)
at com.sun.el.parser.AstValue.setValue(AstValue.java:197)
at com.sun.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:286)
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:131)
... 48 more
EDIT: this is my bean with getListOfItems function:
#ManagedBean
#ViewScoped
public class MrBean {
#EJB
private PartnerBeanLocal partnerBean;
#ManagedProperty(value="0")
private long itemCategoryID;
private List<ItemState> items;
...
public void getListOfItems() {
try {
System.out.println(itemCategoryID); // I never saw this line printed out
ArrayList data = partnerBean.getInfo(Constants.GET_LIST_OF_ITEMS, itemCategoryID);
int result = ((Integer) data.get(0)).intValue();
if (result == Constants.STATUS_SUCCESSFUL) items = (List<ItemState>) data.get(1);
else if (result == Constants.STATUS_NOT_FOUND) FacesContext.getCurrentInstance().getExternalContext().redirect("HomePage.xhtml");
} catch (IOException ex) {
Logger.getLogger(MrBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
...
// Getters and Setters
...
public long getItemCategoryID() {
return itemCategoryID;
}
public void setItemCategoryID(long itemCategoryID) {
this.itemCategoryID = itemCategoryID;
}
public List<ItemState> getItems() {
return items;
}
public List<ItemState> setItems(List<ItemState> items) {
this.items = items;
}
...
}
I'd be very grateful if someone could give me an advice on how to tackle this problem.
EDIT 2: Thanks everyone for helping me! The problem was that I stupidly forgot to put the <f:ajax> tag inside a <h:form> tag.
Here is what I tried:
#ManagedBean
#ViewScoped
public class MrBean implements Serializable {
#ManagedProperty(value="0")
private long itemCategoryID;
private List<ItemCategory> itemCategories;
#PostConstruct
public void init() {
this.itemCategories = new ArrayList<ItemCategory>();
this.itemCategories.add(new ItemCategory("Item1", 1));
this.itemCategories.add(new ItemCategory("Item2", 2));
this.itemCategories.add(new ItemCategory("Item3", 3));
}
public void getListOfItems() {
System.out.println(Thread.currentThread().getStackTrace()[1]);
System.out.println("itemCategoryID: " + this.itemCategoryID);
}
public List<ItemCategory> getItemCategories() {
return itemCategories;
}
public void setItemCategories(List<ItemCategory> itemCategories) {
this.itemCategories = itemCategories;
}
public long getItemCategoryID() {
return itemCategoryID;
}
public void setItemCategoryID(long itemCategoryID) {
this.itemCategoryID = itemCategoryID;
}
}
with:
<h:form>
<h:selectOneMenu value="#{mrBean.itemCategoryID}">
<f:ajax execute="#this" listener="#{mrBean.getListOfItems}"></f:ajax>
<f:selectItem itemLabel="Choose one .." itemValue="0" noSelectionOption="true" />
<f:selectItems value="#{mrBean.itemCategories}" var="ic"
itemLabel="#{ic.name}" itemValue="#{ic.id}" />
</h:selectOneMenu>
</h:form>
And it works without any problem.
Might be the version of JSF (EL) you have, or you have problem somewhere else.
The <f:ajax> tag need to be wrapped inside a <h:form> tag.
Seems like some of your item values are null. If you want to accept null, use Long instead of long.
I had the same issue and it was resolved by changing my variable type boolean to Boolean
I face with situation, when item selection from does not change bean property. Method setCurrentOrg() does not invoked.
Managed bean code is:
#ManagedBean(name = "requestAccessBean")
#RequestScoped
public class RequestAccessSection {
private List<AccessRight> accessList;
private List<OrgUnit> orgList;
private String currentOrg;
public String getCurrentOrg() {
return this.currentOrg;
}
public void setCurrentOrg(String currentOrg) {
this.currentOrg = currentOrg;
}
public List<AccessRight> getAccessList() {
if (this.accessList == null) {
this.accessList = returnAccessList();
}
return this.accessList;
}
public void setAccessList(List<AccessRight> accessList) {
this.accessList = accessList;
}
public List<OrgUnit> getOrgList() {
if (this.orgList == null) {
this.orgList = returnOrgList();
}
return this.orgList;
}
public void setOrgList(List<OrgUnit> orgList) {
this.orgList = orgList;
}
public List<OrgUnit> returnOrgList() {
List<OrgUnit> orgList = new ArrayList<OrgUnit>();
orgList = getOfficeBranches();
return orgList;
}
public List<AccessRight> returnAccessList() {
List<AccessRight> accessList = new ArrayList<AccessRight>();
accessList = getAccessList();
return accessList;
}
}
Page is:
<h:form>
<h:selectOneMenu id="orgList" value="# {requestAccessBean.currentOrg}">
<f:selectItem itemLabel="--select--" itemValue="null"></f:selectItem>
<f:selectItems value="#{requestAccessBean.orgList}"
var="org" itemLabel="#{org.ou}" itemValue="#{org.globalid}"/>
<f:ajax event="change" execute="#this" render="accessTable"/>
</h:selectOneMenu>
<h:dataTable var="access" value="#{requestAccessBean.accessList}"
binding="#{requestAccessBean.htmlDataTable}" id="accessTable">
<h:column>
<h:selectOneRadio onclick="radioButton(this);" id="selectAccess"
valueChangeListener="#{requestAccessBean.setSelected}">
<f:selectItem itemValue="null" />
</h:selectOneRadio>
</h:column>
<h:column>
<h:outputText value="#{access.title}" />
</h:column>
</h:dataTable>
<h:form>
Could you please help me?
<h:selectOneMenu id="orgList" value="# {requestAccessBean.currentOrg}">
This is not valid EL. You have a space between # and {. Remove it.
<h:selectOneMenu id="orgList" value="#{requestAccessBean.currentOrg}">