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
Related
This question already has an answer here:
#SessionScoped bean looses scope and gets recreated all the time, fields become null
(1 answer)
Closed 4 years ago.
This is my first question.
I am trying to increment a variable value in a textbox when a button is clicked using primefaces.
But through debug I found out that whenever I click the p:commandButton, EL bean function call, tries to increment the bean class variable "counter", whenever this happens the value of counter is always 0, so it gets incremented to 1 and that is shown in my webpage. It never reaches 2, 3, 4...
Below is the code:
xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel value="Counter:"/>
<h:outputText id="output" value="#{counterView.counter}" />
<p:commandButton value="Count" action="#{counterView.increment}" update="output" />
</h:panelGrid>
</h:form>
</h:body>
</html>
Java:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;
#ManagedBean(name="counterView")
#ViewScoped
public class counterView implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2369382392318418242L;
private int counter = 0;
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public void increment() {
// Counter is 0 always the moment this function is entered...
this.counter = this.counter + 1;
}
}
I cant figure out where I am going wrong as its a classical example in primefaces showcase and I am following that...
Thanks in advance
You use the wrong ViewScoped annotation. You have to use the javax.faces.bean.* annotations in combination with #ManagedBean.
see: #SessionScoped bean looses scope and gets recreated all the time, fields become null
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
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();}
}
Completely edited:
Maybe I was mixing problems and misinterpreted. After simplifying my code the question simplifies to: How can I prevent the <p:commandButton> from executing it's action method on page refresh (like when you hit F5 inside browser window)?
JSF Code:
<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:body>
<h:form>
<h:outputText value="#{bugBean.number}" />
<h:outputText value="#{bugBean.isComplete()}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form" oncomplete="#{bugBean.complete()}"/>
</h:form>
</h:body>
</html>
backing bean code:
package huhu.main.managebean;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class BugBean implements Serializable {
private static final long serialVersionUID = 1L;
private int number;
private boolean isComplete = false;
public void increase(){
number++;
}
public void complete(){
isComplete = true;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean isComplete) {
this.isComplete = isComplete;
}
}
Update:
Even if I remove the oncomplete stuff like this an click the <p:commandButton> just once, the counter goes up on every page refresh.
<h:form>
<h:outputText value="#{bugBean.number}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form"/>
</h:form>
The construct was lacking Ajax-support due to a missing head definition as it seems. In this case I just added <h:head/> right above the <h:body>-tag and everything worked fine.
Thanks to all contributors!
I think that the action method increase() is not called on each page refresh, but it's called the complete() method instead, and this is probably making you think that the action method has been called.
The oncomplete attribute inside the p:commandButton indicates a client side action, and so a JS method, and not a server action: the EL executes #{bugBean.complete()} when parses it on each page refresh.
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.