No navigation/refresh after submitting a form - jsf-2.2

Here is a very simple jsf page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form enctype="multipart/form-data">
Hello<br/>
<h:outputText value="#{backingBean.currentTime}" />
<br/>
<h:outputText id="contatoreID" value="#{backingBean.counter}" />
<br/>
<h:commandButton value="Add" action="#{backingBean.add}">
<f:ajax render="contatoreID"/>
</h:commandButton>
<br/>
<hr/>
<h:commandButton value="Reset Counter" action="#{backingBean.resetCounter}" />
</h:form>
</h:body>
</html>
The backing bean implementation is trivial.
It has a form with multipart/form-data and two buttons, one with ajax behavior which refresh only one component in the page and a 'standard' submit button.
If the Add button is pressed then Reset Counter doesn't cause the browser to refresh or navigate to a new page.
After lots of searches on internet I found this related bug report:The combination of enctype="multipart/form-data" and ajax stops navigation in some scenarios but it is not clear to me if it is recognized as a real bug or a misconfiguration issue.
I'm using latest available Mojarra release 2.2.5. I cannot seen any progress on this bug report. Can you suggest some workaround ?
Besides I recently moved a web application from Glassfish 3.1.2 to Glassfish 4.0. It worked well before while now I'm struggling with lots of problems which seem bug related, such as this on <ui:repeat>.
I'm conscious I cannot ask opinion related questions here, but I'm wondering if I'm the only person which is having a bad experience with JSF 2.2 release. Maybe I was using Jsf 2.0 in a wrong/unsafe manner...
UPDATE
I add the backing bean code
#ManagedBean
#SessionScoped
public class BackingBean {
/**
* Creates a new instance of BackingBean
*/
public BackingBean() {
}
int counter = 0;
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public void add()
{
counter++;
System.out.println("add called " + counter);
}
public void azzera()
{
counter =0;
System.out.println("Azzera ");
}
public String getOra() { return new Date().toString();}
}

Related

Primefaces AJAX Cannot render nested UIComponent AND actionListener is not working

EDIT 2: Why it is different
#BalusC, this is different from the post you say because I'm asking about an actionListener weird behavior that's not executing a method.
Also, In my test I'm following the Primefaces's documentation, applying fixed id attribute to every NamingContainer and checking the generated HTML (and has the expected id's)
The post you say it's a duplicate from this, was a good help but here we're talking about another problems.
I was working in a webapp's layout and found a problem updating the DOM. I'm working with Primefaces 5.2 and Glassfish 4.1. To isolate the problem I tried to test it in other project but I found another issue in my test. Maybe I'm missing something, so I need to ask in this forum.
I'll go backwards: I'll describe the test and then the real problem so you can see it has the same structure
THE FAILING TEST
index.xhtml
<h:body>
<h:form id="form-render">
<p:commandButton id="btnRender" value="Render" update=":form-rendered"
actionListener="#{renderView.setRender(true)}"/>
</h:form>
<h:form id="form-rendered">
<h:outputText value="Rendered in form-rendered" rendered="#{renderView.render}"/>
<p:panelGrid id="panel-grid" rendered="#{renderView.render}">
<p:outputLabel value="Rendered in form-rendered:panel-grid"/>
</p:panelGrid>
</h:form>
</h:body>
renderView.java
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class RenderView implements Serializable {
private static final long serialVersionUID = -1687524798440117276L;
private boolean render;
public RenderView() {
this.render = false;
System.out.println("Constructor - render=" + this.render);
}
public boolean isRender() {
return render;
}
public void setRender(boolean render) {
this.render = render;
System.out.println("Setter - render=" + this.render);
}
}
But when I run the test only renders the <h:outputText> component. I tried another options:
update=":form-rendered, :form-rendered:panel-grid": same result
update=":form-rendered:panel-grid": doesn't render anything
move rendered=#{...} attribute from <p:panelGrid> to <p:outputLabel> inside it: doesn't change
I don't know how to reference the <p:panelGrid> inside the <h:form>. According to Primefaces's documentation:
Update attribute takes a comma or white-space separated list of JSF component ids to be updated
So the first option should work, but it doesn't. What am I missing here?
THE REAL PROBLEM
The previous test came from a problem I was facing working with a layout. The layout's idea is the following:
In several pages I need to search something and show the results under the search form (with AJAX, of course).
Every page in the layout is a facelet template client (made with <ui:composition>)
This is ONLY the layout, there are not any queries, business logic or anything like that. The #ManagedBean classes I use are just creating dummy objects to populate the Primefaces's components
So I used the same structure of the previous test to solve the problem in every page. The funny thing is that I coded the first one and worked perfectly, but when I coded the second, fails on rendering the second form. Even more, I coded the third and worked perfectly, coded the fourth and fails!!!.
In my first solution attempt I used the following bean:
#ManagedBean // from javax.faces.bean
#ViewScoped // idem
public class SearchView {
private boolean showResults;
public SearchView() {
this.showResults = false;
System.out.println("Constructor-showResults=" + this.showResults);
}
public boolean isShowResults() {
return showResults;
}
public void setShowResults(boolean showResults) {
this.showResults = showResults;
System.out.println("Setter-showResults=" + this.showResults);
}
}
I'll copy-paste from a working example first and then form a failing example, so maybe you can see something I'm missing.
searchPage1.xhtml (working)
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
template="./../templateMenu.xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<ui:define name="left">
<ui:include src="include/auMenu.xhtml"/>
</ui:define>
<ui:define name="content">
<h1>Search 1</h1>
<h:form id="form-busq-au">
<p:panelGrid columns="2" styleClass="ui-noborder">
<!--form fields -->
<p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
actionListener="#{searchView.setShowResults(true)}"
update=":form-res-au"/>
</p:panelGrid>
</h:form>
<h:form id="form-res-au">
<c:if test="#{searchView.showResults}">
<h1>Search Results</h1>
</c:if>
<p:panelGrid id="panelgrid-res-au" columns="2" rendered="#{searchView.showResults}">
<!-- other fields -->
</p:panelGrid>
</h:form>
</ui:define>
</ui:composition>
searchPage2.xhtml (not working)
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
template="./../templateMenu.xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<ui:define name="left">
<ui:include src="include/menu.xhtml"/>
</ui:define>
<ui:define name="content">
<h:form id="form-busq-mt">
<h1>Search 2</h1>
<p:panelGrid columns="4" styleClass="ui-noborder">
<!-- form fields -->
<p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
actionListener="#{searchView.setShowResults(true)}"
update=":form-res-mt"/>
</p:panelGrid>
</h:form>
<h:form id="form-res-mt">
<c:if test="#{searchView.showResults}">
<h1>Search Results</h1>
</c:if>
<p:panelGrid columns="2" rendered="#{searchView.showResults}">
<!-- Other fields -->
</p:panelGrid>
</h:form>
</ui:define>
</ui:composition>
As you can see, it's the same structure in the test and the two pages, but the behavior is different. I don't know if this is a bug in primefaces or what.
Debugging the code I realized that in the second page, the setSearchResult(true) method is never called, don't know why. So I tried the following solution:
Failed solution attempt
Thinking that it was a problem with the SearchView Managed Bean, I made a change in the Controller: I made an abstract class with the attribute and methods and a #ManagedBean for each one of the web pages extending the abstract class. In code:
public abstract class SearchView {
private boolean showResults;
public SearchView() {
this.showResults = false;
System.out.println("Constructor-showResults=" + this.showResults);
System.out.println("Class: " + this.getClass().toString());
System.out.println("ID: " + this.getClass().hashCode());
}
public boolean isShowResults() {
return showResults;
}
public void setShowResults(boolean showResults) {
this.showResults = showResults;
System.out.println("Setter-showResults=" + this.showResults);
}
}
And for every search page:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class ConcreteXXXSearchView extends SearchView implements Serializable {
private static final long serialVersionUID = -4717041016001640528L;
}
but the result is the same (setShowResult(true) is never called in the second page). The println() methods in the abstract class SearchView was to test that I'm instantiating different objects (indeed, there are different).
I tried the test's options but the problem is in the <p:commandButton> because actionListener is not working.
Summarizing
I'm facing two problems here:
In the test I need to render a <h:form> containing a UIComponent that implements NamingContainer(<p:panelGrid>)
In the project I need to know why the setShowResults(true) is not called in the failing page
Any help / guide is appreciated. Thanks in advance
EDIT: more info
In both TEST and REAL PROBLEM I checked the DOM with the browser inspector and the id attribute is correct for both <h:form id="form-res-mt"> and <p:panelGrid id="panelgrid-res-mt">
You have used actionListener="#{searchView.setShowResults()}" in your non-working approach.
<p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
actionListener="#{searchView.setShowResults()}"
update="form-res-mt"/>
But, searchView.setShowResults() method expects a boolean argument, change your code to:
<p:commandButton value="Search" icon="ui-icon-search" style="width: 100%;"
actionListener="#{searchView.setShowResults(true)}"
update="form-res-mt"/>
Also, use <ui:fragment rendered="yourCondition"> instead of <c:if test="condition"> because if component condition returns false ,it'll not attached to the component tree. And thus can't find the component in the UI Tree.

ajax listener inside conditionally rendered element not working [duplicate]

This question already has an answer here:
h:commandButton is not working once I wrap it in a <h:panelGroup rendered>
(1 answer)
Closed 6 years ago.
Here is a test case of my problem:
TestBean:
#ManagedBean
#ViewScoped
public class TestBean implements Serializable {
private static final long serialVersionUID = -2329929006490721388L;
private List<TestObject> testObjects;
private int selectedId;
public TestBean(){
List<TestObject> to = new ArrayList<TestObject>();
for(int i=0; i<10; i++){
TestObject o = new TestObject(i, "object-"+i);
to.add(o);
}
this.setTestObjects(to);
}
public void testAjaxListener(int id){
System.out.println("testAjaxListener("+id+")");
this.setSelectedId(id);
}
//+getters/setters
}
TestObject
public class TestObject {
private int id;
private String name;
public TestObject(int id, String name){
this.setId(id);
this.setName(name);
}
//+getters/setters
}
Test.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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head></h:head>
<h:body>
<h:form id="testForm">
<h:panelGroup rendered="#{param['view'] eq 'test'}">
<h2>DataTable</h2>
<h:dataTable var="o" value="#{testBean.testObjects}">
<h:column>
<h:commandLink value="#{o.name}" actionListener="#{testBean.testAjaxListener(o.id)}">
<f:ajax
render=":testForm:outputTest"
/>
</h:commandLink>
</h:column>
</h:dataTable>
<h2>output</h2>
<h:outputText id="outputTest" value="#{testBean.selectedId}" />
</h:panelGroup>
</h:form>
</h:body>
</html>
The problem is, that actionListener won't firing (i'm checking that with System.out.print as you can see). It works fine when i remove conditional render from panelGroup, so i think that is the issue - but how can i fix it?
I have readed those topics:
h:commandLink / h:commandButton is not being invoked,
f:ajax inside conditionally rendered custom tag - backing bean method not invoked
and many more, but it didn't solve my problem :(
Please help
It's because the #{param['view'] eq 'test'} didn't evaluate true while JSF is busy processing the ajax submit. It will then also consult the rendered, disabled and readonly attributes once again as safeguard against hacked requests. JSF namely doesn't include the request parameters in the <form action> URL as generated by <h:form>. This matches point 5 of commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
There are several ways to get around this.
Set it as a property of the view scoped bean via <f:viewParam>.
<f:metadata>
<f:viewParam name="view" value="#{testBean.view}" />
</f:metadata>
...
<h:panelGroup rendered="#{testBean.view eq 'test'}">
Manually retain the param via <f:param> (you need to put it in every submit action!):
<h:commandLink ...>
<f:param name="view" value="#{param.view}" />
...
</h:commandLink>
Replace <h:form> by OmniFaces <o:form> which is capable of telling JSF that it must submit the form to an URL including the request parameters:
<o:form includeRequestParams="true">
...
</o:form>
See also:
Retaining GET request query string parameters on JSF form submit

PrimeFaces Ajax call only once through the entire application

I am developing a fairly large web application. Suddenly the other day, primefaces ajax only work out once and then not work more.
This problem applies to all primefaces ajax call through the entire application.
I've tried everything and even tried to make a new jsf project in netbeans with the code that you see below. And the same thing, backbean method is called only once. I can see the call in the scriptconsolen firefox, but the backbean method is never called, I get no error.
What could this be caused by? If I replace the primefaces ajax call against the regular jsf ajax, it works.
My set:
NetBeans 7.3
JSF 2.2
PrimeFaces 3.5
GlassFish 3.1.2
I've also tried with the following set and get the same results:
Netbeans 7.4
JSF 2.2
PrimeFaces 3.5
GlassFish 4.0
add() only calls at first click.
Backbean:
package temp;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "backbean")
#SessionScoped
public class Backbean implements Serializable{
private int value = 0;
private int temp = 0;
public Backbean()
{
}
public void setTemp(int temp)
{
this.temp = temp;
}
public int getTemp()
{
return temp;
}
public void add()
{
value += temp;
temp = 0;
}
public void setValue(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}
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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form>
<h:inputText value="#{backbean.temp}"/>
<h:outputText value="#{backbean.value}"/>
<h:commandButton value="Test" type="button">
<p:ajax listener="#{backbean.add()}" update="#form" process="#form" />
</h:commandButton>
</h:form>
</h:body>
</html>
solution:
I tried to replace the primefaces 3.5 the primefaces 4.0 and then worked ajax calls as they should.
Why?
Depend on what you are trying to achieve here, If you want to use JSF h:commandButton then replace p:ajax with f:ajax and add action="#{backbean.add()}" to your h:commandButton (removed the listener) from your p:ajax and replace the update with render and process with execute
If you want to use p:commandButton than remove the p:ajax and add the action="#{backbean.add()}" update="#form" process="#form" to your p:commandButton
In general:
Use <p:ajax inside primefaces components and use <f:ajax inside pure JSF components

retaining values across screen sin JSF2.0

I am working on JSF2.0 project where I need to get value in backing bean from previous screen I have explained it below
my first screen
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="LocationID" />
<h:inputText value="#{getDetails.locationID}"/>
<h:commandButton value="Add OS" action="#{getDetails.addOSDetails}"/>
</h:form>
</h:body>
</html>
My backing bean when the commandButton is invoked
#ManagedBean(name="getDetails")
#RequestScoped
public class GetDetailsBean {
private String locationID;
public String getLocationID() {
return locationID;
}
public void setLocationID(String locationID) {
this.locationID = locationID;
}
public String addOSDetails(){
return "/app_pages/addOS";
}
}
My second screen which is addOS is
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="Enter Value" />
<h:inputText value="#{addOS.addValue}"/>
<h:commandButton value="Add OS" action="#{addOS.save}"/>
</h:form>
</h:body>
</html>
I want the LocationID entered in the first screen to be available in this backing bean
#ManagedBean(name="addOS")
#RequestScoped
public class AddOS {
private String addValue;
public String getAddValue() {
return addValue;
}
public void setAddValue(String addValue) {
this.addValue = addValue;
}
public String save(){
return "app_pages/success";
}
}
I donot want values to be set in session.Can be used.
Thoughts and help please
Thanks.
If you really intend to do a forward, as you do in your question, the submitted on the first page data is already there when the second page is rendered: remember, the forward is done within the same HTTP request. So, what you ultimately need is to keep the value for a subsequesnt POST request. You can do it, for example, by storing the information is a hidden field on the second page:
<h:inputHidden value="#{getDetails.locationID}" />
And that's basically it.
If you intend to do a redirect, thus by appending ?faces-redirect=true to a navigation case outcome, you need to store that information in EL flash to be able to retrieve it in the recepient page: there are two requests to be done. So, change your first bean's action method to the following:
public String action() {
...
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("locationID", locationID);
return "result?faces-redirect=true";
}
This way on the recepient page it will be available in flash map, thus by
#{flash.locationID}
in EL scope and
(String)FacesContext.getCurrentInstance().getExternalContext()
.getFlash().get("locationID");
in Java code.

JSF 2 Ajax requests fail on IE 9

I recently tried to test my JSF application on IE9 and discovered all Ajax requests to fail with a MalformedXML exception complaining about an undefined object when trying to access the removeChild attribute. I observed the problems both with MyFaces 2.0.5 and mojarra 2.1.1. Are there any known limitiations or prerequisites to support IE 9?
To reproduce the problem I nailed it down to a simple test case consisting of one ajax request:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view contentType="text/html">
<h:head>
<h:outputScript name="jsf.js" library="javax.faces" target="head"/>
</h:head>
<h:body>
<h:form id="#{testBean.idForm}">
<h1>Test of IE9 Ajax</h1>
<h:panelGroup id="#{testBean.idDiv}" layout="block">
Text: <h:outputText value="#{testBean.text}"/>
<br/>
<h:commandLink
action="#{testBean.onAction}"
value="click me">
<f:ajax render="#{testBean.idDiv}"/>
</h:commandLink>
</h:panelGroup>
</h:form>
</h:body>
</f:view>
</html>
The bean is
package ietest;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class TestBean {
private int clickCount;
private String idForm="testForm";
private String idDiv="testDiv";
public String getText(){
String text = "you clicked " + clickCount +" times";
System.out.println("Return text " + text);
return text;
}
public String onAction(){
System.out.println("onAction invoked");
clickCount++;
return "iebug";
}
public String getIdDiv() {
return idDiv;
}
public String getIdForm() {
return idForm;
}
}
Looks like Mojarra issue JAVASERVERFACES-1981.
Cannot reproduce this problem using Mojarra 2.1.1 on Tomcat 7.0.12.
Your problem is caused by something else. I suspect it's in your real code an incorrect use of dynamic ids as you have with #{testBean.idDiv}. Try it with fixed ids (why would you ever make it dynamic?)
Further, the <h:outputScript> is entirely superfluous, this one is already by default included by JSF. Remove it. If it makes the problem bigger, then it is definitely caused by something else, e.g. a dirty classpath of different JSF versions mixed altogether.

Resources