I have a JSF application where you enter 2 numbers (index.xhtml), and when you click "Add" button those numbers are added and the result is shown in a new page (resultado.xhtml).
What I want to do is that when you insert the 2 numbers, click "Add" button and go to resultado.xhtml, if you go back to index.xhtml, clicking going back button in you browser, the inputText fields must be empty and not containing the previously inserted values. The problem is that it works with Firefox, but not with Chromium and Konqueror browsers. When I use this browser and press going back button the numbers inserted are in the inputText. How could make it work with all the browsers?
I have followed this link to implement a servlet filter to clear cache: Prevent user from seeing previously visited secured page after logout
index.xhtml
<h:head>
<h:outputStylesheet library="css" name="styles.css" />
</h:head>
<h:body>
<h:form>
<!--Number 1 -->
<h:inputText id="num1" label="num1" required="true" size="5" maxlength="5"
styleClass="#{component.valid ? '' : 'validation-failed'}"
value="#{sumaManagedBean.number1}"
requiredMessage="You must enter a value"/>
</h:inputText>
<h:message for="num1" />
<!--Number 2-->
<h:inputText id="num2" label="num2" required="true" size="5" maxlength="5"
styleClass="#{component.valid ? '' : 'validation-failed'}"
value="#{sumaManagedBean.number2}"
requiredMessage="You must enter a value">
</h:inputText>
<h:message for="num2" />
<h:commandButton value="Add" action="#{sumaManagedBean.direccionPagina()}"/>
</h:form>
</h:body>
resultado.xhtml
<h:head>
<h:outputStylesheet library="css" name="styles.css" />
</h:head>
<h:body>
<h:outputText value="Add correct" rendered="#{sumaManagedBean.insertCorrecto}" styleClass="message"/>
Result:
<h:outputText value="#{sumaManagedBean.calcularResultado()}" />
</h:body>
sumaManagedBean.java. My ManagedBean scope is RequestScope.
package controllers;
//Imports
#ManagedBean
#RequestScoped
public class SumaManagedBean implements Serializable
{
boolean m_binsertCorrecto;
int number1;
int number2;
public SumaManagedBean() {
}
//Getters and Setters
public int getNumber1() {
return number1;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public int getNumber2() {
return number2;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
//
public boolean isInsertCorrecto()
{
return m_binsertCorrecto;
}
public void setInsertCorrecto(boolean bInsertCorrecto)
{
this.m_binsertCorrecto = bInsertCorrecto;
}
public int calcularResultado()
{
int resultado;
resultado = number1 + number2;
return resultado;
}
public String direccionPagina()
{
String direccion = "/resultado";
setInsertCorrecto(true);
return direccion;
}
}
NoCacheFilter.java
package filters;
import java.io.IOException;
import javax.faces.application.ResourceHandler;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebFilter("/*") //Apply a filter for all URLs
public class NoCacheFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}
Related
I have a drop down (p:selectOneMenu) as the input field in the Primefaces 8.0 datatable row, after I select the value in the drop down, if I sort it the selected value can be kept after ajax submit. However if I input a filter that filter 0 rows, and then I clear the filter, the selected value in the drop down disappear:
updated base on Kukeltje's request for adding input text:
Select the drop down value
input the filter so that all the rows are filter out
clear the filter, the selected value disappear
My backing bean:
package sample;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class SampleBean implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 5307652891294044974L;
private static final Map<String, String> dropDown = new HashMap<>();
static {
dropDown.put("K1", "K1");
dropDown.put("K2", "K2");
dropDown.put("K3", "K3");
}
public Map<String, String> getDropDown() {
return dropDown;
}
private List<TableObject> tableObjects = Arrays.asList(new TableObject[] {new TableObject(), new TableObject()});
public List<TableObject> getTableObjects() {
return tableObjects;
}
public void setTableObjects(List<TableObject> tableObjects) {
this.tableObjects = tableObjects;
}
public static class TableObject
{
private String dd;
private String inputText;
public String getDd() {
return dd;
}
public void setDd(String dd) {
this.dd = dd;
}
public String getInputText() {
return inputText;
}
public void setInputText(String inputText) {
this.inputText = inputText;
}
}
}
My facelet:
<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" xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
<h:head>
<title>Hello World JSF 2.3</title>
</h:head>
<h:body>
<h:form>
<p:dataTable var="item" value="#{sampleBean.tableObjects}"
widgetVar="itemTable">
<p:ajax event="sort" process="#this" update="#this"
skipChildren="false" />
<p:ajax event="page" process="#this" update="#this"
skipChildren="false" />
<p:ajax event="filter" process="#this" update="#this" global="false"
skipChildren="false" />
<p:column headerText="Dropdown" sortBy="#{item.dd}"
filterBy="#{item.dd}" filterMatchMode="contains">
<p:selectOneMenu id="Dropdown" value="#{item.dd}" required="false"
label="Dropdown" style="width: 90%">
<f:selectItem itemValue="#{null}" itemLabel="" />
<f:selectItems value="#{sampleBean.dropDown.entrySet()}"
var="entry" itemValue="#{entry.value}" itemLabel="#{entry.key}" />
</p:selectOneMenu>
</p:column>
<p:column id="InputTextHeader" headerText="Input Text"
sortBy="#{item.inputText}" filterBy="#{item.inputText}"
filterMatchMode="contains">
<p:inputText id="InputText" value="#{item.inputText}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
I push my testing project to github, in case you want to test it
git clone https://github.com/saycchai/jsf-test.git
cd jsf-test
chmod +x *.sh
./buildAndRun.sh
for payara server:
browse: http://localhost:8080/index.xhtml
for other server:
http://localhost:8080/jsf-test/index.xhtml
Finally I found a work around solution as follows:
I added a phase listener, if the filter submit 0 row (pass as a request parameter, please see the onstart part in the facelet), then backup the Dd value to previousDd before the APPLY_REQUEST_VALUES phase and set the backup value previousDd back to Dd before the RENDER_RESPONSE phase, code as follows:
Backing Bean
package sample;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.persistence.Transient;
#Named
#SessionScoped
public class SampleBean implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 5307652891294044974L;
private static final Map<String, String> dropDown = new HashMap<>();
static {
for(int i=1; i<10; i++) {
dropDown.put("K"+i, "K"+i);
}
}
public Map<String, String> getDropDown() {
return dropDown;
}
private List<TableObject> tableObjects = Arrays.asList(new TableObject[] {new TableObject(), new TableObject(), new TableObject(), new TableObject()});
public List<TableObject> getTableObjects() {
return tableObjects;
}
public void setTableObjects(List<TableObject> tableObjects) {
this.tableObjects = tableObjects;
}
public static class TableObject
{
private String dd;
private String inputText;
public String getDd() {
return dd;
}
public void setDd(String dd) {
this.dd = dd;
}
public String getInputText() {
return inputText;
}
public void setInputText(String inputText) {
this.inputText = inputText;
}
#Transient
private String previousDd;
public String getPreviousDd() {
return previousDd;
}
public void setPreviousDd(String previousDd) {
this.previousDd = previousDd;
}
}
}
Facelet
<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>Hello World JSF 2.3</title>
</h:head>
<h:body>
<h:form id="form">
<p:dataTable id="itemTable" var="item" value="#{sampleBean.tableObjects}"
widgetVar="itemTable"
paginator="true"
>
<p:ajax event="sort" process="#this" update="#this"
skipChildren="false" />
<p:ajax event="page" process="#this" update="#this"
skipChildren="false"
/>
<p:ajax event="filter" process="#this" update="#this" global="false"
skipChildren="false"
onstart="cfg.ext.params.push({name: 'tableFilterCount', value: PF('itemTable').paginator.cfg.rowCount});"
/>
<p:column id="DropdownHeader" headerText="Dropdown" sortBy="#{item.dd}"
filterBy="#{item.dd}" filterMatchMode="contains">
<p:selectOneMenu id="Dropdown" value="#{item.dd}" required="false"
label="Dropdown" style="width: 90%">
<f:selectItem itemValue="#{null}" itemLabel="" />
<f:selectItems value="#{sampleBean.dropDown.entrySet()}"
var="entry" itemValue="#{entry.value}" itemLabel="#{entry.key}" />
</p:selectOneMenu>
</p:column>
<p:column id="InputTextHeader" headerText="Input Text"
sortBy="#{item.inputText}" filterBy="#{item.inputText}"
filterMatchMode="contains">
<p:inputText id="InputText" value="#{item.inputText}" >
<p:ajax />
</p:inputText>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
Phase Listener
package sample;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.primefaces.component.datatable.DataTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.SampleBean.TableObject;
public class SamplePhaseListener implements PhaseListener {
/**
*
*/
private static final long serialVersionUID = 5273254619684337785L;
private Logger logger = LoggerFactory.getLogger(this.getClass());
public void afterPhase(PhaseEvent event) {
}
public void beforePhase(PhaseEvent event) {
if(event.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES) {
prettyPrint("----------------start of Before "+event.getPhaseId().getName()+"------------------------------", 0);
String tableFilterCount = event.getFacesContext().getExternalContext().getRequestParameterMap().get("tableFilterCount");
if(tableFilterCount != null && "0".equals(tableFilterCount)) {
//backup the previous value first
DataTable table = (DataTable) event.getFacesContext().getViewRoot().findComponent("form:itemTable");
for (int index = 0; index < table.getRowCount(); index++) {
table.setRowIndex(index);
Object rowData = table.getRowData();
if(rowData != null) {
TableObject tableObject = (TableObject) rowData;
logger.info(" before backup to previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
tableObject.setPreviousDd(tableObject.getDd());
logger.info(" after backup to previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
}
}
}
prettyPrint("----------------end of Before "+event.getPhaseId().getName()+"------------------------------", 0);
}
if(event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
prettyPrint("----------------start of Before " + event.getPhaseId().getName() + "------------------------------", 0);
String tableFilterCount = event.getFacesContext().getExternalContext().getRequestParameterMap().get("tableFilterCount");
if(tableFilterCount != null && "0".equals(tableFilterCount)) {
//restore the Dd from previous value
DataTable table = (DataTable) event.getFacesContext().getViewRoot().findComponent("form:itemTable");
for (int index = 0; index < table.getRowCount(); index++) {
table.setRowIndex(index);
Object rowData = table.getRowData();
if(rowData != null) {
TableObject tableObject = (TableObject) rowData;
logger.info(" before restore from previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
tableObject.setDd(tableObject.getPreviousDd());
logger.info(" after restore from previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
}
}
}
prettyPrint("----------------end of Before "+event.getPhaseId().getName()+"------------------------------", 0);
}
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
public static final String IDENT = " ";
private void prettyPrint(String str, int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++)
sb.append(IDENT);
sb.append(str + "\n");
logger.trace(sb.toString());
}
}
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
version="2.3">
<lifecycle>
<phase-listener>sample.SamplePhaseListener</phase-listener>
</lifecycle>
</faces-config>
What I doing is just an application where the selected option display in the textArea. But Ajax is not working after lending the page after navigation from the main menu on this page. That function only works after using the submit button.
Below is my JSF page code
<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"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/template.xhtml">
<ui:define name="title">
Ajax Framework - <span class="subitem">Basic</span>
</ui:define>
<ui:define name="description">
This example demonstrates a simple but common usage of posting the form, updating the backend value and displaying the output with ajax.
</ui:define>
<ui:define name="implementation">
<h:form>
<p:panel id="panel" header="Form" style="margin-bottom:10px;">
<p:messages>
<p:autoUpdate />
</p:messages>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="lazy" value="Lazy:" />
<p:selectOneMenu id="lazy" value="#{selectOneMenuView.option}" lazy="true" style="width:125px">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{selectOneMenuView.options}" />
<f:ajax event="change" listener="#{selectOneMenuView.onChange}" execute="#this" render="textarea1"/>
</p:selectOneMenu>
</h:panelGrid>
<p:commandButton value="Submit" update="display" oncomplete="PF('dlg').show()" icon="ui-icon-check" />
<p:dialog header="Values" modal="true" showEffect="bounce" widgetVar="dlg" resizable="false">
<p:panelGrid columns="2" id="display" columnClasses="label,value">
<h:outputText value="Lazy:" />
<h:outputText value="#{selectOneMenuView.option}" />
</p:panelGrid>
</p:dialog>
<h3>AutoResize</h3>
<p:inputTextarea id="textarea1" value="#{selectOneMenuView.inputTextArea}" rows="6" cols="33" />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
And my managed bean is as below
package org.primefaces.showcase.view.input;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;
import org.primefaces.showcase.domain.Theme;
import org.primefaces.showcase.service.ThemeService;
#ManagedBean
public class SelectOneMenuView {
private String console;
private String car;
private List<SelectItem> cars;
private String city;
private Map<String,String> cities = new HashMap<String, String>();
private Theme theme;
private List<Theme> themes;
private String option;
private List<String> options;
private String inputTextArea;
public String getInputTextArea() {
return inputTextArea;
}
public void setInputTextArea(String inputTextArea) {
this.inputTextArea = inputTextArea;
}
#ManagedProperty("#{themeService}")
private ThemeService service;
#PostConstruct
public void init() {
//cars
SelectItemGroup g1 = new SelectItemGroup("German Cars");
g1.setSelectItems(new SelectItem[] {new SelectItem("BMW", "BMW"), new SelectItem("Mercedes", "Mercedes"), new SelectItem("Volkswagen", "Volkswagen")});
SelectItemGroup g2 = new SelectItemGroup("American Cars");
g2.setSelectItems(new SelectItem[] {new SelectItem("Chrysler", "Chrysler"), new SelectItem("GM", "GM"), new SelectItem("Ford", "Ford")});
cars = new ArrayList<SelectItem>();
cars.add(g1);
cars.add(g2);
//cities
cities = new HashMap<String, String>();
cities.put("New York", "New York");
cities.put("London","London");
cities.put("Paris","Paris");
cities.put("Barcelona","Barcelona");
cities.put("Istanbul","Istanbul");
cities.put("Berlin","Berlin");
//themes
themes = service.getThemes();
//options
options = new ArrayList<String>();
for(int i = 0; i < 20; i++) {
options.add("Option " + i);
}
}
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Theme getTheme() {
return theme;
}
public void setTheme(Theme theme) {
this.theme = theme;
}
public List<SelectItem> getCars() {
return cars;
}
public Map<String, String> getCities() {
return cities;
}
public List<Theme> getThemes() {
return themes;
}
public void setService(ThemeService service) {
this.service = service;
}
public String getOption() {
return option;
}
public void setOption(String option) {
this.option = option;
}
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
public void onChange(){
this.inputTextArea = this.option;
}
}
May I know why? Can anyone give me some guideline?
Mojara 2.1.21
I'm using primefaces editor component p:editor. The value attribute in editor is a complex EL-Statement.
<h:form>
<p:datatable value="#{bean.getItems}" var="item">
<p:column>
<p:editor value="bean.A(item).value" />
</p:column>
</p:datatable>
</h:form>
class Bean {
public Entity A (Item i) { return ...}
}
class Entity {
public String getValue();
public void setValue(String);
}
The getter Entity.getValue() is called, but the setter Entity.serValue(String) is not called, if form is submitted.
I suppose it has nothing to do with editor but a common feature of EL. How can I instruct the editor to call a setter if some changes will be made in editor by a user ?
UPDATE
The variant <p:editor value="#{multiEditorBacking.eval(editor).text}" id="textArea" /> has trouble if setter will be called. But <p:editor value="#{editor.text}" id="textArea" /> is ok. The following examples can be used for testing.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:o="http://omnifaces.org/ui" xmlns:pe="http://primefaces.org/ui/extensions">
<ui:composition>
<h:head></h:head>
<h:body>
<h:form id="formId">
<p:dataTable value="#{multiEditorBacking.editors}" var="editor" rowIndexVar="index" >
<p:column>
<p:commandButton value="Refresh" actionListener="#{multiEditorBacking.onRefresh(index)}" update="textArea"
process="#this" />
<p:editor value="#{multiEditorBacking.eval(editor).text}" id="textArea" />
<!-- <p:editor value="#{editor.text}" id="textArea" /> -->
</p:column>
</p:dataTable>
<p:commandButton value="Save" />
</h:form>
</h:body>
</ui:composition>
</html>
MultiEditorBean.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#SessionScoped
#Named
public class MultiEditorBacking implements Serializable{
private List<MultiPojo> editors;
private HashMap <Integer, MultiPojo> hash = new HashMap<Integer, MultiPojo>();
#PostConstruct
public void init(){
editors = new ArrayList<MultiPojo>();
MultiPojo m = new MultiPojo();
m.setText("hey1");
editors.add(m);
hash.put(1, m);
m=new MultiPojo();
m.setText("adf2");
editors.add(m);
hash.put(2, m);
m=new MultiPojo();
m.setText("cjd3");
editors.add(m);
hash.put(3, m);
}
public MultiPojo eval (MultiPojo m){
return m;
}
public void onRefresh (int index){
}
public List<MultiPojo> getEditors() {
return editors;
}
public void setEditors(List<MultiPojo> editors) {
this.editors = editors;
}
public HashMap <Integer, MultiPojo> getHash() {
return hash;
}
public void setHash(HashMap <Integer, MultiPojo> hash) {
this.hash = hash;
}
}
MultiPojo.java
public class MultiPojo {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
This works for me, in Mojarra 2.2.5, using EL 2.2. Are you sure you've got that EL version enabled which allows method parameter passing? You need a Servlet 3.x container available (such as Tomcat 7) or you'll need to add the library yourself. However, it seems you've got it as #{multiEditorBacking.eval(editor).text} value for your editors is being properly evaluated.
By the way, your <ui:composition> surrounding <h:head /> and <h:body /> is unecessary. Another thing I don't like from your code is the use of #SessionScoped for pure view matters. Go with #ViewScoped unless you're explicitly dealing with session related stuff.
#SessionScoped
#Named
public class MultiEditorBacking implements Serializable {
private List<MultiPojo> editors;
private HashMap<Integer, MultiPojo> hash = new HashMap<Integer, MultiPojo>();
public MultiEditorBacking() {
editors = new ArrayList<MultiPojo>();
MultiPojo m = new MultiPojo();
m.setText("hey1");
editors.add(m);
hash.put(1, m);
m = new MultiPojo();
m.setText("adf2");
editors.add(m);
hash.put(2, m);
m = new MultiPojo();
m.setText("cjd3");
editors.add(m);
hash.put(3, m);
}
public MultiPojo eval(MultiPojo m) {
return m;
}
public void onRefresh(int index) {
System.out.println("Editor " + index + " refreshed");
}
public List<MultiPojo> getEditors() {
return editors;
}
public void setEditors(List<MultiPojo> editors) {
this.editors = editors;
}
public HashMap<Integer, MultiPojo> getHash() {
return hash;
}
public void save() {
System.out.println("Editors: " + editors);
}
public void setHash(HashMap<Integer, MultiPojo> hash) {
this.hash = hash;
}
public class MultiPojo {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#Override
public String toString() {
return "MultiPojo [text=" + text + "]";
}
}
}
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<h:form id="formId">
<p:dataTable value="#{multiEditorBacking.editors}" var="editor"
rowIndexVar="index">
<p:column>
<p:commandButton value="Refresh"
actionListener="#{multiEditorBacking.onRefresh(index)}"
update="textArea" process="#this" />
<p:editor value="#{multiEditorBacking.eval(editor).text}"
id="textArea" />
</p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{multiEditorBacking.save}" />
</h:form>
</h:body>
</html>
See also:
Using EL 2.2 with Tomcat 6.0.24
The solution was to use brackets in EL to get setter called.
<p:editor value="#{(multiEditorBacking.eval(editor)).text}"
id="textArea" />
I'm trying to put the currently iterated <p:dataTable var> as a property of a managed bean using <f:setPropertyActionListener>. However, it is always set as null.
The view, dentistas.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: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">
<h:head>
</h:head>
<h:body>
<ui:composition template="/templates/template.xhtml">
<ui:define name="content">
<h:form id="formDentistas">
<p:growl autoUpdate="true" />
<p:commandButton icon="ui-icon-plus" value="Cadastrar"
id="cadastrar" oncomplete="dialogCadastrar.show()" />
<p:dataTable var="dentista" value="#{dentistaMB.dentistas}"
paginator="true" emptyMessage="Não foi encontrado nenhum registro"
rows="10" id="dataTableDentistas">
<f:facet name="header">Lista de Dentistas</f:facet>
<p:column headerText="Nome" sortBy="nome" filterBy="nome" id="nome"
width="200px">
#{dentista.pessoaFisica.nome}
</p:column>
<p:column headerText="Data Nascimento" sortBy="dataNascimento"
filterBy="dataNascimento" id="dataNascimento" width="60px">
#{dentista.pessoaFisica.dataNascimento}
</p:column>
<p:column headerText="CRO" sortBy="cro" filterBy="cro" id="cro"
width="60px">
#{dentista.cro}
</p:column>
<p:column headerText="Ações" style="width:50px;">
<p:commandButton value="Alterar" icon="ui-icon-pencil">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
<p:commandButton value="Remover" icon="ui-icon-trash"
actionListener="#{dentistaMB.deletar}">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
<ui:include src="/tabelas/dialog_insert_dentista.xhtml" />
</ui:define>
</ui:composition>
</h:body>
</html>
The managed bean, DentistaMBImpl:
package br.com.odontonew.mb;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.convert.FacesConverter;
import javax.faces.event.ActionEvent;
import org.apache.log4j.Logger;
import org.primefaces.context.RequestContext;
import br.com.odontonew.bean.Dentista;
import br.com.odontonew.bean.EstadoCivil;
import br.com.odontonew.bean.PessoaFisica;
import br.com.odontonew.bean.Sexo;
import br.com.odontonew.bean.SituacaoPessoa;
import br.com.odontonew.bean.Uf;
import br.com.odontonew.bo.BasicBO;
import br.com.odontonew.exception.BOException;
#ManagedBean(name = "dentistaMB")
#ViewScoped
public class DentistaMBImpl extends BasicMBImpl {
private Logger logger = Logger.getLogger(DentistaMBImpl.class);
#ManagedProperty("#{dentistaBO}")
private BasicBO dentistaBO;
private Dentista dentista;
private Dentista selectedDentista;
private List<Dentista> dentistas;
// Lists
private List<EstadoCivil> estadosCivis;
private List<SituacaoPessoa> situacoesPessoa;
private List<Sexo> sexos;
private List<Uf> ufs;
#PostConstruct
public void init() {
dentista = new Dentista();
dentista.setPessoaFisica(new PessoaFisica());
dentista.getPessoaFisica().setSexo(new Sexo());
dentista.getPessoaFisica().setEstadoCivil(new EstadoCivil());
dentista.getPessoaFisica().setSituacao(new SituacaoPessoa());
dentista.getPessoaFisica().setUf(new Uf());
estadosCivis = (List<EstadoCivil>) dentistaBO
.findByNamedQuery(EstadoCivil.FIND_ALL);
situacoesPessoa = (List<SituacaoPessoa>) dentistaBO
.findByNamedQuery(SituacaoPessoa.FIND_ALL);
sexos = (List<Sexo>) dentistaBO.findByNamedQuery(Sexo.FIND_ALL);
ufs = (List<Uf>) dentistaBO.findByNamedQuery(Uf.FIND_ALL);
}
public void salvar(ActionEvent event) {
try {
dentista = (Dentista) dentistaBO.save(dentista);
addInfoMessage("Dentista salvo com sucesso");
RequestContext.getCurrentInstance().execute(
"dialogCadastrar.hide()");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public void atualizar(ActionEvent event) {
try {
dentistaBO.update(selectedDentista);
addInfoMessage("Dentista atualizado com sucesso");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public void deletar(ActionEvent event) {
try {
dentistaBO.delete(selectedDentista);
addInfoMessage("Dentista deletado com sucesso");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
public List<Dentista> getDentistas() {
try {
if (dentistas == null)
dentistas = (List<Dentista>) dentistaBO
.findByNamedQuery(Dentista.FIND_ALL_COMPLETO);
return dentistas;
} catch (BOException e) {
addErrorMessage(e.getMessage());
return null;
}
}
/* gets and sets */
public Dentista getSelectedDentista() {
return selectedDentista;
}
public void setSelectedDentista(Dentista selectedDentista) {
this.selectedDentista = selectedDentista;
}
public Dentista getDentista() {
return dentista;
}
public void setDentista(Dentista dentista) {
this.dentista = dentista;
}
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public List<EstadoCivil> getEstadosCivis() {
return estadosCivis;
}
public void setEstadosCivis(List<EstadoCivil> estadosCivis) {
this.estadosCivis = estadosCivis;
}
public List<SituacaoPessoa> getSituacoesPessoa() {
return situacoesPessoa;
}
public void setSituacoesPessoa(List<SituacaoPessoa> situacoesPessoa) {
this.situacoesPessoa = situacoesPessoa;
}
public List<Sexo> getSexos() {
return sexos;
}
public void setSexos(List<Sexo> sexos) {
this.sexos = sexos;
}
public void setDentistas(List<Dentista> dentistas) {
this.dentistas = dentistas;
}
public List<Uf> getUfs() {
return ufs;
}
public void setUfs(List<Uf> ufs) {
this.ufs = ufs;
}
public BasicBO getDentistaBO() {
return dentistaBO;
}
public void setDentistaBO(BasicBO dentistaBO) {
this.dentistaBO = dentistaBO;
}
}
Here,
<p:commandButton value="Remover" icon="ui-icon-trash"
actionListener="#{dentistaMB.deletar}">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
you're performing the delete in an actionListener method instead of an action method. This is not right. Business actions should be performed in the action method. All action listeners, including the <f:setPropertyActionListener>, are invoked before action method in the very same order as they are declared and assigned on the command component. So, in effects, the delete is first invoked and then the property is set. That explains why the property is null during the delete.
The fix is simple: make it a real action method:
<p:commandButton value="Remover" icon="ui-icon-trash"
action="#{dentistaMB.deletar}">
<f:setPropertyActionListener target="#{dentistaMB.selectedDentista}" value="#{dentista}" />
</p:commandButton>
Don't forget to remove the ActionEvent argument:
public void deletar() {
// ...
}
See also:
Differences between action and actionListener
Unrelated to the concrete problem, if you happen to target a Servlet 3.0 / EL 2.2 compatible container, then you can even get rid of that <f:setPropertyActionListener> altogether:
<p:commandButton value="Remover" icon="ui-icon-trash"
action="#{dentistaMB.deletar(dentista)}" />
With:
public void deletar(Dentista selectedDentista) {
// ...
}
See also point 3 of How can I pass selected row to commandLink inside dataTable?
This question already has answers here:
Avoid back button on JSF web application
(2 answers)
Closed 1 year ago.
I'm having an issue with the back button, not keeping data in a dynamic dropdown in JSF on a request scoped bean.
I have a form with 2 dropdowns where dropdown2 is dynamic based on what is selected in dropdown1. Below is my code for these dropdowns.
<h:selectOneMenu id="group" label="group" value="#{queryBacking.groupInternalId}">
<f:ajax event="valueChange" render="membership" />
<f:selectItems value="#{supportBean.groupInstitutions}" var="group" itemValue="#{group.institutionInternalId}" itemLabel="#{group.institutionName}" />
</h:selectOneMenu>
<h:selectOneMenu id="membership" label="Membership" value="#{queryBacking.institutionInternalId}">
<f:selectItem itemLabel="Select One" itemValue="0" />
<f:selectItems value="#{queryBacking.groupMembershipInstitutions}" var="institution" itemValue="#{institution.institutionInternalId}" itemLabel="#{institution.institutionShortName}" />
</h:selectOneMenu>
My code works great except that if you submit the form and then click the back button, dropdown2 does not contain any values. How can fix this issue?
You mean the back button in the browser right?
The browser probably loads the page out of the browser cache. So you need to disable caching with a filter:
public class NoCacheFilter implements Filter {
private FilterConfig config;
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
if (!httpReq.getRequestURI().startsWith(
httpReq.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
httpRes.setHeader("Cache-Control",
"no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpRes.setHeader("Pragma", "no-cache"); // HTTP 1.0.
httpRes.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
config = null;
}
#Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
}
And then add this to the web.xml:
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>yourpackage.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
You can specify the pages you want filtered in <url-pattern> </url-pattern>
You can initialize the values for the page in the bean constructor:
TestBean class
#ManagedBean
#ViewScope
public class TestBean {
private String name;
public TestBean() {
//initialize the name attribute
//recover the value from session
HttpSession session = (HttpSession)FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
name = session.getAttribute("name");
if (name == null) {
name = "Luiggi";
}
}
public String someAction() {
//save the value in session
HttpSession session = (HttpSession)FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
session.setAttribute("name", name);
return "Test";
}
//getters and setters...
}
Test.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">
<h:body>
<h:outputText value="Hello " />
<h:outputText value="#{testBean.name}" />
<h:form>
<h:outputText value="Write your name: " />
<h:inputText value="#{testBean.name}" />
<br />
<h:commandButton value="Change name" action="#{testBean.someAction}" />
</h:form>
</h:body>
</ui:composition>
Adding an example to remove the session attribute before navigating to Text.xhtml
SomeBean class
#ManagedBean
#RequestScope
public class SomeBean {
public SomeBean() {
}
public String gotoTest() {
//removes an item from session
HttpSession session = (HttpSession)FacesContext.getCurrentInstance()
.getExternalContext().getSession(false);
session.removeAttribute("name");
return "Test";
}
}
SomeBean.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">
<h:body>
<h:form>
<!-- Every time you navigate through here, your "name"
session attribute will be removed. When you hit the back
button to get Test.xhtml you will see the "name"
session attribute that is actually stored. -->
<h:commandButton value="Go to Test" action="#{someBean.gotoTest}" />
</h:form>
</h:body>
</ui:composition>