ViewScoped bean is recreated everytime I click on commandButton in my dataTable - jsf-2

Im using primefaces version 3.1.1, Mojarra 2.1.3, Netbeans 7.0.1, Glassfish Server 3.1.
My test application is using a facelet template with top, left, content, right and bottom layout with raw divs and css. After user logs in with container managed jdbcrealm, they will be presented with the main index.html which use the said template.
I put a navigation menu on the left panel which will subsequently update center panel content with ajax upon clicking menuitem. The center panel will be updated dynamically in <ui:include> by using sessionScoped NavigationBean.
In one of the page clientList.xhtml, I put a <p:dataTable> with a button to view the detail by popping up a <p:dialog>. Im using a viewCoped bean to hold the data list displayed on the dataTable.
The problem is, when I click on the button to select a row in the last colum of every row, the dialog does not appear at all, and my p:ajaxStatus gif image kept on rolling unendingly. When I debug the program with netbeans, I notice the constructor is called again and the previous instance is gone after clicking the button.
This is my index.xhtml using facelets template.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:composition template="/BySalesAutomationTemplate.xhtml">
<ui:define name="title">
<h:outputText value="Facelet Index Page"></h:outputText>
</ui:define>
<ui:define name="top">
TOP
</ui:define>
<ui:define name="left">
<ui:include src="users/menu#{request.isUserInRole('ADMIN') ? 'Admin' : 'User'}.xhtml" />
</ui:define>
<ui:define name="right">
<h:outputText value="Cuba2 daan"></h:outputText>
</ui:define>
<ui:define name="maincontent">
<c:if test="#{navigationBean.page!=null}">
<ui:include src="#{navigationBean.page}.xhtml" />
</c:if>
</ui:define>
<ui:define name="bottom">
<center>2012</center>
</ui:define>
</ui:composition>
</html>
This is the clientList.xhtml page which is displayed in the center panel of my index.xhtml upon clicking a link on the menu in the left panel.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Client Listing</title>
</h:head>
<h:body>
<p>Client List</p>
<h:form>
<h:commandButton action="#{authBackingBean.logout}" value="Logout" />
</h:form>
<f:view>
<h:form id="formdetail" prependId="false">
<p:ajaxStatus>
<f:facet name="start">
<h:graphicImage value="images/loading.gif" />
</f:facet>
<f:facet name="complete">
<h:outputText value="" />
</f:facet>
</p:ajaxStatus>
<p:growl id="growl" showDetail="true"/>
<p:dataTable id="dtClientList" value="#{saClientController.lazyModel}" rowsPerPageTemplate="10,20,30,50"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
paginatorAlwaysVisible="false" var="item" paginator="true" rows="10">
<f:facet name="header">
<h:outputText value="Client List"/>
</f:facet>
<p:column filterBy="#{item.idSaClient}">
<f:facet name="header">
<h:outputText value="IdSaClient"/>
</f:facet>
<p:commandLink action="#{saClientController.showDetails(item)}" value="#{item.idSaClient}" target=":maincontent"/>
</p:column>
<p:column filterBy="#{item.saClientName}">
<f:facet name="header">
<h:outputText value="saClientName"/>
</f:facet>
<h:outputText value="#{item.saClientName}"/>
</p:column>
<p:column filterBy="#{#item.saClientAddress}">
<f:facet name="header">
<h:outputText value="SaClientAddress"/>
</f:facet>
<h:outputText value="#{item.saClientAddress}"/>
</p:column>
<p:column style="width:40px">
<h:panelGrid columns="3" styleClass="actions" cellpadding="2">
<p:commandButton id="selectButton" update=":formdetail:display" oncomplete="clientDialog.show()" icon="ui-icon-search" title="View">
<f:setPropertyActionListener value="#{item}" target="#{saClientController.selectedSaClient}" />
</p:commandButton>
</h:panelGrid>
</p:column>
<f:facet name="footer">
<h:outputText value="Client List"/>
</f:facet>
</p:dataTable>
</h:form>
<p:dialog id="clientDialog" header="Client Detail" widgetVar="clientDialog" resizable="false" showEffect="explode" hideEffect="explode">
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
<h:outputText value="Selected Row" />
</f:facet>
<h:outputText value="ID" />
<h:outputText value="#{saClientcontroller.selectedSaClient.idSaClient}" />
<h:outputText value="NAME:" />
<h:outputText value="#{saClientcontroller.selectedSaClient.saClientName}" />
<h:outputText value="DESCRIPTION:" />
<h:outputText value="#{saClientcontroller.selectedSaClient.saClientAddress}" />
</h:panelGrid>
</p:dialog>
</f:view>
</h:body>
</html>
This is my Backing Bean.
public class SaClientController implements Serializable {
#EJB
private SaClientFacade saClientFacade;
private SaClient selectedSaClient;
private LazyDataModel<SaClient> lazyModel;
private List<SaClient> saclients;
/** Creates a new instance of SaClientController */
public SaClientController() {
}
#PostConstruct
public void Init() {
saclients = saClientFacade.Retrieve();
lazyModel = new LazyDataModelImp(saclients);
}
public LazyDataModel<SaClient> getLazyModel() {
return lazyModel;
}
public List<SaClient> getClients() {
return saClientFacade.Retrieve();
}
public SaClient getDetails() {
return selectedSaClient;
}
public String showDetails(SaClient selectedSaClient) {
this.selectedSaClient = selectedSaClient;
return "DETAILS";
}
public String update() {
System.out.println("###UPDATE###");
selectedSaClient = saClientFacade.Update(selectedSaClient);
return "SAVED";
}
public String list() {
System.out.println("###LIST###");
return "LIST";
}
public SaClient getSelectedSaClient() {
return selectedSaClient;
}
public void setSelectedSaClient(SaClient selectedSaClient) {
this.selectedSaClient = selectedSaClient;
}
public String dummyAction()
{
return null;
}
}
This is the LazyModelImp class
public class LazyDataModelImp extends LazyDataModel<SaClient> {
private List <SaClient> datasource;
public LazyDataModelImp(List<SaClient> datasource) {
this.datasource = datasource;
}
#Override
public SaClient getRowData(String rowKey) {
for (SaClient saclient : datasource) {
if (saclient.getIdSaClient().toString().equals(rowKey)) {
return saclient;
}
}
return null;
}
#Override
public Object getRowKey(SaClient saclient) {
return saclient.getIdSaClient().toString();
}
#Override
public List<SaClient> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
List<SaClient> data = new ArrayList<SaClient>();
//filter
for (SaClient saclient : datasource) {
boolean match = true;
for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
String filterValue = filters.get(filterProperty);
String fieldValue = String.valueOf(saclient.getFilterSortFieldValue(filterProperty));
if (filterValue == null || fieldValue.startsWith(filterValue.toUpperCase()) || fieldValue.startsWith(filterValue.toLowerCase())) {
match = true;
} else {
match = false;
break;
}
} catch (Exception e) {
match = false;
}
}
if (match) {
data.add(saclient);
}
}
//rowCount
int dataSize = data.size();
this.setRowCount(dataSize);
//paginate
if (dataSize > pageSize) {
try {
return data.subList(first, first + pageSize);
} catch (IndexOutOfBoundsException e) {
return data.subList(first, first + (dataSize % pageSize));
}
}
else {
return data;
}
//sort
//if (sortField != null) {
// Collections.sort(data, new LazySorter(sortField, sortOrder));
//}
//return data;
}
}
I've already disabled the partial state saving in web.xml.
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
The backingBean is reinitialized the first time I click on the view detail commandButton in the last column of the dataTable in clienList.xhtml. And the dialog does not display at all. But after pressing F5. The dialog can be displayed but without any content, the only thing displayed in the dialog is the label outputText but not the bean values, they are empty. Sorry for newbie question. I will be extremely glad if anyone could advise what im doing is wrong, and maybe a little advise on the navigation and whether my strategy of displaying everything in index.xhtml (so I only have 1 view id all the time which is index.xhtml, right?) is right.

This may be the issue with your PrimeFaces dialog that you have an h:form surrounding the p:dialog. I have noticed the PrimeFaces dialog does not work properly when a child of a form element.
Try placing this dialog form inside of the contents of the dialog.
<p:dialog id="clientDialog" header="Client Detail" widgetVar="clientDialog" resizable="false" showEffect="explode" hideEffect="explode">
<h:form id="formdialog" prependId="false">
<h:panelGrid id="display" columns="2" cellpadding="4">
...

Related

primefaces accordionPanal dynamic disable tab

I have 2 tab in accordionPanel (tab1 and tab2), tab2 is disabled by default, and tab activeIndex is -1 by default.
I want the tab2 be enable if i check on the checkbox in tab1.
I tried by update the whole accordionPanel(bbb), but the tab1 will collapse as default.
method1:
xhtml:
<h:form id="aaa">
<p:accordionPanel id="bbb" activeIndex="#{beanPage.testdd}" widgetVar="accordionPanelWidget">
<p:tab id="tab1">
<f:facet name="title">
<h:panelGroup columns="2">
<h:selectBooleanCheckbox id="chkBox1" value="#{beanPage.testbb}">
<p:ajax global="false" event="click" update=":aaa:bbb:chkBox1,:aaa:bbb" listener="#{beanPage.testcc}" />
</h:selectBooleanCheckbox>
<h:outputText value="tab1" />
</h:panelGroup>
</f:facet>
<h:outputText value="tab1" />
</p:tab>
<p:tab id="tab2" disabled="#{appealPage.testaa}">
<f:facet name="title">
<h:panelGroup columns="2">
<h:selectBooleanCheckbox id="chkBox2" value="#{appealPage.testee}">
<p:ajax global="false" event="click" update=":aaa:bbb:chkBox2" />
</h:selectBooleanCheckbox>
<h:outputText value="tab2" />
</h:panelGroup>
</f:facet>
<h:outputText value="tab2" />
</p:tab>
</p:accordionPanel>
</h:form>
beanPage:
public void init() {
setTestaa(true);
setTestbb(false);
setTestee(false);
setTestdd(-1);
}
public void testcc() {
boolean result = isTestbb();
if (result) {
setTestaa(false);
} else {
setTestaa(true);
}
}
Try this.
I removed the panelGroups.
This is what you need?
XHTML CODE
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:head>
<style>
</style>
</h:head>
<h:body>
<h:form id="aaa">
<p:accordionPanel id="bbb" activeIndex="#{beanPage.testdd}" widgetVar="accordionPanelWidget">
<p:tab id="tab1" title="LA primera">
<f:facet name="title">
<h:selectBooleanCheckbox id="chkBox1" value="#{beanPage.testbb}">
<p:ajax global="false" event="click" update=":aaa:bbb:chkBox1,:aaa:bbb" listener="#{beanPage.testcc}" />
</h:selectBooleanCheckbox>
<h:outputText value="tab1" />
<h:outputText value="tab1" />
</f:facet>
</p:tab>
<p:tab id="tab2" disabled="#{beanPage.testaa}">
<f:facet name="title">
<h:selectBooleanCheckbox id="chkBox2" value="#{beanPage.testee}">
<p:ajax global="false" event="click" update=":aaa:bbb:chkBox2" />
</h:selectBooleanCheckbox>
<h:outputText value="tab2" />
<h:outputText value="tab2" />
</f:facet>
</p:tab>
</p:accordionPanel>
</h:form>
</h:body>
</html>
JAVA CODE
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name="beanPage")
#ViewScoped
public class BeanPage {
public boolean testaa;
public boolean testbb;
public boolean testee;
public int testdd;
public BeanPage() {
System.out.println("1");
setTestaa(true);
setTestbb(false);
setTestee(false);
setTestdd(-1);
}
public void testcc() {
boolean result = isTestbb();
if (result) {
setTestaa(false);
} else {
setTestaa(true);
}
}
public boolean isTestaa() {
return testaa;
}
public void setTestaa(boolean testaa) {
this.testaa = testaa;
}
public boolean isTestbb() {
return testbb;
}
public void setTestbb(boolean testbb) {
this.testbb = testbb;
}
public boolean isTestee() {
return testee;
}
public void setTestee(boolean testee) {
this.testee = testee;
}
public int getTestdd() {
return testdd;
}
public void setTestdd(int testdd) {
this.testdd = testdd;
}
}

Pagination on Primefaces datatable doesn't work

I am currently developing an application with JPA2, Spring 3, MyFaces 2.1 and Primefaces 4.0 RC1.
I developed a simple page with one datatable using pagination feature of primefaces, but when I click on page number (bottom or header), it simply doesn't work. No exception or javascript error is shown.
I've tested both in Chrome and Firefox. Same problem.
Here my code:
#ManagedBean
#ViewScoped
public class MeusCelularesTitularMB extends AbstractMB implements Serializable {
private static final long serialVersionUID = 5446365969371398743L;
private static final Logger logger = LogManager.getLogger(MeusCelularesTitularMB.class);
private CadastroGeral loggedUser;
private List<LinhaCelularTitular> listaCelularesTitular;
#PostConstruct
public void init() {
try {
this.loggedUser = getCadastroGeralService().loadUser(getAuthenticatedUser());
this.listarMeusCelularesTitular();
} catch (ServiceException e) {
logger.error("Erro ao consultar banco de dados", e);
throw new RuntimeException(e);
}
}
private void listarMeusCelularesTitular() {
try {
this.listaCelularesTitular = getLinhaCelularTitularSevice().getLinhasCelularesPorReponsavel(this.loggedUser.getMatricula());
} catch (ServiceException e) {
logger.error("Erro ao consultar banco de dados", e);
throw new RuntimeException(e);
}
}
private static CadastroGeralService getCadastroGeralService() {
return Faces.evaluateExpressionGet("#{cadastroGeralService}");
}
private static LinhaCelularTitularService getLinhaCelularTitularSevice() {
return Faces.evaluateExpressionGet("#{linhaCelularTitularService}");
}
public List<LinhaCelularTitular> getListaCelularesTitular() {
return listaCelularesTitular;
}
public void setListaCelularesTitular(List<LinhaCelularTitular> listaCelularesTitular) {
this.listaCelularesTitular = listaCelularesTitular;
}
}
And the 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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:composition template="../../templates/template.xhtml">
<ui:define name="content">
<h:outputStylesheet library="css" name="meusCelulares.css" />
<h:form id="meusCelularesTitulares">
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();"/>
<h2>Celulares - Titular</h2>
<p:dataTable id="tblLinhaCelularesTitulares"
var="celTitular"
widgetVar="wdgLinhaCelularesTitulares"
value="#{meusCelularesTitularMB.listaCelularesTitular}"
rowKey="#{celTitular.id}"
paginator="true"
rows="10"
rowsPerPageTemplate="5,10,15"
emptyMessage="Nenhum celular encontrado na Base de Dados">
<p:column>
<f:facet name="header">
<h:outputText value="Ações" />
</f:facet>
<h:outputText value="A B C" />
</p:column>
<p:column styleClass="colunaCentralizada">
<f:facet name="header">
<h:outputText value="Código DDD" />
</f:facet>
<h:outputText value="#{celTitular.codigoDDD}" />
</p:column>
<p:column styleClass="colunaCentralizada">
<f:facet name="header">
<h:outputText value="Número" />
</f:facet>
<h:outputText value="#{celTitular.numeroLinha}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Nome" />
</f:facet>
<h:outputText value="#{celTitular.responsavel.nome}" />
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
</html>
If you need some more information, please let me know.
Found the solution! Thanks to #XtremeBiker for the hints.
The <p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();"/> is referencing a dialog box that I forgot to add in the XHTML. So I added the code below and it worked.
<p:dialog modal="true"
widgetVar="statusDialog"
header="Aguarde..."
draggable="false"
closable="false"
resizable="false"
width="245"
height="25" >
<div align="center">
<p:graphicImage value="/resources/images/ajax-loader.gif" />
</div>
</p:dialog>
I use this code to block screen when a ajax request is processing.
Thanks again.

JSF #ViewScoped Bean State is Lost

I am using #ViewScoped Bean for small CRUD application I have a edit and view page but when I click buttons (edit) it will render edit form. After edit form appears the save button or cancel button does not call the function but renders the whole page. The actionListener's function is not called at all and everthing is initialized. Is something wrong with my bean and page?? I am using JSF 2 with richfaces and facelet.
//ViewScoped Bean
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.legendMgr.Legend;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
/**
*
* #author kitex
*/
#ManagedBean(name = "legendbean")
#ViewScoped
public class LegendController implements Serializable {
LegendDTO legendDTO;
String selectedLegend;
List<LegendDTO> legendDTOs;
boolean edit;
public List<LegendDTO> getLegendDTOs() {
return legendDTOs;
}
public void setLegendDTOs(List<LegendDTO> legendDTOs) {
this.legendDTOs = legendDTOs;
}
#PostConstruct
void initialiseSession() {
FacesContext.getCurrentInstance().getExternalContext().getSession(true);
}
public LegendController() {
if (!edit) {
legendDTO = new LegendDTO();
legendDTO.getList().add(new Legend());
legendDTOs = getLegends();
}
}
public String getSelectedLegend() {
return selectedLegend;
}
public void setSelectedLegend(String selectedLegend) {
this.selectedLegend = selectedLegend;
}
public boolean isEdit() {
return edit;
}
public void setEdit(boolean edit) {
this.edit = edit;
}
public LegendDTO getLegendDTO() {
return legendDTO;
}
public void setLegendDTO(LegendDTO legendDTO) {
this.legendDTO = legendDTO;
}
public void addLegendRange() {
Logger.getLogger(LegendController.class.getName()).warning("List Size " + legendDTO.getList().size());
legendDTO.getList().add(new Legend());
Logger.getLogger(LegendController.class.getName()).warning("List Size " + legendDTO.getList().size());
}
public void removeLegendRange(Legend legend) {
if (legendDTO.getList().size() != 1) {
legendDTO.getList().remove(legend);
}
}
public String saveLegend() {
Logger.getLogger(LegendController.class.getName()).warning("Save Legend Edit" + edit);
LegendDAO dao = new LegendDAO();
if (dao.addLegend(legendDTO, edit)) {
edit = false;
Logger.getLogger(LegendController.class.getName()).warning("Save Legend Edit" + edit);
} else {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Could Not Save Confim if you have already defined Legend " + legendDTO.getLegendName() + "!"));
}
return "";
}
public String cancel() {
edit = false;
legendDTO = new LegendDTO();
legendDTO.getList().add(new Legend());
return "";
}
public List<LegendDTO> getLegends() {
LegendDAO dao = new LegendDAO();
return dao.getLegendDTO();
}
//All function from here are for legend delete
public void deleteLegendType(LegendDTO dto) {
LegendDAO dao = new LegendDAO();
if (dao.deleteLegendType(dto.getLegendName())) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Deleted !"));
} else {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Deleted Error !"));
}
}
//All function from here is to legend edit
public void editLegendType(LegendDTO dto) {
edit = true;
Logger.getLogger(LegendController.class.getName()).warning("DTO : " + dto.legendName);
legendDTO = dto;
LegendDAO dao = new LegendDAO();
Logger.getLogger(LegendController.class.getName()).warning("Edit dto set");
try {
List<Legend> legends = dao.getDetailForEditLegend(dto.getLegendName());
if (legends == null || legends.isEmpty()) {
dto.getList().add(new Legend());
} else {
dto.setList(legends);
}
} catch (SQLException ex) {
Logger.getLogger(LegendController.class.getName()).warning("SQL EXception has occoured");
}
Logger.getLogger(LegendController.class.getName()).warning("In Edit Legend Function The size of list" + dto.getList().size());
}
}
//xhtml code
<?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:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
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>
<ui:composition template="/legendTemplate.xhtml">
<ui:define name="windowTitle">Change Legend</ui:define>
<ui:define name="content">
<h:messages globalOnly="true"/>
<rich:panel id="firstPanel">
<h:form id="nis_viewLegend">
<rich:dataTable id="data_tbl" value="#{legendbean.legendDTOs}" var="legendDTOvar" style="width:100%" rendered="#{!legendbean.edit and not empty legendbean.legendDTOs}">
<rich:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:outputText value="#{legendDTOvar.desc}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Legend Type"/>
</f:facet>
<h:outputText value="#{legendDTOvar.legendName}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Legend Type"/>
</f:facet>
<h:outputText value="#{legendDTOvar.legendFor}"/>
</rich:column>
<rich:column>
<a4j:commandLink value="Delete" actionListener="#{legendbean.deleteLegendType(legendDTOvar)}" render=":firstPanel"/>
<h:outputText value="/"/>
<a4j:commandLink value="Edit" actionListener="#{legendbean.editLegendType(legendDTOvar)}" render=":secondPanel :editLegendForm :nis_viewLegend"/>
</rich:column>
</rich:dataTable>
</h:form>
</rich:panel>
<rich:panel id="secondPanel">
<h:form id="editLegendForm" rendered="#{legendbean.edit}">
<h:outputText value="Legend Name"/><br/>
<h:inputText value="#{legendbean.legendDTO.legendName}" readonly="true"/><br/>
<h:outputText value="Description"/><br/>
<h:inputText value="#{legendbean.legendDTO.desc}"/><br/>
<h:outputText value="Legend For"/><br/>
<h:inputText value="#{legendbean.legendDTO.legendFor}"/><br/>
<br/>
<h:outputText value="Range" />
<rich:dataTable id="editDataPnl" value="#{legendbean.legendDTO.list}" var="legend" style="width:100%">
<rich:column>
<f:facet name="header">
<h:outputText value="SN"/>
</f:facet>
<h:inputText value="#{legend.sn}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText value="#{legend.desc}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Lower Range"/>
</f:facet>
<h:inputText value="#{legend.lowerRange}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Upper Range"/>
</f:facet>
<h:inputText value="#{legend.upperRange}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Color"/>
</f:facet>
<h:inputText value="#{legend.color}"/>
</rich:column>
<rich:column>
<a4j:commandLink value="Add" actionListener="#{legendbean.addLegendRange}" render=":secondPanel"/>
<h:outputText value=" / "/>
<a4j:commandLink value="Remove" actionListener="#{legendbean.removeLegendRange(legend)}" render=":secondPanel"/>
</rich:column>
</rich:dataTable>
<br/>
<center>
<a4j:commandButton value="SAVE" action="#{legendbean.saveLegend()}" render=":firstPanel :secondPanel"/>
<a4j:commandButton value="CANCEL" action="#{legendbean.cancel()}" render=":firstPanel :secondPanel"/>
</center>
</h:form>
</rich:panel>
</ui:define>
</ui:composition>
</h:body>
</html>
In ViewScope, once the view is built, for example form.xhtml, its data will last as long you do not go away from this view. To stay in the same view you should call methods that has return type void (which are usually used in actionListener property) or return null, in case of returning an outcome for navigation.
Method expression
In your case your methods are void but instead of passing it to the action listener you're calling it in the view.
Try changing similar code like this:
<a4j:commandButton value="SAVE" actionListener="#{legendbean.saveLegend()}" render="mainPnl"/>
To this:
<a4j:commandButton value="SAVE" actionListener="#{legendbean.saveLegend}" render="mainPnl"/>
As actionListener property already expects a method expression.
Form inside dataTable
Also I noticed you have a form inside your dataTable. That could lead to strange behavior because your form has an id it will be repeated in the resulting page. For that you should try placing the form outside the dataTable.
Even better you could have only one form enclosing the entire code as nested forms are invalid HTML code.
I would suggest you check your legendTemplate.xhtml against nested forms too.
Bean construction
In order to initialize your bean state it is recommended to use a #PostContruct method instead of the bean constructor.
Try changing from this:
public LegendController() {
legendDTO = new LegendDTO();
legendDTO.getList().add(new Legend());
}
To this:
#PostConstruct
public void reset() {
legendDTO = new LegendDTO();
legendDTO.getList().add(new Legend());
}
And delete your constructor.
Your bean data should be kept as long as you're in the same view (aka .xhtml page).
I hope it helps.
I am having the same problem. I don't think the answers above really address the question. He is not having a problem as a result of submitting any forms - pressing those buttons themselves results in the whole page re-rendering, which means that the reference to the view state is already gone before the button is pressed. This is what I am observing as well. For me, it only happens when there are a lot of large search results, and simply re-submitting the same search I just did re-renders the page (without executing the search). I believe the problem has to do with a limit on the amount of data that can be passed to the server in a form: in view scope, all of the data is serialized and passed around in one long hidden value as a value in the form. If that value is too long the server won't accept it and, therefore, will not remember the previous state.
I know this is not definitive, but this is only thread out there on this problem I can find so I hope it helps shed light for others or inspires better information. If you have something more definitive please let us know.
Edit: I am convinced now that this was the problem. My model bean had a reference to a file blob. Once I replaced that reference with a boolean (only needed to know if it existed) the problem went away. Try passing around references to your DTOs/DAOs instead of the objects themselves, or mark them as "transient" where you don't need them to persist. Or, if possible, lighten the objects as I did.
Did you try to return null for functions saveLegend() and cancel() instead of returning empty string?
public String saveLegend() {
---------
return null;
}
public String cancel() {
----------
return null;
}
Return can also be void for ajax request. But if I remember it correctly for richfaces returning null is the only solution. Give it a try. :)
The cancel() works as it reinitialize the bean.
As answered by Bento you cannot pass values using actionListener. Use action instead.
Further Reading:
JSF 2 ViewScope questions
JSF2 Action parameter
Differences between action and actionListener

JSF 2 basic #RequestScoped CRUD

i have these simple pages:
list.xhtml
<h:form id="form">
<h:dataTable value="#{testBean.model}" var="elem">
<h:column>
<f:facet name="header">code</f:facet>
#{elem.code}
</h:column>
<h:column>
<f:facet name="header">description</f:facet>
#{elem.description}
</h:column>
<h:column>
<f:facet name="header">action</f:facet>
<h:commandButton action="#{testBean.edit(elem)}" value="edit"/>
</h:column>
</h:dataTable>
</h:form>
edit.xhtml
<h:form id="form">
<h:panelGrid columns="2">
<h:outputLabel value="code"/>
<h:inputText value="#{testBean.selection.code}"/>
<h:outputLabel value="description"/>
<h:inputText value="#{testBean.selection.description}"/>
</h:panelGrid>
<h:commandButton action="#{testBean.update}" value="update"/>
</h:form>
and this bean:
#ManagedBean
public class TestBean implements Serializable
{
private static final long serialVersionUID = 1L;
#EJB
private PersistenceService service;
private Object selection;
private List<UnitType> model;
#PostConstruct
public void init()
{
model = service.findAll(UnitType.class);
}
public String edit(Object object)
{
System.out.println(Tracer.current(object));
setSelection(object);
return "edit";
}
public String update()
{
System.out.println(Tracer.current(selection));
return "list";
}
// getters and setters
}
so the table is rendered, when i click one of the "edit" buttons it navigates to "edit.jsf" showing filled input,
but when i click the "update" buttons it gives me this error:
javax.el.PropertyNotFoundException: /test2/edit.xhtml #27,54 value="#{testBean.selection.code}": Target Unreachable, 'null' returned null
note that i know how to implement a #ViewScoped interface to manage CRUD operations, but this is a simple proof of concept that i need to better understand JSF lifecycle.
so i want "testBean" to be #RequestScoped
UPDATE trying with f:viewParam, still not understanding...
list.xhtml
<?xml version="1.0" encoding="ISO-8859-1"?>
<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>test list</title>
</h:head>
<h:body>
<h:messages/>
<h:form id="form">
<h:dataTable value="#{testBean2.model}" rows="10" var="elem">
<h:column>
<f:facet name="header">converterString</f:facet>
#{elem.converterString}
</h:column>
<h:column>
<f:facet name="header">first name</f:facet>
#{elem.firstName}
</h:column>
<h:column>
<f:facet name="header">last name</f:facet>
#{elem.lastName}
</h:column>
<h:column>
<f:facet name="header">action</f:facet>
<h:commandButton action="#{testBean2.edit}" value="edit">
<f:param name="entity" value="#{elem.converterString}"/>
</h:commandButton>
<h:commandButton action="#{testBean2.edit2}" value="edit2">
<f:param name="entity" value="#{elem.converterString}"/>
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
edit.xhtml
<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:viewParam id="entityParam" name="entity" value="#{testBean2.selection}" converter="entityConverter" required="true"/>
</f:metadata>
<h:head>
<title>test edit</title>
</h:head>
<h:body>
<h:messages/>
<h:form id="form">
<h:panelGrid columns="2">
<h:outputLabel value="selection"/>
<h:outputText value="#{testBean2.selection.converterString}"/>
<h:outputLabel value="firstName"/>
<h:inputText value="#{testBean2.selection.firstName}"/>
<h:outputLabel value="lastName"/>
<h:inputText value="#{testBean2.selection.lastName}"/>
</h:panelGrid>
<h:commandButton action="#{testBean2.update}" value="update" ajax="false">
<f:param name="entity" value="#{testBean2.selection.converterString}"/>
</h:commandButton>
</h:form>
</h:body>
</html>
testBean2.java
#ManagedBean
public class TestBean2 implements Serializable
{
private static final long serialVersionUID = 1L;
#EJB
private PersistenceService service;
private Object selection;
private List<Person> model;
#PostConstruct
public void init()
{
Tracer.out();
model = service.queryAll(Person.class);
}
public String edit()
{
JsfUtils.addSuccessMessage("edited");
return "edit";
}
public String edit2()
{
JsfUtils.addSuccessMessage("edited");
return "edit?faces-redirect=true&includeViewParams=true";
}
public void update()
{
Tracer.out(selection);
JsfUtils.addSuccessMessage("updated");
}
// getters and setters
}
if i press "edit" button it goes to edit page, but selection is null and no message is showed.
if i press "edit2" button it goes to edit page, but selection is null, showing required message and the url is edit.jsf?entity=
what am i doing wrong?
As my understand, when your second request come to testBean, selection Object is null. If you run this with session bean you may not get this error.
The way I see it, there's no clean way to achieve what you want.
I'll suggest you simply pass around an Id attr between requests as a simple request parameter. So in your post constructor, check if the parameter value is set and based on that, perform a look in your persistence layer.
Alternatively, using the setup you already have, bind the:
<h:inputText value="#{testBean.selection.code}"/>
component to your backing bean and call getValue() on it when necessary. Either way, still untidy.
If you find any other way, please let us know.
Finally I found a way: data will be in a long scope, bean in short.
Note that this is just a proof of concept, not a real use case. And be aware, when dealing with #RequestScope beans, of PrimeFaces lazy DataTable model scope
#ManagedBean
public class TestBean
{
#EJB
private PersistenceService service;
#ManagedProperty("#{viewScope.item}")
private Item item;
#ManagedProperty("#{sessionScope.model}")
private EntityDataModel<Item> model;
#PostConstruct
public void init()
{
if(model == null)
{
model = new EntityDataModel<Item>(Item.class);
Faces.setSessionAttribute("model", model);
}
}
public String update()
{
Faces.getFlash().setKeepMessages(true);
try
{
item = service.update(item);
Faces.setViewAttribute("item", item);
JsfUtils.addSuccessMessage("updated");
return "view?faces-redirect=true&includeViewParams=true";
}
catch(Exception e)
{
e.printStackTrace();
JsfUtils.addErrorMessage(e);
}
return null;
}
// getters and setters, other actions, ...
}
list.xhtml
<p:dataTable value="#{testBean.model}" var="elem" ...>
...
<p:column exportable="false" toggleable="false" headerText="#{bundle.actions}">
<!-- two techniques available for navigation -->
<p:button outcome="view?id=#{elem.converterString}" icon="#{icons.view}" />
<p:commandButton rendered="#{user.isEditAllowed(elem)}"
action="edit?faces-redirect=true&includeViewParams=true" process="#form"
icon="#{icons.edit}">
<f:param name="id" value="#{elem.converterString}" />
</p:commandButton>
</p:column>
</p:dataTable>
view.xhtml
<f:metadata>
<o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true"
converter="entityConverter" />
</f:metadata>
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="content">
<p:panelGrid columns="2">
<h:outputLabel value="#{bundle.name}" />
<h:outputText value="#{item.name}" />
...
</p:panelGrid>
<p:button outcome="list" value="#{bundle.list}" icon="#{icons.list}" />
<p:button rendered="#{user.isEditAllowed(item)}"
outcome="edit?id=#{item.converterString}" value="#{bundle.edit}"
icon="#{icons.edit}" />
</ui:define>
</ui:composition>
edit.xhtml
<f:metadata>
<o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true"
converter="entityConverter" />
</f:metadata>
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="content">
<p:panelGrid columns="2">
<h:outputLabel value="#{bundle.name}" />
<h:panelGroup>
<p:inputText id="name" value="#{item.name}" />
<p:message for="name" />
</h:panelGroup>
...
</p:panelGrid>
<p:commandButton process="#form" update="#form" action="#{testBean.update}"
value="#{bundle.update}" icon="#{icons.update}" />
<p:button outcome="view?id=#{item.converterString}" value="#{bundle.cancel}"
icon="#{icons.cancel}" />
</ui:define>
</ui:composition>

Primefaces ajax row selection fail to update values in dialog

I have a data table that will display a detail dialog on row select event. However, the dialog does not show any values of the selected object. I can see that the selected object is properly set during debug session.
The table consists of rows of students and it is suppose to display a popup dialog showing detailed information on row selection event.
The StudentBean:
#Named(value = "studentBean")
#SessionScoped
public class StudentBean {
#Inject
private UserFacade userFacade;
private List<User> studentList;
private User selectedStudent;
public StudentBean() {
}
#PostConstruct
public void init() {
studentList = userFacade.findAll();
}
public List<User> getStudentList() {
return studentList;
}
public void setStudentList(List<User> studentList) {
this.studentList = studentList;
}
public User getSelectedStudent() {
return selectedStudent;
}
public void setSelectedStudent(User student) {
this.selectedStudent = student;
}
public void onRowSelect(SelectEvent event) {
}
public void onRowUnselect(UnselectEvent event) {
//FacesMessage msg = new FacesMessage("Student Unselected", ((User) event.getObject()).getFirstName());
//FacesContext.getCurrentInstance().addMessage("messages", msg);
}
}
The Facelet 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:ui="http://java.sun.com/jsf/facelets"
xmlns:h ="http://java.sun.com/jsf/html"
xmlns:p ="http://primefaces.org/ui">
<body>
<ui:composition template="./layout.xhtml">
<ui:define name="content">
<h:form id="studentForm">
<p:dataTable var="student" value="#{studentBean.studentList}"
selectionMode="single"
selection="#{studentBean.selectedStudent}" rowKey="#{student.id}">
<p:ajax event="rowSelect" listener="#{studentBean.onRowSelect}"
update=":studentForm:studentDetail" oncomplete="studentDialog.show()"
global="true" immediate="true"
/>
<p:ajax event="rowUnselect" listener="#{studentBean.onRowUnselect}" />
<p:column headerText="First Name">
<h:outputText value="#{student.firstName}" />
</p:column>
<p:column headerText="Last Name">
<h:outputText value="#{student.lastName}" />
</p:column>
<p:column headerText="Student ID">
<h:outputText value="#{student.studentid}" />
</p:column>
</p:dataTable>
<p:dialog id="dialog" header="Student Detail" widgetVar="studentDialog" resizable="false"
showEffect="fade" hideEffect="fade" appendToBody="true">
<h:panelGrid id="studentDetail" columns="2" cellpadding="4">
<h:outputText value="First Name: " />
<h:outputText value="#{studentBean.selectedStudent.firstName}" />
<h:outputText value="Last Name: " />
<h:outputText value="#{studentBean.selectedStudent.lastName}" />
</h:panelGrid>
</p:dialog>
</ui:define>
</ui:composition>
</body>
</html>
I'm following the Car data table example from the Primefaces Showcase page. It seems so simple there but I can't seem to display the selectedStudent information no matter what I do. The dialog shows up fine but the firstName and lastName values are empty.
I tried the following:
Putting the dialog into another form
Use process="#form"
Use process=":studentForm:studentDetail"
What am I doing wrong?
Primefaces 3.3.1,
Glassfish 3.1.2
I removed global="true" immediate="true", unused listeners
from p:ajax, synchronized rowKey="#{student.id}"
with expression from "Student ID" column and populated
studentList inside #PostConstruct init() function not knowing how yours userFacade code is, and it works.

Resources