I have the following code in JSF
<h:outputLabel value="Date" for="rdate" />
<h:inputText id="rdate" autocomplete="off"
value="#{myMB.abstractProject.joinedDate}">
</h:inputText>
and in Entity class, I have declared as
private Date joinedDate;
public Date getJoinedDate() {
return joinedDate;
}
public void setJoinedDate(Date joinedDate) {
this.joinedDate= joinedDate;
}
The problem is, in ManagedBean I am getting null for the following
System.out.println("date in save method "
+ abstractRequest.getJoinedDate());
What could be the reason for this? h:inputText is infact in <h:form>. Scope of my bean is #ViewAccessScoped
You need to use f:convertDateTime. Like:
<h:outputLabel value="Date" for="rdate" />
<h:inputText id="rdate" autocomplete="off" value="#{myMB.abstractProject.joinedDate}" label="Date">
<f:convertDateTime pattern="dd-MM-yyyy" />
</h:inputText>
Here is an example.
Edit:
Here is what I have done:
The xhtml:
<ui:composition 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" template="/WEB-INF/templates/globalTemplate.xhtml">
<ui:define name="title">1532116</ui:define>
<ui:define name="content">
<h:form>
<h:outputLabel value="Date" for="date" />
<h:inputText id="date" value="#{so15321163.date}" label="Date" required="true">
<f:convertDateTime pattern="dd-MM-yyyy"/>
</h:inputText>
<h:message for="date" style="color:red" />
<h:commandButton value="Submit" actionListener="#{so15321163.listener}"/>
</h:form>
</ui:define>
</ui:composition>
The managed bean:
package app.so.dev.web.controller;
import java.io.Serializable;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
#ManagedBean(name="so15321163")
#ViewScoped // #SessionScoped
public class SO15321163 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8012804893825661900L;
private Date date;
#PostConstruct
public void init() {
}
public void listener(ActionEvent event) {
System.out.println(date);
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
Not sure, but if you are missing the annotation #Named then jsf bean is not working properly.
Here is some more detailed explanation: https://cwiki.apache.org/confluence/display/EXTCDI/Conversations
I have resolved the issue, the problem was there was an Converter error in another form element which stopped the form submit. I have used a Converter class to resolve this issue.
Thanks
Related
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 using Eclipse along with jsf and MVC framework.. when save function of bean file calls from Xhtml file.. it displays the error: Null pointer exception on notingMB.save
Code:
"xhtml File"
"CreateFileDialog.xhtml"
<!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"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form id="CreateFileDialogForm" prependId="false">
<p:dialog widgetVar="CreateFileDialogWidget"
id="CreateFileDialogId" height="500" width="500" modal="true"
closable="true" draggable="true" resizable="false" header="Create File">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="Subject" value="#{bundle.subject}"/>
<h:inputText id="Subject" value="#{fileMB.info.subject}" required="true"/>
<h:outputLabel for="fileRefNo" value="File-Ref-No"/>
<h:inputText id="fileRefNo" value="#{fileMB.info.fileRefNo}" required="true"/>
<h:outputText value="Classification" />
<p:selectOneRadio id="Classi" value="#{fileMB.info.classification}">
<f:selectItem itemLabel="Normal" itemValue="Normal" />
<f:selectItem itemLabel="Restricted" itemValue="Restricted" />
<f:selectItem itemLabel="Confidential" itemValue="Confidential" />
<f:selectItem itemLabel="Secret" itemValue="Secret" />
<f:selectItem itemLabel="TopSecret" itemValue="Top Secret" />
</p:selectOneRadio>
<h:outputText value="Priority" />
<p:selectOneRadio id="prior" value="#{fileMB.info.priority}">
<f:selectItem itemLabel="Normal" itemValue="Normal" />
<f:selectItem itemLabel="High" itemValue="High" />
<f:selectItem itemLabel="Medium" itemValue="Medium" />
<f:selectItem itemLabel="Low" itemValue="Low" />
</p:selectOneRadio>
<h:outputText for="Description" value="#{bundle.briefDescription}" />
<p:inputTextarea id="Description" value="#{fileMB.info.description}" rows="5" cols="30" counter="display" maxlength="10" counterTemplate="{0} characters remaining." autoResize="false" />
<h:outputText id="display" />
<br></br>
<p:commandButton value="Add Comment" icon="ui-icon-plus"
onclick="CreateComentDialogWidget.show();"/>
<br></br>
<br></br>
<p:commandButton value="create" actionListener="#{fileMB.save}" />
<p:commandButton value="cancel" icon="ui-icon-cancel"
onclick="CreateFileDialogWidget.hide();" type="button" />
</h:panelGrid>
</p:dialog>
</h:form>
<ui:include src="/pages/protected/filling/File/CreateComentDialog.xhtml" />
</h:body>
</html>
"CreateCommentDialog.xhtml"
<!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"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form id="CreateComentDialogForm" prependId="false">
<p:dialog widgetVar="CreateComentDialogWidget"
id="CreateComentDialogId" height="500" width="500" modal="true"
closable="true" draggable="true" resizable="false" header="Create File">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="coment" value="write coment"/>
<p:inputTextarea id="coment" value="#{notingMB.note.comment}" rows="5" cols="30" counter="display2" maxlength="50" counterTemplate="{0} characters remaining." autoResize="false" />
<h:outputText id="display2" />
<br></br>
<p:commandButton value="create" actionListener="#{notingMB.save}" />
<p:commandButton value="cancel" icon="ui-icon-cancel"
onclick="CreateComentDialogWidget.hide();" type="button" />
</h:panelGrid>
</p:dialog>
</h:form>
</h:body>
</html>
"BEAN Files"
"FileMB.java"
package com.managedBean.Filling;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.primefaces.model.CheckboxTreeNode;
import org.primefaces.model.TreeNode;
import com.controller.Controller;
import com.dataModel.filling.FileDataModel;
import com.dataModel.filling.HeadingDataModel;
import com.managedBean.BaseMB;
import com.model.um.Organization;
import com.model.um.OrganizationType;
import com.model.um.Person;
import com.model.filling.File;
import com.model.filling.Heading;
import com.model.filling.Noting;
import org.primefaces.event.SelectEvent;
#ManagedBean(name="fileMB")
#SessionScoped
public class FileMB extends BaseMB implements Serializable
{
public static final long serialVersionUID = 1L;
public static final Logger log = LogManager.getLogger(FileMB.class.getName());
private File info;
private File file;
private Person person;
private List<Person> personList;
private FileDataModel fileDataModel;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public List<Person> getPersonList() {
this.personList = controller.getAllPersons();
return personList;
}
public void setPersonList(List<Person> personList) {
this.personList = personList;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public File getInfo() {
return info;
}
public void setInfo(File info) {
this.info = info;
}
public FileDataModel getFileDataModel() {
List<File> fileList = controller.getAllFiles();
this.fileDataModel = new FileDataModel(fileList);
return fileDataModel;
}
public void setFileDataModel(FileDataModel fileDataModel) {
this.fileDataModel = fileDataModel;
}
public FileMB()
{
this.info = new File();
this.person = new Person();
this.file = new File();
controller = Controller.getInstance();
}
public void resetPerson()
{
this.person = new Person();
System.out.println("reset...");
}
public void resetFile()
{
this.file = new File();
System.out.println("reset...");
}
public void save()
{
System.out.println(info.getSubject());
controller.saveFileInfo(info);
System.out.println("before save");
}
}
"NotingMB.java"
package com.managedBean.Filling;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import com.controller.Controller;
import com.managedBean.BaseMB;
import com.model.filling.Noting;
#ManagedBean(name="notingMB")
#SessionScoped
public class NotingMB extends BaseMB implements Serializable
{
public static final long serialVersionUID = 1L;
public static final Logger log = LogManager.getLogger(NotingMB.class.getName());
private Noting note;
public Noting getNote() {
return note;
}
public void setNote(Noting note) {
this.note = note;
}
public NotingMB()
{
this.note = new Noting();
//controller = Controller.getInstance();
}
public void save()
{
System.out.println("before save");
System.out.println(note.getComment());
controller.saveComment(note);
System.out.println("after save");
}
}
The actionListener attribute will accept with a javax.faces.event.ActionEvent parameter.
You should change
public void save() {
System.out.println("before save");
System.out.println(note.getComment());
controller.saveComment(note);
System.out.println("after save");
}
to
public void save(ActionEvent event) {
System.out.println("before save");
System.out.println(note.getComment());
controller.saveComment(note);
System.out.println("after save");
}
Hi I'm trying to access and call a method inside a managed bean in my JSF page. Here is the relevant part of the JSF page:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns="http://www.w3.org/1999/xhtml"
template="./template.xhtml">
<ui:define name="right">
<c:forEach items="#{tweetManager.getTweets}" var="item">
<h:link value="#{item.username}" />
Likes: <h:outputText value="#{item.likes}" />
<h:link id="" value="like" /> <br />
<textarea>
<h:outputText value="#{item.text}" />
</textarea>
</c:forEach>
</ui:define>
Here is the managed bean.
#ManagedBean
#RequestScoped
public class TweetManager {
private Tweet TweetEntity;
private List<Tweet> Tweets;
#EJB
private TweetService TweetService;
#PostConstruct
public void init(){
TweetEntity = new Tweet();
}
public void setTweet(Tweet tweetEntity){
this.TweetEntity = tweetEntity;
}
public Tweet getTweet(){
return this.TweetEntity;
}
public void Save(){
TweetService.create(TweetEntity);
}
public List<Tweet> getTweets(){
Query query = TweetService.getEntityManager().createNativeQuery("SELECT * FROM tweet");
Tweets = query.getResultList();
return Tweets;
}
}
I'm getting an error saying: ... .TweetManager' does not have the property 'getTweets'.
getTweet() is not a property, it is the accessor (or "getter") of the property.
The name of the property is tweets (without the get, first letter to lowercase). So:
<c:forEach items="#{tweetManager.tweets}" var="item">
Remember that boolean properties have "getters" like "is" (v.g. isRich())
And keep in mind my comment about using generics.
I think my problem is related to the fact that my Managed Bean constructor does not appear go get called. That is if i put a breakpoint at the constructor the app does not stop at the breakpoint.
I get headers but not the row added in the constructor.
Here is my code: First the xhtml:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.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"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>LOTTO CHECKER</title>
</f:facet>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="100" resizable="true" closable="true" collapsible="true">
LOTTO CHECKER
</p:layoutUnit>
<p:layoutUnit position="south" size="100" closable="true" collapsible="true">
Footer
</p:layoutUnit>
<p:layoutUnit position="west" size="175" header="Left" collapsible="true" >
</p:layoutUnit>
<p:layoutUnit position="center">
<h:form id="powerBallDrawingForm">
<p:dataTable value="#(lottoCheckerBean.powerBallDrawings}" var="powerBallDrawing" >
<p:column headerText="DATE">
<h:outputText value ="#{powerBallDrawing.drawingDate}"/>
</p:column >
<p:column headerText="BALL 1">
<h:outputText value="#{powerBallDrawing.ball_1}" />
</p:column>
<p:column headerText ="BALL 2">
<h:outputText value="#{powerBallDrawing.ball_2}" />
</p:column>
<p:column headerText ="BALL 3">
<h:outputText value="#{powerBallDrawing.ball_3}" />
</p:column>
<p:column headerText ="BALL 4">
<h:outputText value="#{powerBallDrawing.ball_4}" />
</p:column>
<p:column headerText="BALL 5">
<h:outputText value="#{powerBallDrawing.ball_5}" />
</p:column>
<p:column headerText="POWER BALL">
<h:outputText value="#{powerBallDrawing.powerBall}" />
</p:column>
</p:dataTable>
</h:form>
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
Now the managed Bean
package PowerBall_BigBame_Checker;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class LottoCheckerBean implements Serializable {
// Add business logic below. (Right-click in editor and choose
// "Insert Code > Add Business Method")
private List<PowerBallDrawing> powerBallDrawings;
public LottoCheckerBean() {
powerBallDrawings = new ArrayList<PowerBallDrawing>();
powerBallDrawings.add( new PowerBallDrawing("03/16/2013",1,2,3,4,5,6));
}
public List<PowerBallDrawing> getPowerBallDrawings() {
return this.powerBallDrawings;
}
public void setPowerBallDrawings(List<PowerBallDrawing> powerBallDrawings) {
this.powerBallDrawings = powerBallDrawings;
}
}
Finally the class that comprises a row of the table:
package PowerBall_BigBame_Checker;
import java.io.Serializable;
public class PowerBallDrawing implements Serializable {
private String drawingDate;
private int ball_1;
private int ball_2;
private int ball_3;
private int ball_4;
private int ball_5;
private int powerBall;
public PowerBallDrawing(String drawingDate, int ball_1, int ball_2, int ball_3,
int ball_4, int ball_5, int powerBall) {
this.ball_1 = ball_1;
this.ball_2 = ball_2;
this.ball_3 = ball_3;
this.ball_4 = ball_4;
this.ball_5 = ball_5;
this.powerBall = powerBall;
this.drawingDate = drawingDate;
}
public String getDrawingDate() {
return drawingDate;
}
public void setDrawingDate(String drawingDate) {
this.drawingDate = drawingDate;
}
public int getBall_1() {
return ball_1;
}
public void setBall_1(int ball_1) {
this.ball_1 = ball_1;
}
public int getBall_2() {
return ball_2;
}
public void setBall_2(int ball_2) {
this.ball_2 = ball_2;
}
public int getBall_3() {
return ball_3;
}
public void setBall_3(int ball_3) {
this.ball_3 = ball_3;
}
public int getBall_4() {
return ball_4;
}
public void setBall_4(int ball_4) {
this.ball_4 = ball_4;
}
public int getBall_5() {
return ball_5;
}
public void setBall_5(int ball_5) {
this.ball_5 = ball_5;
}
public int getPowerBall() {
return powerBall;
}
public void setPowerBall(int powerBall) {
this.powerBall = powerBall;
}
}
I suspect I am violating a convention somewhere, but I am not seeing it.
I've added your classes and jsf page to an existing project to see the error.
The only error you have is on this line
<p:dataTable value="#(lottoCheckerBean.powerBallDrawings}" var="powerBallDrawing">
As stated in the comments you have a ( in your EL expression. The correct definition is
<p:dataTable value="#{lottoCheckerBean.powerBallDrawings}" var="powerBallDrawing">
No errors other than this.
The code you have written in the constructor should be inside the following method :
public void setPowerBallDrawings(List powerBallDrawings) {
}
This is because whenever you will try to access the variable then that corresponding setter method will be called .
Try this once. It should work .
Would really appreciate some guidance concerning patterns for a Web App using JSF 2.0, PrimeFaces and Ajax. Our current system uses JSPs with standard submits and we have 1 JSP for each functional page in our app. Each JSP calls an action class for logic, navigation and EJB calls. Migrating to JSF using the same set up would be relatively simple i.e. 1 xhtml page and associated backing bean and navigation/logic done via a do method. However we want to submit via Ajax and this causes puzzles in my head. If I load abc1.xhtml and submit with ajax then I stay on abc1.xhtml although I might need to go to abc2.xhtml. I thought about having the associated forms on 1 xhtml page and using the rendered property to decide what to display. This works but I'm not comfortable having lots of forms in 1 page. Ideally I want to keep each page separate but don't know how this is possible with Ajax. Any ideas would be much appreciated.
Edit - This was original Solution but now has been refined in my answer below. This works but there seems to be issues with the Params. When I click on the AAA or BBB link I need to pass a param so that the ViewController bean knows what was clicked and where to set the Destination page. However if I click the Submit button in AAA.xhtml the content doesn't change unless I also add <f:param name="tranID" value="AAA"/> to the command button. I'd thought I'd handled a null Param in the ViewController constructor but obviously I'm missing something important. My only thoughts were to do with the URL. When I click the menu link it adds the param on to the url ?tranID=AAA. If I then don't add the param onto the subsequent submit is this effectively changing the url and causing some sort of mismatch?
viewController.xhtml
<h:body>
<h:panelGroup layout="block" id="transactionControl">
<h4>
<h:outputLink id="mfa" value="#{facesContext.externalContext.requestContextPath}/xhtml/viewController.xhtml" styleClass="menuLink">
<h:outputText value="AAA"></h:outputText>
<f:param name="tranID" value="AAA"/>
</h:outputLink>
</h4>
<h4>
<h:outputLink id="inq" value="#{facesContext.externalContext.requestContextPath}/xhtml/viewController.xhtml" styleClass="menuLink">
<h:outputText value="BBB"></h:outputText>
<f:param name="tranID" value="BBB"/>
</h:outputLink>
</h4>
</h:panelGroup>
<h:panelGroup layout="block" id="content" style="border-style: solid;">
<ui:include src="#{viewController.destinationPage}.xhtml"></ui:include>
</h:panelGroup>
</h:body>
AAA.xhtml
<h:body>
<h:form prependId="false">
<h:outputText value="Click the button to go to AAB"></h:outputText>
<p>
<p:commandButton id="submitButton" value="Go" ajax="true" actionListener="#{viewController.doAAAtoAAB}"
process="#form"
update="content">
<f:param name="tranID" value="AAA"/>
</p:commandButton>
</p>
</h:form>
</h:body>
AAB.xhtml
<h:body>
<h:panelGroup layout="block" id="subContent">
<h:outputText value="This is the AAB content"></h:outputText>
</h:panelGroup>
</h:body>
BBB.xhtml and BBC.xhtml as above
ViewController bean
package com.mcpplc.supportclient.webapp.managedBeans;
import javax.faces.context.FacesContext;
import java.io.Serializable;
#ManagedBean
#ViewScoped
public class ViewController implements Serializable
{
String destinationPage = "splash";
FacesContext context;
String callingTranID;
public ViewController ()
{
context = FacesContext.getCurrentInstance();
callingTranID = context.getExternalContext().getRequestParameterMap().get("tranID");
if (callingTranID != null )
{
destinationPage = callingTranID;
}
}
public void doAAAtoAAB()
{
destinationPage = "AAB";
}
public void doBBBtoBBC()
{
destinationPage = "BBC";
}
public String getDestinationPage()
{
return destinationPage;
}
public void setDestinationPage( String destinationPage )
{
this.destinationPage = destinationPage;
}
}
My recomendation for you is, do not use ajax unless you need it. If you need to actually call another page after a request, what is the point in using ajax?
Try to think in the application workflow and apply ajax where it is necessary. The cases you think that ajax will be confusing, is because you probably should not be using it
Cheers
Decided to answer my own question as I have now have a full working ajax only prototype app. This fits my initial requirements of having each view saved as one .xhtml page and each view having it's own backing bean. Instead of further polluting my question here is the simplified code. (Thanks to BalusC for his previous answer that really helped although its now disappeared).
viewController.xhtml
<h:body>
<h:panelGroup layout="block" id="transactionControl">
<h:form>
<h4>
<p:commandLink id="mfa" ajax="true" process="#form" update="content transactionBannerContent" styleClass="menuLink" oncomplete="showTransaction01Screens();">
<h:outputText value="MFA"></h:outputText>
<f:setPropertyActionListener target="#{viewController.destinationPage}" value="MFA01"/>
</p:commandLink>
</h4>
<h4>
<p:commandLink id="inq" ajax="true" process="#form" update="content transactionBannerContent" styleClass="menuLink" oncomplete="showTransaction01Screens();">
<h:outputText value="INQ"></h:outputText>
<f:setPropertyActionListener target="#{viewController.destinationPage}" value="INQ01"/>
</p:commandLink>
</h4>
</h:form>
</h:panelGroup>
<h:panelGroup layout="block" id="content" style="border-style: solid;">
<ui:include src="#{viewController.destinationPage}.xhtml"></ui:include>
</h:panelGroup>
</h:body>
mfa01.xhtml
<h:panelGroup layout="block" id="mfa01">
<h:form id="mfa01Form">
<p>
<span>
<h:outputLabel value="UCN" for="ucn"/>
<h:inputText id="ucn" value="#{mfa01BackingBean.mfa01FormVO.ucn}" size="20"/>
</span>
</p>
<p class="submitButton">
<p:commandButton id="submitButton" value="Go" ajax="true" actionListener="#{mfa01BackingBean.doMFA01}" process="#form"
update="content transactionBannerContent" oncomplete="ajaxFinished('MFA01')">
</p:commandButton>
</p>
</h:form>
</h:panelGroup>
mfa02.xhtml
<h:panelGroup layout="block" id="mfa02">
<h:form id="mfa02Form" prependId="true">
<p>
<span style="width:25%">
<h:outputLabel value="Vessel Name"/>
<h:outputText id="vesselName"
value="#{mfa02BackingBean.mfa02FormVO.vesselName}"/>
</span>
<span style="width:75%">
<h:outputLabel value="ETA"/>
<h:outputText id="eta"
value="#{mfa02BackingBean.mfa02FormVO.eta}"/>
</span>
</p>
<p>
<span>
<h:outputLabel value="Unit ID" for="unitID"/>
<h:inputText id="unitID"
value="#{mfa02BackingBean.mfa02FormVO.unitID}"
size="20"
required="true" validator="#{mfa02BackingBean.validateData}"/>
</span>
</p>
<p class="submitButton">
<p:commandButton id="submitButton" value="Go" ajax="true" action="#{mfa02BackingBean.doMFA02}"
process="#form" update="content transactionBannerContent" oncomplete="ajaxFinished('MFA02')">
<f:param name="randomString" value="AAA"/>
</p:commandButton>
</p>
</h:form>
</h:panelGroup>
ViewController.java
package com.mcpplc.supportclient.webapp.managedBeans;
import javax.faces.bean.*;
import java.io.Serializable;
#ManagedBean (name = "viewController")
#SessionScoped
public class ViewController implements Serializable
{
String destinationPage = "splash";
String transactionID;
public String getDestinationPage()
{
return destinationPage;
}
public void setDestinationPage( String destinationPage )
{
this.destinationPage = destinationPage;
transactionID = destinationPage.toUpperCase();
}
public String getTransactionID()
{
return transactionID;
}
public void setTransactionID( String transactionID )
{
this.transactionID = transactionID;
}
}
mfa01BackingBean.java
package com.mcpplc.supportclient.webapp.managedBeans;
import com.mcpplc.supportclient.webapp.Utils.JSFUtils;
import com.mcpplc.supportclient.webapp.valueObjects.*;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class Mfa01BackingBean
{
#ManagedProperty(value = "#{viewController}")
private ViewController viewController;
private ImportConsignmentVO importConsignmentVO;
private VoyageVO voyageVO;
private Mfa01FormVO mfa01FormVO;
private Mfa02FormVO mfa02FormVO;
#PostConstruct
public void init()
{
mfa01FormVO = new Mfa01FormVO();
}
public void doMFA01()
{
//pretend to get VOs
importConsignmentVO = new ImportConsignmentVO();
voyageVO = new VoyageVO();
//set some VO stuff
if ( mfa01FormVO.getUcn().equalsIgnoreCase( "123" ) )
{
importConsignmentVO.setUnitID("AJF1");
voyageVO.setVesselName("Ever Glade");
}
else {
importConsignmentVO.setUnitID("ZZZ1");
voyageVO.setVesselName("Ever Champion");
}
importConsignmentVO.setType("41G1");
importConsignmentVO.setWeight("25000");
voyageVO.setEta("01/01/2011");
constructMFA02Form();
viewController.setDestinationPage("mfa02");
}
private void constructMFA02Form()
{
mfa02FormVO = new Mfa02FormVO();
mfa02FormVO.setUnitID(importConsignmentVO.getUnitID());
mfa02FormVO.setType(importConsignmentVO.getType());
mfa02FormVO.setWeight(importConsignmentVO.getWeight());
mfa02FormVO.setMfaRef("12345");
mfa02FormVO.setVesselName(voyageVO.getVesselName());
mfa02FormVO.setEta(voyageVO.getEta());
JSFUtils.addObjectToRequest(Mfa02FormVO.class.getName(), mfa02FormVO);
}
.....getters&setters
}
mfa02BackingBean.java
package com.mcpplc.supportclient.webapp.managedBeans;
import com.mcpplc.supportclient.webapp.Utils.JSFUtils;
import com.mcpplc.supportclient.webapp.valueObjects.*;
import java.io.Serializable;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class Mfa02BackingBean implements Serializable
{
#ManagedProperty(value = "#{viewController}")
private ViewController viewController;
private Mfa02FormVO mfa02FormVO;
#PostConstruct
public void init()
{
mfa02FormVO = (Mfa02FormVO) JSFUtils.getObjectFromRequest(Mfa02FormVO.class.getName());
}
public String doMFA02()
{
viewController.setDestinationPage("mfa01");
return "viewController";
}
public void validateData ( FacesContext facesContext, UIComponent uiComponentToValidate, Object value)
{
String message = "";
String requestData = (String) value;
if ( !requestData.contains( "0" ) )
{
((UIInput )uiComponentToValidate).setValid( false );
message = "Incorrect format for Unit ID";
facesContext.addMessage( uiComponentToValidate.getClientId(facesContext), new FacesMessage(message) );
//JSFUtils.addObjectToRequest(Mfa02FormVO.class.getName(), mfa02FormVO);
}
}
.....getters&setters
}
Mfa01FormVO & Mfa02FormVO are just value objects with getters & setters
The main issue I encountered was saving object data between requests. When I go from mfa01 to mfa02 I do a lookup populate some vos and then pass a form vo into the Flash. Mfa02 screen is then constructed with the vo values. The big issue I had was when there was a validation error on mfa02. Initially I had the bean set to requestScoped however I lost the vo object after the validation failed. This was despite me adding the object back into the flash as soon as I got it from the Flash. The strange thing about this though was there was no guarantee when I would lose the object. If I clicked again sometimes I would lose the object straight away but sometimes it would remain for 1 more click and then i'd lose it.
I then changed mfa02backingbean to ViewScoped. However because it's completely ajax mfa02backingbean was not getting reinitialised on subsequent requests. This meant that whatever I set the values to on the first request would then be displayed forever more. I finally resolved this using ViewScoped and changing the Command Button to use an Action rather than ActionListener and in that method I return "viewController" String. I assume the lifecycle thinks I'm returning to a new view so it clears out anything left in the viewscope.
I hope this code helps anyone else looking for a similar solution.