I am using JSF to make an application to keep track of books but I am running into a lack of knowledge at this one page right now.
On startup of this page there is a textfield where you can enter search criteria and a search button. Below this is a message saying there is nothing to display. When the user presses the search button a datatable appears with the data of the relevant books.
The issue is that I don't know how to have no datatable in the beginning and update it everytime the user presses the search button. My code is as follows:
XHTML
<?xml version='1.0' encoding='ISO-8859-1' ?>
<!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">
<h:head>
<title>Library</title>
</h:head>
<h:body>
<h:form>
<h:outputLabel value="Libary"/>
<p/>
<div>
<h:outputLabel value="Search term" />
<h:inputText value="#{booksBean.filter}" />
<h:commandButton value="Search" action="#{booksBean.search}" />
</div>
<div>
<h:dataTable value="#{booksBean.books}" var="item">
<h:column>
<f:facet name="header">
<h:outputLabel value="Book Number"/>
</f:facet>
<h:commandLink value="#{item.bookNumber}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel value="Title"/>
</f:facet>
<h:commandLink value="#{item.title}"/>
</h:column>
</h:dataTable>
</div>
</h:form>
</h:body>
</html>
Java
#ManagedBean
#ViewScoped
public class BooksBean implements Serializable{
private List<Book> books;
private String filter;
/**
* Creates a new instance of BooksBean
*/
public BooksBean () {
books = new ArrayList<Book>();
filter = "";
}
public List<Book> getBooks(){
List<Book> lijst;
list = new ArrayList<Book>();
Database database = new Database();
try {
list = database.getBooks(filter);
this.books = list;
} catch (SQLException ex) {
Logger.getLogger(BooksBean.class.getName()).log(Level.SEVERE, null, ex);
} catch (NamingException ex) {
Logger.getLogger(BooksBean.class.getName()).log(Level.SEVERE, null, ex);
}
return this.books;
}
public void search(){
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
}
Among my searches I couldn't find what functionality I could use, I've tried to use this answer, but I couldn't get it to work. Also I don't know if it then would update everytime a user would press the search button. I just started last week with JSF so I don't know how everything ties together.
Currently I feel like the database function might need to be in the "search" method instead of the getter. But apart from that I am quite lost after spending 2 hours on trying to understand how I would accomplish this. I would greatly appreciate some help.
Related
Please, help me with this, is an exercise proposed by me, which is to make an ecommerce page, surely, payments, everything, but I'm stuck on this problem., since I already use the JSP relatively, I wanted to get into the use of JSF and propose challenges, I know that it can be done directly with the Managed Bean all the interaction with the database, but I would like to add another layer to the exercise, that's where the servlet appears, and make my bean to connect between the JSF, and the Servlet, but it does not stop working, it gives me an error of null .
DP: I would like you to recommend a JavaEE book to me in depth, please, sorry for my bad English, it is not my language.
This is the servlet.
enter code here
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("---------------------Begin-----------------------------------------------");
try {
Section_Model sm = (Section_Model) request.getSession().getAttribute("section_Model");
sm.getSection().setNameAlias(request.getParameter("nameAlias"));
sm.getSection().setCodeSS((Sections) sm.findSpecific(Integer.parseInt(request.getParameter("codeSS"))));
sm.getSection().setVisible(Boolean.getBoolean(request.getParameter("visible")));
sm.create();
request.getRequestDispatcher("WEB-INF/testJSF.xhtml").forward(request, response);
} catch (Exception ex) {
Logger.getLogger(inputSections.class.getName()).log(Level.SEVERE, null, ex);
}
}
this is Managed Bean.
#Named(value = "section_Model")
#SessionScoped
public class Section_Model implements Serializable {
#Inject
private Section_Model section_Model;
#EJB
private SectionsFacadeLocal sectionsFacade;
#PersistenceContext(unitName = "ShopOnlinePU")
private EntityManager em;
#Resource
private javax.transaction.UserTransaction utx;
Sections section;
SectionsJpaController controller;
/**
* Creates a new instance of Section_Model
*/
public Section_Model() {
section= new Sections();
}
public Sections getSection() {
return section;
}
public void setSection(Sections section) {
this.section = section;
}
public void init(){
controller=new SectionsJpaController(utx, em.getEntityManagerFactory());
}
public void create () throws Exception{
init();
controller.create(section);
}
public List<Sections> select_all(){
init();
return controller.findSectionsEntities();
}
public void create2(){
sectionsFacade.create(section);
}
public List<Entity.Sections> subSections (Sections s){
return sectionsFacade.subSection(s);
}
public List<Entity.Sections> findSpecific(int id){
return sectionsFacade.findSpecificS(1);
}
public Collection<Entity.Sections> topSection (){
return sectionsFacade.TopSection();
}
public int countSection(){
return sectionsFacade.count();
}
This is JSF
<?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:c="http://xmlns.jcp.org/jsp/jstl/core">
<h:head>
<title>TEST Title</title>
</h:head>
<h:body>
<form action="inputSections" method="post">
<input type="text" name="nameAlias" title="NameAlias" required="true" requiredMessage="The NameAlias field is required."/>
<input type="text" name="codeSS" title="CodeSS" />
<input type="text" name="visible" title="Visible" />
<input type="submit" value="Ok"/>
</form>
<c:forEach items="#{section_Model.findSpecific(1)}" var="item">
<f:view>
<h:form>
<h:dataTable value="#{section_Model.subSections(item)}" var="items">
<h:column>
<f:facet name="header">
<h:outputText value="CodeS"/>
</f:facet>
<h:outputText value="#{items.codeS}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="NameAlias"/>
</f:facet>
<h:outputText value="#{items.nameAlias}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Visible"/>
</f:facet>
<h:outputText value="#{items.visible}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="CodeSS"/>
</f:facet>
<h:outputText value="#{items.codeSS}"/>
</h:column>
</h:dataTable>
</h:form>
</f:view>
</c:forEach>
</h:body>
</html>
The error is
GRAVE: java.lang.NullPointerException
at View.inputSections.doPost(inputSections.java:79)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:706)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1622)
at `org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:824)`
I'm using JSF 2.2 in a web application and I'm having problems in the view when I use f:validateRegex and fails (because when I use immediate="true" and try to navigate to the same page again, the view isn't updated when I have a new Instance of the object in my backing bean). I was thinking richfaces has a bug (because I'm using jsf and richfaces in my main application) so I made a test code with richfaces and without richfaces (only jsf) to identify where is the error, but in both cases the view fails.
Here is my test code without richfaces (Only jsf):
View:
<?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:c="http://xmlns.jcp.org/jsp/jstl/core">
<h:head>
<title>Mis pruebas con JSF</title>
</h:head>
<h:body>
<h:form id="lista">
<h:panelGrid id="principal">
<h:dataTable value="#{indexBB.personas}" var="persona">
<h:column>
<f:facet name="header">Activo</f:facet>
<h:selectBooleanCheckbox value="#{persona.activo}"></h:selectBooleanCheckbox>
</h:column>
<h:column>
<f:facet name="header">Nombre</f:facet>
<h:outputText value="#{persona.nombre}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Correo</f:facet>
<h:outputText value="#{persona.correo}"></h:outputText>
</h:column>
</h:dataTable>
<h:commandButton action="#{indexBB.crearPersona}" value="Crear Persona">
</h:commandButton>
<h:commandButton action="#{indexBB.activarBoton}" value="Activar Boton">
</h:commandButton>
</h:panelGrid>
</h:form>
<h:form id="crear">
<h:panelGrid id="secundario" rendered="#{indexBB.crear}">
<h:outputText value="Activo?">
</h:outputText>
<h:selectBooleanCheckbox label="Activo" value="#{indexBB.persona.activo}">
</h:selectBooleanCheckbox>
<br></br>
<h:outputText value="Nombre"></h:outputText>
<h:inputText label="Nombre" value="#{indexBB.persona.nombre}">
</h:inputText>
<br></br>
<h:outputText value="Correo"></h:outputText>
<h:inputText label="Nombre" value="#{indexBB.persona.correo}">
<f:validateRegex
pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
</h:inputText>
<br></br>
<h:commandButton action="#{indexBB.guardarPersona}" value="Guardar Persona">
</h:commandButton>
<h:commandButton action="#{indexBB.cancelar}" value="Cancelar" immediate="true">
</h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>
Bean:
package com.kanayet.martin.view.bb;
import com.kanayet.martin.model.entity.Persona;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.faces.view.ViewScoped;
#Named(value = "indexBB")
#ViewScoped
public class indexBB implements Serializable {
private Persona persona;
private List<Persona> personas;
private boolean crear;
/**
* Creates a new instance of indexBB
*/
public indexBB() {
}
#PostConstruct
public void onInit(){
personas = new ArrayList<>();
personas.add(new Persona("Martin", "martin#gmail.com", true));
personas.add(new Persona("Andrea", "andrea#gmail.com", true));
personas.add(new Persona("Camilo", "camilo#gmail.com", true));
personas.add(new Persona("Felipe", "felipe#gmail.com", true));
personas.add(new Persona("David", "david#gmail.com", true));
}
public void activarBoton() {
persona = personas.get(0);
}
public void crearPersona(){
crear = true;
persona = new Persona();
}
public void guardarPersona(){
personas.set(0, persona);
}
public void cancelar(){
}
public Persona getPersona() {
return persona;
}
public void setPersona(Persona persona) {
this.persona = persona;
}
public List<Persona> getPersonas() {
return personas;
}
public void setPersonas(List<Persona> personas) {
this.personas = personas;
}
public boolean isCrear() {
return crear;
}
public void setCrear(boolean crear) {
this.crear = crear;
}
}
Model: (Object)
package com.kanayet.martin.model.entity;
public class Persona {
private String nombre;
private String correo;
private Boolean activo;
public Persona() {
}
public Persona(String nombre, String correo, Boolean activo) {
this.nombre = nombre;
this.correo = correo;
this.activo = activo;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getCorreo() {
return correo;
}
public void setCorreo(String correo) {
this.correo = correo;
}
public Boolean getActivo() {
return activo;
}
public void setActivo(Boolean activo) {
this.activo = activo;
}
}
Here is my test code with richfaces: (Bean and Model are the same)
View:
<?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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Mis pruebas con RichFaces</title>
</h:head>
<h:body>
<h:form id="lista">
<a4j:outputPanel id="principal">
<rich:dataTable id="personas" value="#{indexBB.personas}"
var="persona" rows="50">
<rich:column>
<h:selectBooleanCheckbox label="Activo" value="#{persona.activo}">
</h:selectBooleanCheckbox>
</rich:column>
<rich:column>
<h:outputText value="#{persona.nombre}"></h:outputText>
</rich:column>
<rich:column>
<h:outputText value="#{persona.correo}"></h:outputText>
</rich:column>
</rich:dataTable>
<h:commandButton action="#{indexBB.crearPersona}" value="Crear Persona">
</h:commandButton>
<h:commandButton action="#{indexBB.activarBoton}" value="Activar Boton">
</h:commandButton>
</a4j:outputPanel>
</h:form>
<br></br>
<h:form id="crear">
<a4j:outputPanel id="secundario" rendered="#{indexBB.crear}">
<h:outputText value="Activo?">
</h:outputText>
<h:selectBooleanCheckbox label="Activo" value="#{indexBB.persona.activo}">
</h:selectBooleanCheckbox>
<br></br>
<h:outputText value="Nombre"></h:outputText>
<h:inputText label="Nombre" value="#{indexBB.persona.nombre}">
</h:inputText>
<br></br>
<h:outputText value="Correo"></h:outputText>
<h:inputText label="Nombre" value="#{indexBB.persona.correo}">
<f:validateRegex
pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
</h:inputText>
<br></br>
<h:commandButton action="#{indexBB.guardarPersona}" value="Guardar Persona">
</h:commandButton>
<h:commandButton action="#{indexBB.cancelar}" value="Cancelar" immediate="true">
</h:commandButton>
</a4j:outputPanel>
</h:form>
</h:body>
</html>
The problem is when I click "Crear Persona" button, I write for example "Nombre": Felix and "Correo": Felix and click "Guardar Persona" button so f:validateRegex fails because isn't a valid email, then click "Cancelar" because my final user doesn't know email required value (immediate="true"). Again, click "Crear Persona" button, (new object in my bean) and jsf page isn't updated, the form should be empty but it isn't, in field "Nombre" stills "Felix" value, but in my bean I have a new and empty object without values in its attributes, do you know why?
The problem is with and without richfaces (because I thought the problem could be richfaces, but it isn't), so I don't know why jsf page isn't updated if I have a new object in my bean, I used netbeans debug tool to verify but I'm right, the object that I see in my bean is different (server side new and empty object) but in my JSF page "Nombre" has "Felix" value and I want to know why it happens, and how I can resolve this problem.
Thank you so much.
The problem is that JSF maintains two representations of your model. There is the Java object, IndexBB, but there is also the component tree, the thing that keeps track of UI state.
When you fail validation, the component tree still contains the values entered. (This is a useful feature so that the user can correct the values.) You've used immediate=true to skip validation, but that doesn't reset the component tree values.
In JSF 2.2, you can use resetValues to reset component tree values:
<h:form id="crear">
<h:panelGrid id="secundario" rendered="#{indexBB.crear}">
<h:outputText value="Activo?">
</h:outputText>
<h:selectBooleanCheckbox label="Activo" value="#{indexBB.persona.activo}">
</h:selectBooleanCheckbox>
<br></br>
<h:outputText value="Nombre"></h:outputText>
<h:inputText id="nombreId" label="Nombre" value="#{indexBB.persona.nombre}">
</h:inputText>
<br></br>
<h:outputText value="Correo"></h:outputText>
<h:inputText id="correoId" label="Nombre" value="#{indexBB.persona.correo}">
<f:validateRegex
pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
</h:inputText>
<br></br>
<h:commandButton action="#{indexBB.guardarPersona}" value="Guardar Persona">
</h:commandButton>
<h:commandButton
action="#{indexBB.cancelar}" value="Cancelar">
<f:ajax resetValues="true" render="crear:nombreId crear:correoId"/>
</h:commandButton>
</h:panelGrid>
</h:form>
Changes:
Remove immediate=true.
Add ids to inputs you want to reset.
Add f:ajax to Cancelar button.
Add resetValues property to f:ajax and list your IDs (separate IDs with spaces, not comma).
Make sure your cancelar method actually resets persona -- the code you posted doesn't do this.
If you also want to reset the error messages, add an h:messages to the form, give it an ID, and reset it too.
See also
JSF 2.2: Reset input fields
How to skip validation when a specific button is clicked?
I am trying to make a Java, and JSF project with a MySQL database using Hibernate and PrimeFaces.
Hibernate layer works good(basic CRUD works fine), but after I make basic GUI with Prime Faces and deploy project into Tomcat, server, it returns an error:
Unable to create managed bean DBUserMBean. The following problems were
found: - Bean or property class
com/hibernate/maven/Hibernate_APP/DBUserManagedBean for managed bean
DBUserMBean cannot be found.
Here are all the files in my project:
DBUser
#Entity
public final class DBUser{
private Long id;
private String kolumna1;
private String kolumna2;
private String kolumna3;
private int kolumna4;
#Id
#GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public String toString() {
StringBuffer strBuff = new StringBuffer();
strBuff.append("id :").append(id);
strBuff.append("kolumna1 :").append(kolumna1);
strBuff.append("kolumna2 :").append(kolumna2);
strBuff.append("kolumna3 :").append(kolumna3);
strBuff.append("kolumna4 :").append(kolumna4);
return strBuff.toString();
}
}
DBUserManagedBean
#ManagedBean(name="DBUserManagedBean")
#SessionScoped
public class DBUserManagedBean implements Serializable{
private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(DBUserManagedBean.class);
private static final String SUCCESS = "success";
private static final String ERROR = "error";
private Long id;
private String kolumna1;
private String kolumna2;
private String kolumna3;
private int kolumna4;
private String message;
//getters and setters
public String getMessage() {
StringBuffer strBuff = new StringBuffer();
strBuff.append("id :").append(id);
strBuff.append("kolumna1 :").append(kolumna1);
strBuff.append("kolumna2 :").append(kolumna2);
strBuff.append("kolumna3 :").append(kolumna3);
strBuff.append("kolumna4 :").append(kolumna4);
this.setMessage(strBuff.toString());
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
public String save() {
String result = null;
Session session = HibernateUtil.getSessionFactory().openSession();
DBUser dbuser = new DBUser();
dbuser.setKolumna1(this.getKolumna1());
dbuser.setKolumna2(this.getKolumna2());
dbuser.setKolumna3(this.getKolumna3());
dbuser.setKolumna4(this.getKolumna4());
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(dbuser);
tx.commit();
log.debug("New Record : " + dbuser + ", wasCommitted : " + tx.wasCommitted());
result = SUCCESS;
} catch (Exception e) {
if (tx != null) {
tx.rollback();
result = ERROR;
e.printStackTrace();
}
} finally {
session.close();
}
return result;
}
public List<DBUser> getDBUsers() {
Session session = HibernateUtil.getSessionFactory().openSession();
List<DBUser> dbuserList = session.createCriteria(DBUser.class).list();
return dbuserList;
}
public void reset() {
this.setKolumna1("");
this.setKolumna2("");
this.setKolumna3("");
this.setKolumna4(kolumna4);
}
}
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<managed-bean>
<managed-bean-name>DBUserMBean</managed-bean-name>
<managed-bean-class>com.hibernate.maven.Hibernate_APP.DBUserManagedBean</managed-
bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>pages/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>pages/welcome.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>pages/error.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
index.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"
xmlns:p="http://primefaces.org/ui">
<h:head><title>Hibernate_APP</title></h:head>
<body>
<h:form>
<table>
<tr>
<td><h:outputLabel for="kolumna1" value="kolumna1 :" /></td>
<td><p:inputText id="kolumna1" value="#{DBUserManagedBean.kolumna1}"/></td>
</tr>
<tr>
<td><h:outputLabel for="kolumna2" value="kolumna2 :" /></td>
<td><p:inputText id="kolumna2" value="#{DBUserManagedBean.kolumna2}"/></td>
</tr>
<tr>
<td><h:outputLabel for="kolumna3" value="kolumna3 :" /></td>
<td><p:inputText id="kolumna3" value="#{DBUserManagedBean.kolumna3}"/></td>
</tr>
<tr>
<td><h:outputLabel for="kolumna4" value="kolumna4 :" /></td>
<td><p:inputText id="kolumna4" value="#{DBUserManagedBean.kolumna4}"/></td>
</tr>
<tr>
<td><p:commandButton id="submit" value="Save" action="#
{DBUserManagedBean.save}" ajax="false"/></td>
<td><p:commandButton id="reset" value="Reset" action="#
{DBUserManagedBean.reset}" ajax="false"/></td>
</tr>
</table>
</h:form>
</body>
</html>
welcome.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"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Hibernate_APP</title>
</h:head>
<body>
<h:form>
<h:outputText value="Saved Record is #{DBUserMBean.message}"></h:outputText>
<p:dataTable id="DBUsers" value="#{DBUserMBean.getDBUsers()}" var="DBUser"
style="width: 10%">
<p:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<h:outputText value="#{DBUser.id}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="kolumna1" />
</f:facet>
<h:outputText value="#{DBUser.kolumna1}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="kolumna2" />
</f:facet>
<h:outputText value="#{DBUser.kolumna2}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="kolumna3" />
</f:facet>
<h:outputText value="#{DBUser.kolumna3}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="kolumna4" />
</f:facet>
<h:outputText value="#{DBUser.kolumna4}" />
</p:column>
</p:dataTable>
</h:form>
</body>
</html>
Here is the exception when I try to save something to database trough my form:
WARNING: /pages/index.xhtml #14,87 value="#{DBUserManagedBean.kolumna1}":
Target Unreachable, identifier 'DBUserManagedBean' resolved to null
javax.el.PropertyNotFoundException: /pages/index.xhtml #14,87
value="#{DBUserManagedBean.kolumna1}": Target Unreachable,
identifier 'DBUserManagedBean' resolved to null
You are missing the #Table(name="your Table Name") and also #column annotations.
you remove the method signature of the
value="#{DBUserMBean.getDBUsers()}"
Try this one
value="#{DBUserMBean.getDBUsers}"
As far as my post didn't answer the question, I will only leave the comments to the author's code.
Your managed bean is declared twice, both in faces-config.xml and via #ManagedBean annotation. Though it may look like it produces ambiguity, but faces-config.xml takes precedence over configuration with annotations. Though, to my taste, naming beans twice, and with different names, is a way that might lead to multiple errors. So I would suggest to name the beans either with annotations, or in xml format.
Note though that faces-config.xml is an old-school way of defining managed beans and navigation case outcomes. JSF 2.x has support for annotations and implicit navigation.
By the way, your #Entity class lacks annotations for #Columns and #Table, your backing bean should either have DTO of your entity, of detached entity itself, inserting multiple fileds like you do is a bad practice and your action method should return a navigation case outcome, like welcome, etc.
In the end, do as #BalusC rightfully tells in comment #3, and check the fully qualified name in your xml config file and/or assure that your class file is physically present in your build.
I'm creating a simple search form on page1 and on page2 i will be showing the results.
I'm wondering what the best way to do that with a #ViewScoped backing bean. Previously i've had to use #SessionScope to achieve this.
Page1 - search page:
<h:form id="documents">
<h4 class="dkblue u-case">Documents Search</h4>
<h:outputLabel for="mainNum" value="mainNumber" />
<p:inputText id="mainNum" value="#{documentBacking.document.mainNumber}"/>
<h:outputLabel for="secNum" value="secNumber" />
<p:inputText id="secNum" value="#{documentBacking.document.secNumber}"/>
<h:outputLabel for="formType" value="Form Type" />
<p:inputText id="formType" value="#{documentBacking.document.formType}"/>
<p:commandButton value="Search" action="#{documentBacking.search}" />
<p:commandButton id="clear" value="Clear" type="reset"/>
</h:form>
Page2 - results page:
<p:dataTable value="#{documentBacking.results}" var="results">
<p:column headerText="Main Number">
<h:outputText value="#{results.mainNumber}" />
</p:column>
<p:column headerText="Secondary Number">
<h:outputText value="#{results.secNumber}" />
</p:column>
<p:column headerText="Form Type">
<h:outputText value="#{results.formType}" />
</p:column>
</p:dataTable>
#ViewScoped Backing Bean:
#ManagedBean
#ViewScoped
public class DocumentBacking {
private Document document = new Document();
private List<Document> results = new ArrayList<Document>();
public Document getDocument() {
return document;
}
public void setDocument(Document document) {
this.document = document;
}
public List<Document> getResults() {
return results;
}
public void setResults(List<Document> results) {
this.results = results;
}
public String search() {
results = new ArrayList<Document>();
// dummy data
Document doc = new Document();
doc.setMainNumber("1111");
doc.setSecNumber("2222");
doc.setFormType("OTHER");
doc.setSubFormType("TEST");
results.add(doc);
doc = new Document();
doc.setMainNumber("1234");
doc.setSecNumber("4321");
doc.setFormType("SOMETHING");
doc.setSubFormType("TESTER");
results.add(doc);
return "results.xhtml?faces-redirect=true";
}
}
Use Custom Scope is more reliable for your code. Here is the sample of JSF 2.0 Custom Scope.
I decided to use f:viewParam's and f:event type="preRenderView". This way i have bookmarkable pages via the query string params, and i'm generating the results on the results page in the preRenderView listener.
I'm using the same search page as in my question.
Results page:
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:metadata>
<f:viewParam name="mainNumber" value="#{documentBacking.document.mainNumber}" />
<f:viewParam name="secNumber" value="#{documentBacking.document.secNumber}" />
<f:viewParam name="formType" value="#{documentBacking.document.formType}" />
<f:viewParam name="subFormType" value="#{documentBacking.document.subFormType}" />
<f:event type="preRenderView" listener="#{documentBacking.generateResults}" />
</f:metadata>
...
<p:dataTable value="#{documentBacking.results}" var="results">
<p:column headerText="Main Number">
<h:outputText value="#{results.mainNumber}" />
</p:column>
<p:column headerText="Secondary Number">
<h:outputText value="#{results.secNumber}" />
</p:column>
<p:column headerText="Form Type">
<h:outputText value="#{results.formType}" />
</p:column>
</p:dataTable>
#ViewScoped Backing Bean:
#ViewScoped
public class DocumentBacking {
private Document document = new Document();
private List<Document> results = null;
public Document getDocument() {
return document;
}
public void setDocument(Document document) {
this.document = document;
}
public List<Document> getResults() {
return results;
}
public void setResults(List<Document> results) {
this.results = results;
}
public void generateResults() {
results = new ArrayList<Document>();
// dummy data
Document doc = new Document();
doc.setMainNumber("9343");
doc.setSecNumber("71254");
doc.setFormType("OTHER FORMS");
doc.setSubFormType("CALGB");
results.add(doc);
doc = new Document();
doc.setMainNumber("1234");
doc.setSecNumber("4321");
doc.setFormType("SOMETHING");
doc.setSubFormType("MAYO");
results.add(doc);
}
public String search() {
return "results.xhtml?faces-redirect=true&includeViewParams=true";
}
}
I have a custom EntityHome class. I wire the dependent entity in the wire method, but when I call the action (persist) the wired component is always null.
What could be the reason, similar code generated by seam gen is apparently working.
Here is the entity class.
The round.teeSet component is always null when persist is called, although it is shown in the jsf page.
Note: Seam version: 2.2.0.GA Jboss:
jboss-5.1.0.GA
I have overrden persist method to log the value of the wired element.
#Name("roundHome")
#Scope(ScopeType.CONVERSATION)
public class RoundHome extends EntityHome<Round>{
#In(required = false)
private Golfer currentGolfer;
#In(create = true)
private TeeSetHome teeSetHome;
#Override
public String persist() {
logger.info("Persist called");
if (null != getInstance().getTeeSet() ) {
logger.info("teeSet not null in persist");
} else {
logger.info("teeSet null in persist");
// wire();
}
String retVal = super.persist(); //To change body of overridden methods use File | Settings | File Templates.
return retVal;
}
#Logger
private Log logger;
public void wire() {
logger.info("wire called");
TeeSet teeSet = teeSetHome.getDefinedInstance();
if (null != teeSet) {
getInstance().setTeeSet(teeSet);
logger.info("Successfully wired the teeSet instance with color: " + teeSet.getColor());
}
}
public boolean isWired() {
logger.info("is wired called");
if(null == getInstance().getTeeSet()) {
logger.info("wired teeSet instance is null, the button will be disabled !");
return false;
}
else {
logger.info("wired teeSet instance is NOT null, the button will be enabled !");
logger.info("teeSet color: "+getInstance().getTeeSet().getColor());
return true;
}
}
#RequestParameter
public void setRoundId(Long id) {
super.setId(id);
}
#Override
protected Round createInstance() {
Round round = super.createInstance();
round.setGolfer(currentGolfer);
round.setDate(new java.sql.Date(System.currentTimeMillis()));
return round;
}
}
Here the xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="layout/template.xhtml">
<ui:define name="body">
<h:form id="roundform">
<rich:panel>
<f:facet name="header>">
#{roundHome.managed ? 'Edit' : 'Add' } Round
</f:facet>
<s:decorate id="dateField" template="layout/edit.xhtml">
<ui:define name="label">Date:</ui:define>
<rich:calendar id="date" datePattern="dd/MM/yyyy" value="#{round.date}"/>
</s:decorate>
<s:decorate id="notesField" template="layout/edit.xhtml">
<ui:define name="label">Notes:</ui:define>
<h:inputTextarea id="notes" cols="80" rows="3" value="#{round.notes}" />
</s:decorate>
<s:decorate id="totalScoreField" template="layout/edit.xhtml">
<ui:define name="label">Total Score:</ui:define>
<h:inputText id="totalScore" value="#{round.totalScore}" />
</s:decorate>
<s:decorate id="weatherField" template="layout/edit.xhtml">
<ui:define name="label">Weather:</ui:define>
<h:selectOneMenu id="weather" value="#{round.weather}">
<s:selectItems var="_weather" value="#{weatherCategories}" label="#{_weather.label}"
noSelectionLabel=" Select " />
<s:convertEnum/>
</h:selectOneMenu>
</s:decorate>
<div style="clear: both;">
<span class="required">*</span> required fields
</div>
</rich:panel>
<div class="actionButtons">
<h:commandButton id="save" value="Save"
action="#{roundHome.persist}"
rendered="#{!roundHome.managed}" />
<!-- disabled="#{!roundHome.wired}" /> -->
<h:commandButton id="update" value="Update" action="#{roundHome.update}"
rendered="#{roundHome.managed}" />
<h:commandButton id="delete" value="Delete" action="#{roundHome.remove}"
rendered="#{roundHome.managed}" />
<s:button id="discard" value="Discard changes" propagation="end"
view="/Round.xhtml" rendered="#{roundHome.managed}" />
<s:button id="cancel" value="Cancel" propagation="end"
view="/#{empty roundFrom ? 'RoundList' : roundFrom}.xhtml"
rendered="#{!roundHome.managed}" />
</div>
<rich:tabPanel>
<rich:tab label="Tee Set">
<div class="association">
<h:outputText value="Tee set not selected" rendered="#{round.teeSet == null}" />
<rich:dataTable var="_teeSet" value="#{round.teeSet}" rendered="#{round.teeSet != null}">
<h:column>
<f:facet name="header">Course</f:facet>#{_teeSet.course.name}
</h:column>
<h:column>
<f:facet name="header">Color</f:facet>#{_teeSet.color}
</h:column>
<h:column>
<f:facet name="header">Position</f:facet>#{_teeSet.pos}
</h:column>
</rich:dataTable>
</div>
</rich:tab>
</rich:tabPanel>
</h:form>
</ui:define>
</ui:composition>
I suppose You have a single ScopeType.CONVERSATION (RoundHome) instance without any long-running conversation enabled. So you may have a Temporary conversation which survive until The render response phase.
When you submit your form, because you have a Temporary conversation, You just populate what you submit. It explains why your TeeSet is null. (Your submitted form does not contain any reference to a Tee instance)
If you really want your TeeSet survive until The next submit, you must enable a long-running conversation before showing and disable after submitting your form.
Just an advice: Each Home instance is by default ScopeType.CONVERSATION - inherited from Home. So you can set up your RoundHome as follows
#Name("roundHome")
public class RoundHome extends EntityHome<Round> {
...
}