JSF Datatable does not show all List fields(columns) - jsf

I want to display a table in JSF:DataTAble. I successfully retrived table from database to List of users type where "users" is my pojo class. Now I am having problem with displaying it on data table some of the columns like FName, LName, Pwd, displayed correctly but when i add other coulmns like "Note" "Email" it gives me this error
javax.servlet.ServletException: /dt.xhtml: Property 'Email' not found on type in.ali.pojo.users
javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
root cause
javax.el.ELException: /dt.xhtml: Property 'Email' not found on type in.ali.pojo.users
com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:88)
com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
com.sun.faces.renderkit.html_basic.TableRenderer.renderRow(TableRenderer.java:385)
com.sun.faces.renderkit.html_basic.TableRenderer.encodeChildren(TableRenderer.java:162)
javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:894)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:443)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
here is my xhtml page
<?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://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:dataTable value="#{pretechDataTableBean.user}" var="users">
<h:column>
<f:facet name="header">Name</f:facet>
#{users.FName}
</h:column>
<h:column>
<f:facet name="header">Email</f:facet>
#{users.Email}
</h:column>
<h:column>
<f:facet name="header">Password</f:facet>
#{users.pwd}
</h:column>
</h:dataTable>
</h:body>
</html>
here is my PretechDataTableBean which i used for retrieving data from DB
package com.pretech;
import in.ali.pojo.users;
import in.ali.util.HibernateUtil;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
/**
*
* #author vinod
*/
#ManagedBean
#RequestScoped
public class PretechDataTableBean {
public PretechDataTableBean() {
}
public List<users> getUser() {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
List<users> users =null;
try
{
transaction = session.beginTransaction();
users = session.createQuery("from users").list();
}
catch(Exception e)
{
e.printStackTrace();
}
finally{
session.close();
}
return users;
}
}
This is my users pojo
package in.ali.pojo;
// Generated Sep 28, 2013 3:55:01 PM by Hibernate Tools 4.0.0
/**
* users generated by hbm2java
*/
public class users implements java.io.Serializable {
private long UserId;
private String FName;
private String LName;
private long UserTypeId;
private String UserName;
private String Email;
private String Pwd;
private String Note;
private boolean IsActive;
public users() {
}
public users(long UserId) {
this.UserId = UserId;
}
public users(long UserId, String FName, String LName, long UserTypeId,
String UserName, String Email, String Pwd, String Note,
boolean IsActive) {
this.UserId = UserId;
this.FName = FName;
this.LName = LName;
this.UserTypeId = UserTypeId;
this.UserName = UserName;
this.Email = Email;
this.Pwd = Pwd;
this.Note = Note;
this.IsActive = IsActive;
}
public long getUserId() {
return this.UserId;
}
public void setUserId(long UserId) {
this.UserId = UserId;
}
public String getFName() {
return this.FName;
}
public void setFName(String FName) {
this.FName = FName;
}
public String getLName() {
return this.LName;
}
public void setLName(String LName) {
this.LName = LName;
}
public long getUserTypeId() {
return this.UserTypeId;
}
public void setUserTypeId(long UserTypeId) {
this.UserTypeId = UserTypeId;
}
public String getUserName() {
return this.UserName;
}
public void setUserName(String UserName) {
this.UserName = UserName;
}
public String getEmail() {
return this.Email;
}
public void setEmail(String Email) {
this.Email = Email;
}
public String getPwd() {
return this.Pwd;
}
public void setPwd(String Pwd) {
this.Pwd = Pwd;
}
public String getNote() {
return this.Note;
}
public void setNote(String Note) {
this.Note = Note;
}
public boolean isIsActive() {
return this.IsActive;
}
public void setIsActive(boolean IsActive) {
this.IsActive = IsActive;
}
}

The fields must be likeThis instead of LikeThis. Just change your JSF code to
<h:dataTable value="#{pretechDataTableBean.user}" var="user">
<h:column>
<f:facet name="header">Name</f:facet>
#{user.fName}
</h:column>
<h:column>
<f:facet name="header">Email</f:facet>
#{user.email}
</h:column>
<h:column>
<f:facet name="header">Password</f:facet>
#{user.pwd}
</h:column>
</h:dataTable>
And update the field names in your User class to follow the proper Java Bean naming convention.
public class users implements java.io.Serializable {
private long userId;
private String fName;
private String lName;
private long userTypeId;
private String userName;
private String email;
private String pwd;
private String note;
private boolean isActive;
//constructor, getters and setters
}
Apart from this, there are other bugs in your current design:
You must not have business logic in the getters of your managed bean, instead take advantage of the #PostConstruct method to initialize the necessary data to be used.
Since this bean looks that should stay alive while the user stays in the same view, it will be better to decorate it as #ViewScoped instead of #RequestScoped.
Use proper names for your classes and fields. For example, if you have a List<Something> field, name your variable somethingList or similar in order that the code is self-explanatory.
From these, you can change your managed bean to:
#ManagedBean
#ViewScoped
public class PretechDataTableBean {
private List<users> userList;
public PretechDataTableBean() {
}
#PostConstruct
public void init() {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
List<users> users =null;
try
{
transaction = session.beginTransaction();
users = session.createQuery("from users").list();
}
catch(Exception e)
{
e.printStackTrace();
}
finally{
session.close();
}
return users;
}
public List<users> getUserList() {
return this.user;
}
}
Since the field changed its name in the managed bean, you should edit it accordingly in the respective view:
<h:dataTable value="#{pretechDataTableBean.userList}" var="user">
Related info:
Why JSF calls getters multiple times
Communication in JSF 2: Managed bean scopes
JavaBeans API Specification , more specifically, Section 7: Properties.

Related

JSF EL Expressions and Java beans

I have a JSF project and I am trying to create a login page, I have managed to get the username and password from the database and validate them, my project has a Java bean, managed bean and DAO classes, when the user successfully logs in, I would like to print Hello Mr.
< h:outputLabel value="#{mBLogin.user.firstName}" /> the Hello Mr. is printing but the name is not, although when testing my DAO class I'm printing the name to the console without any problem! Can someone advice what I am doing wrong?
My managed bean class:
#ManagedBean
#SessionScoped
public class MBLogin {
User user = new User();
LoginDAO loginDao = new LoginDAO();
public String validteStudent() {
boolean valid = loginDao.validateStudent(user.getUserId(), user.getPassword());
if (valid) {
user.getFirstName();
HttpSession session = SessionUtils.getSession();
session.setAttribute("username", user);
return "admin";
} else {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,
"Incorrect Username and Passowrd", "Please enter correct username and Password"));
return "login";
}
}
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
My Java Bean class:
#Table(name = "students_info")
public class User {
#Column(name = "std_record_id")
private int id;
#Column(name = "std_id")
private String userId;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "web_password")
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
My DAO class :
public class LoginDAO {
static JKPlainDataAccess dataAccess = JKDataSourceFactory.getPlainDataAccess();
User user;
public boolean validateStudent(String userName, String password) {
user = dataAccess.executeQueryAsSingleObject(User.class, "id,userId,firstName,lastName,password",
"SELECT std_record_id, std_id, first_name, family_name, web_password From students_info WHERE std_id=? and web_password=?",
userName, password);
JK.print("getAllEmployeeRecords() : ", user);
if(user != null) {
System.out.println(user.getFirstName());
System.out.println(user.getLastName());
return true;
}
return false;
}
public static void main(String[] args) {
LoginDAO a = new LoginDAO();
a.validateStudent("200663042001", "1234");
}
}
my xhtml page after the login page:
<ui:composition template="/WEB-INF/layouts/default.xhtml">
<ui:define name="content">
WELCOME Mr. <h:outputLabel value="#{mBLogin.user.firstName}" />
AND <h:outputLabel value="#{mBLogin.user.lastName}" />
</ui:define>
</ui:composition>
When validating, you seem to put the user as the session attribute without assigning it to the Managed Bean field:
session.setAttribute("username", user);
So either assign it also to the instance user variable or simply use:
<ui:composition template="/WEB-INF/layouts/default.xhtml">
<ui:define name="content">
WELCOME Mr. <h:outputLabel value="#{username.firstName}" />
AND <h:outputLabel value="#{username.lastName}" />
</ui:define>
</ui:composition>
Update
I would suggest changing your service method to:
public User validateStudent(..)
where you actually return the queried user instead of setting it in the DAO..
And thus you would change the ManagedBean method to:
public String validteStudent() {
User validatedUser = loginDao.validateStudent(user.getUserId(), user.getPassword());
if (validatedUser != null) {
this.user = validatedUser;
HttpSession session = SessionUtils.getSession();
session.setAttribute("username", user);
....

Passing parameters in JSF and PrimeFaces

I am studying a PrimeFaces AutoComplete demo. I shortenied it from the full showcase demo. http://www.primefaces.org/showcase/ui/input/autoComplete.xhtml
AutoCompleteBean.java
#ManagedBean
public class AutoCompleteBean {
private Query query;
private List<Query> queries = new ArrayList<Query>();
#PostConstruct
public void init() {
queries.add(new Query(0, "Afterdark", "afterdark"));
queries.add(new Query(1, "Afternoon", "afternoon"));
queries.add(new Query(2, "Afterwork", "afterwork"));
queries.add(new Query(3, "Aristo", "aristo"));
}
public List<Query> completeQuery(String query) {
List<Query> filteredQueries = new ArrayList<Query>();
for (int i = 0; i < queries.size(); i++) {
Query skin = queries.get(i);
if(skin.getName().toLowerCase().contains(query)) {
filteredQueries.add(skin);
}
}
return filteredQueries;
}
public void onItemSelect(SelectEvent event) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Item Selected", event.getObject().toString()));
}
public Query getQuery() {
return query;
}
public void setQuery(Query query) {
this.query = query;
}
}
Query.java
public class Query {
private int id;
private String displayName;
private String name;
public Query() {}
public Query(int id, String displayName, String name) {
this.id = id;
this.displayName = displayName;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return name;
}
}
I omitted a Convert class, which I think is not that relevant.
search.xhtml
<h:form>
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" cellpadding="5">
<p:autoComplete id="queryPojo" value="#{autoCompleteView.query}"
completeMethod="#{autoCompleteView.completeQuery}" var="query"
itemLabel="#{query.displayName}" itemValue="#{query}"
converter="queryConverter" forceSelection="true" />
<p:commandButton value="search" oncomplete="PF('dlg').show()"/>
</h:panelGrid>
</h:form>
I have three questions for this:
1) completeMethod="#{autoCompleteView.completeQuery}": completeQuery method is called without passing a parameter, but it's defined as completeQuery(String query). How does this work?
2) value="#{autoCompleteView.query}". Query is an object defined in AutoCompleteBean. How can this Query object take user input string as its value? Usually InputText's value is good for taking user's input, which is a String value.
3) Can I still add an attribute "action=..." to the p:autoComplete componenet?
The converter class that you omitted here plays the real game.... Lets see your questions
As you see converter class overrides 2 methods
getAsString and getAsObject
1)the value
completeMethod="#{autoCompleteView.completeQuery}
gets refactred to
autoCompleteView.completeQuery(autoCompleteView.query);
as you can find to string method in Query class.
2).as converter is defined for autocomplete it calls getAsString method to render on screen. when selected getAsObject method is called to convert string value to object(Query).
3)you can use ajax select event
<p:ajax event="select" listener="#{autoCompleteView.someMethod}">
or call a remoteCommand by onSelect attribute in p:autoComplete
<p:autoComplete id="queryPojo" value="#{autoCompleteView.query}" onSelect="someRemoteCommand();"
completeMethod="#{autoCompleteView.completeQuery}" var="query"
itemLabel="#{query.displayName}" itemValue="#{query}"
converter="queryConverter" forceSelection="true" />
<p:remoteCommand name="someRemoteCommand" update="queryPojo" actionListener="#{autoCompleteView.execute}" />

Error : javax.el.PropertyNotFoundException: Target Unreachable, 'null' returned null [duplicate]

This question already has answers here:
Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable
(18 answers)
Closed 7 years ago.
I got this error below when I was running my JSF page.
javax.el.PropertyNotFoundException: Target Unreachable, 'null' returned null..
Warning: /createStaff.xhtml #33,125
value="#{staffBean.staff.firstName}": Target Unreachable, 'null'
returned null javax.el.PropertyNotFoundException: /createStaff.xhtml
#33,125 value="#{staffBean.staff.firstName}": Target Unreachable,
'null' returned null
I don't get why I will run into the error when I use value="#{staffBean.staff.firstName}". There is no problem when I use the value="#{staffBean.userName}" and value="#{staffBean.passWord}" above.
This is my createStaff.xhtml
<?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"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Create Staff</title>
</h:head>
<h:body>
<f:view>
<h:form>
<p:panel id ="panel" header="Staff Creation">
<p:messages id="msgs" />
<h:panelGrid columns="3" columnClasses="label, value">
<h:outputText value="Username: *" />
<p:inputText id="username" value="#{staffBean.userName}" required="true" label="Username">
</p:inputText>
<p:message for="username" />
<h:outputLabel for="pwd1" value="Password 1: *" />
<p:password id="pwd1" value="#{staffBean.passWord}" match="pwd2" label="Password 1" required="true" feedback="true" />
<p:message for="pwd1" />
<h:outputLabel for="pwd2" value="Password 2: *" />
<p:password id="pwd2" value="#{staffBean.passWord}" label="Password 2" required="true" feedback="true" />
<p:message for="pwd2" />
<h:outputText value="First name: *" />
<p:inputText id="firstname" value="#{staffBean.staff.firstName}" required="true" label="Username">
</p:inputText>
<p:message for="firstname" />
<h:outputText value="Last name: *" />
<p:inputText id="lastname" value="#{staffBean.staff.lastName}" required="true" label="Username">
</p:inputText>
<p:message for="lastname" />
<h:outputText value="Last name: *" />
<p:selectOneRadio id="genderconsole" value="#{staffBean.staff.gender}" required="true">
<f:selectItem itemLabel="Male" itemValue="Male" />
<f:selectItem itemLabel="Female" itemValue="Female" />
</p:selectOneRadio>
<p:message for="genderconsole" />
<p:commandButton value="Create Staff"
id="ajax"
update="panel">
</p:commandButton>
</h:panelGrid>
</p:panel>
</h:form>
</f:view>
</h:body>
</html>
This is my StaffBean.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package managedbean;
import entities.Staff;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import sessionBean.staffSessionBeanLocal;
#Named(value = "staffBean")
#SessionScoped
//#ViewScoped
public class StaffBean implements Serializable {
#EJB
private staffSessionBeanLocal staffSession;
private String userName;
private String passWord;
private String loginStatus;
private Staff staff;
...........
////Code removed
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 String getLoginStatus() {
return loginStatus;
}
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public Staff getStaff() {
return staff;
}
public void setStaff(Staff staff) {
this.staff = staff;
}
}
This is my staff entity.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package entities;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
#Entity
public class Staff extends User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String imageURL;
#ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
private List<Roles> roles = new ArrayList<Roles>();
#Override
public Long getId() {
return id;
}
#Override
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Staff)) {
return false;
}
Staff other = (Staff) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entities.Staff[ id=" + id + " ]";
}
public String getImageURL() {
return imageURL;
}
public void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
public List<Roles> getRoles() {
return roles;
}
public void setRoles(List<Roles> roles) {
this.roles = roles;
}
}
This is my User class which Staff class extends from.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package entities;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
#MappedSuperclass
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String password;
private Timestamp joinDate;
private String userType;
private String gender;
private String email;
private String contactNo;
private String firstName;
private String lastName;
private Timestamp dOB;
private String address;
private String accountStatus;
private int numOfFailLogin;
private String maritalStatus;
private String activationCode;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entities.User[ id=" + id + " ]";
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Timestamp getJoinDate() {
return joinDate;
}
public void setJoinDate(Timestamp joinDate) {
this.joinDate = joinDate;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContactNo() {
return contactNo;
}
public void setContactNo(String contactNo) {
this.contactNo = contactNo;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Timestamp getdOB() {
return dOB;
}
public void setdOB(Timestamp dOB) {
this.dOB = dOB;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAccountStatus() {
return accountStatus;
}
public void setAccountStatus(String accountStatus) {
this.accountStatus = accountStatus;
}
public String getMaritalStatus() {
return maritalStatus;
}
public void setMaritalStatus(String maritalStatus) {
this.maritalStatus = maritalStatus;
}
public int getNumOfFailLogin() {
return numOfFailLogin;
}
public void setNumOfFailLogin(int numOfFailLogin) {
this.numOfFailLogin = numOfFailLogin;
}
public String getActivationCode() {
return activationCode;
}
public void setActivationCode(String activationCode) {
this.activationCode = activationCode;
}
}
You have no property firstName in your entity staff
UPDATE:
Looks like your staffobject is null add:
#PostConstruct
public void init() {
staff = new Stuff();
}
The error suggests that when the "firstName" is being accessed, it cannot be reached. So the "Staff" has not been constructed yet.
Add a method to your managed bean, this will resolve the issue.
#PostConstruct
public void init() {
staff= new Staff ();
}
For better understanding of why you should do it that way and not
Staff staff = new Staff();
JSF - what is the difference between #PostConstruct and direct method call from constructor?

No View in JSP Example

I have a problem with the view in JSP (Java EE)
Only the heading is shown.
My Code:
Entitiy Class (Konto);
#Entity
public class Konto implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable=false)
#NotNull(message="Kontonummer muss angegenben werden")
#Pattern(regexp="[0-9][0-9][0-9][0-9]")
private String kontonummer;
#Column(nullable=false)
#NotNull(message="Kontostand muss angegeben werden")
#DefaultValue(value="0.0")
private Double ktostd;
#Column(nullable=false)
#DecimalMin(value="0", message="Der Zins muss zw. 0 und 10 % liegen")
#DecimalMax(value="0.1", message="Der Zins muss zw. 0 und 10 % liegen")
private Double habenZins;
#ManyToOne
#JoinColumn(nullable=false)
#NotNull(message="Besitzer muss angegeben werden")
private Besitzer besitzer;
public Besitzer getBesitzer() {
return besitzer;
}
public void setBesitzer(Besitzer besitzer) {
this.besitzer = besitzer;
}
public Double getHabenZins() {
return habenZins;
}
public void setHabenZins(Double habenZins) {
this.habenZins = habenZins;
}
public String getKontonummer() {
return kontonummer;
}
public void setKontonummer(String kontonummer) {
this.kontonummer = kontonummer;
}
public Double getKtostd() {
return ktostd;
}
public void setKtostd(Double ktostd) {
this.ktostd = ktostd;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Konto)) {
return false;
}
Konto other = (Konto) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "at.korn.entity.NewEntity[ id=" + id + " ]";
}
}
Kontolist.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h1>Kontoliste</h1>
<h:form>
<h:dataTable value="#{kontolist.kontos}" var="konto">
<h:column>
<f:facet name="header">
<h:outputText value="Kontonummer"></h:outputText>
</f:facet>
<h:outputText value="#{konto.kontonummer}"></h:outputText>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
KontoList Controller:
#ManagedBean
#SessionScoped
public class Kontolist {
#EJB
KontoFacadeLocal kontofacade;
private List<Konto> kontos;
/** Creates a new instance of kontolist */
public Kontolist() {
kontos = kontofacade.findAll();
}
public KontoFacadeLocal getKontofacade() {
return kontofacade;
}
public void setKontofacade(KontoFacadeLocal kontofacade) {
this.kontofacade = kontofacade;
}
public List<Konto> getKontos() {
setKontos(kontofacade.findAll());
return kontos;
}
public void setKontos(List<Konto> kontos) {
this.kontos = kontos;
}
}
Problem:
Only the header is shown. In the source from the browser is the same code without html injection (like value="#{konto.kontonummer}")
First of all, that is not a JSP file. That's a Facelets (XHTML) file. JSP is an ancient view technology. Facelets is the successor of JSP.
So, your concrete problem is that the JSF tags are not been parsed? That can happen when the request URL did not match the URL pattern of the FacesServlet as definied in web.xml. If it is for example *.jsf, then you'd need to change the request URL from
http://localhost:8080/contextname/kontolist.xhtml
to
http://localhost:8080/contextname/kontolist.jsf
However, much better is to just change the URL pattern of the FacesServlet to *.xhtml so that you do not need to fiddle with virtual URLs and introduce security constraints to prevent the enduser from accidently or awaringly viewing the raw *.xhtml pages.
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
See also:
What is the difference between creating JSF pages with .jsp or .xhtml or .jsf extension
Unrelated to the concrete problem, you've by the way a NullPointerException bug in your code. Replace
public Kontolist() {
kontos = kontofacade.findAll();
}
by
#PostConstruct
public void init() {
kontos = kontofacade.findAll();
}
Injected dependencies are namely not available during construction. The getter and setter for the kontofacate are also entirely superfluous, I'd remove them to prevent future confusion and abuse.

Changes not reflected in JPA entities after updating in h:dataTable

I am working with Eclipse and Glassfish 3.0. Pretty new to this technology although I have done similar things before. Very simple really got a datatable bound to a backing bean. Add methods and remove methods i have covered - the problem lies with the update method I am calling. I cannot seem to see the changes being picked up in the component (HtmlInputText) never mind passing the data back to the table.
My code for the data table is below (and the jsf page)
<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">
<f:loadBundle basename="resources.application" var="msg"/>
<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>
<body>
<h:form id="mainform">
<h:dataTable var="row" border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">
<f:facet name="header">
<h:outputText value="Categories"/>
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText id="input1" value="#{row.description}" valueChangeListener="#{row.inputChanged}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText id="id" value="#{row.id}"/>
</h:column>
<h:column>
<h:commandButton value="Delete" type="submit" action="#{beanCategory.remove}">
<f:setPropertyActionListener target="#{beanCategory.selectedcategory}" value="#{row}"/>
</h:commandButton>
<h:commandButton value="Save" action="#{beanCategory.update}"
>
<f:setPropertyActionListener
target="#{beanCategory.selectedcategory}" value="#{row}" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:inputText id="text1"></h:inputText> <h:commandButton action="#{beanCategory.addCategory}" value="Add" type="submit" id="submitbutton">
</h:commandButton>
<br/><br/>
Messages
<h:messages></h:messages><br /><br />
</h:form>
</body>
</html>
Backing Bean is here
package net.bssuk.timesheets.controller;
import java.io.Serializable;
import java.util.List;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.context.FacesContext;
import javax.persistence.*;
import net.bssuk.timesheets.model.Category;
#javax.inject.Named("beanCategory")
#javax.enterprise.context.SessionScoped
public class BeanCategory implements Serializable {
private List<Category> collection;
private EntityManagerFactory emf;
private EntityManager em;
private int selectedid;
private Category selectedcategory;
private HtmlDataTable datatable;
private static final long serialVersionUID = 1L;
public BeanCategory() {
// TODO Auto-generated constructor stub
System.out.println("Bean Constructor");
}
public String addCategory() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Changed - Now attempting to add");
System.out.println("Ready to do cateogory");
Category category = new Category();
FacesContext context = FacesContext.getCurrentInstance();
UIInput input = (UIInput) context.getViewRoot().findComponent(
"mainform:text1");
String value = input.getValue().toString();
if (value != null) {
category.setDescription(input.getValue().toString());
} else {
category.setDescription("Was null");
}
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(category);
tx.commit();
em.close();
emf.close();
// return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
}
return "return.html";
}
public String remove() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Getting Collection");
this.em = this.emf.createEntityManager();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("Number found is " + this.selectedid);
if (selectedcategory != null) {
System.out.println("removing "+selectedcategory.getId()+" - " +selectedcategory.getDescription());
EntityTransaction tx = em.getTransaction();
tx.begin();
System.out.println("Merging..");
this.em.merge(selectedcategory);
System.out.println("removing...");
this.em.remove(selectedcategory);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "index.xhtml";
}
}
public String update() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Update Getting Collection");
Category category = (Category) getDatatable().getRowData();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("PHASE ID="+context.getCurrentPhaseId().toString());
if (category != null) {
// DESCRIPTION VALUE BELOW IS ALWAYS OLD VALUE (IE DATA IN DATABASE)
System.out.println("updating "+category.getId()+" - " +category.getDescription());
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.merge(category);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public void setCollection(List<Category> collection) {
this.collection = collection;
}
public List<Category> getCollection() {
// this.emf=Persistence.createEntityManagerFactory("timesheets1");
// System.out.println("Getting Collection");
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
this.em = this.emf.createEntityManager();
Query query = this.em.createNamedQuery("findAll");
this.collection = query.getResultList();
return this.collection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setSelectedid(int id) {
this.selectedid=id;
}
public void setSelectedcategory(Category selectedcategory) {
this.selectedcategory = selectedcategory;
}
public HtmlDataTable getDatatable() {
return datatable;
}
public void setDatatable(HtmlDataTable datatable) {
this.datatable = datatable;
}
public Category getSelectedcategory() {
return selectedcategory;
}
}
My Mapped entity for JPA is here
package net.bssuk.timesheets.model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the CATEGORIES database table.
*
*/
#Entity
#Table(name="CATEGORIES")
#NamedQuery(name="findAll", query = "SELECT c from Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private String description;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
public Category() {
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
}
OK - Updated my code to follow example. I have tried to incorporate an EJB into the scenario as follows
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
#Stateless
public class CategoryEJB implements CategoryEJBRemote {
#PersistenceContext(unitName="timesheets1")
private EntityManager em;
#Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
#Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
#Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
#Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
My EJB is below
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
#Stateless
public class CategoryEJB implements CategoryEJBRemote {
#PersistenceContext(unitName="timesheets1")
private EntityManager em;
#Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
#Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
#Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
#Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
Can anyone suggest if this sort of looks ok? Or have I completely lost the plot with it!
Look,
<h:dataTable var="row" border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">
and
public List<Category> getCollection() {
// this.emf=Persistence.createEntityManagerFactory("timesheets1");
// System.out.println("Getting Collection");
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
this.em = this.emf.createEntityManager();
Query query = this.em.createNamedQuery("findAll");
this.collection = query.getResultList();
return this.collection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
You're loading the list inside a getter method. This is a very bad idea. A getter should solely be an access point to the bean property, not to do some business job. A getter can be called multiple times during bean's life. The DB will be hit on every call and the local collection property which was been updated by JSF during form submit will be overwritten again at a later point. This makes no sense.
Do the business job in the (post)constructor method or action(listener) methods. Definitely not in a getter. Here's a minimum kickoff example with some code improvements:
<h:dataTable value="#{bean.categories}" var="category">
<h:column>
<h:inputText value="#{category.description}" />
</h:column>
<h:column>
<h:outputText value="#{category.id}" />
</h:column>
<h:column>
<h:commandButton value="Delete" action="#{bean.delete(category)}" />
<h:commandButton value="Save" action="#{bean.update(category)}" />
</h:column>
</h:dataTable>
<h:inputText value="#{bean.newCategory.description}" />
<h:commandButton value="Add" action="#{bean.add}" />
(note that passing arguments in EL is supported since EL 2.2 (part of Servlet 3.0), Glassfish 3 is a Servlet 3.0 container, so it should definitely support it when web.xml is properly declared conform Servlet 3.0 spec)
with
#ManagedBean
#ViewScoped // Definitely don't use session scoped. I'm not sure about CDI approach, so here's JSF example.
public class Bean {
private List<Category> categories;
private Category newCategory;
#EJB
private CategoryService categoryService;
#PostConstruct
public void init() {
categories = categoryService.list();
newCategory = new Category();
}
public void add() {
categoryService.add(newCategory);
init();
}
public void delete(Category category) {
categoryService.delete(category);
init();
}
public void update(Category category) {
categoryService.update(category);
init();
}
public List<Category> getCategories() {
return categories;
}
public Category getNewCategory() {
return newCategory;
}
}
That should be it. See also:
Why JSF calls getters multiple times
Help understanding JSF's multiple calls to managed bean
<h:dataTable value=#{myBean.xxx}>: getXxx() get called so many times, why?
As I see, you have forgotten the <h:form>. This is very necessary to save inputs.

Resources