I found a weird behavior in JSF/PrimeFaces and ask your help to understand and get around it. The actionListener method in a commandButton is executed just once.
Contextualization:
I put a link in start page of my project to a second page, renderized as follows:
http://localhost:8080/MeusTestes-war/faces/somepage.xhtml?id=1
Notice there is a parameter sent by query string.
The somepage.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:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<f:metadata>
<f:viewParam name="id" value="#{someBean.id}" required="true" />
<f:viewAction action="#{someBean.init}" />
</f:metadata>
<h:body>
<h:form id="form1">
<p:commandButton id="teste1"
value="Teste"
actionListener="#{someBean.doTeste}" />
</h:form>
</h:body>
</html>
As you can see, its extremely simple. Notice there is a metadata section doing the parameter reception and the execution of init() method. In page body there is a p:commandButton and a actionListener pointing to doTeste().
There is my Bean:
@Named(value = "someBean")
@ViewScoped
public class SomeBean implements Serializable {
private int id;
public SomeBean() {
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public void init() {
System.out.println("init " + id);
}
public void doTeste(ActionEvent actionEvent) {
System.out.println("doTeste " + id);
}
}
Well, now the mysterious behavior:
1) When page is loaded, as expected, the init() method shows a message with the correct property value got by viewParam. 2) Firing the button, as expected too, the doTeste() method shows a message with the correct property value. However, 3) Firing the button again, nothing happens!
Other facts:
If I remove the metadata section the doTeste() method is executed as many times as the button is clicked, which is supposed to happen. But the property, obviously, is not initialized.
If I switch the button definition from p:commandButton to h:commandButton, the doTeste() method is executed as expected AND the property is initialized. But I lose the PrimeFaces pattern.
My question:
How to do the commandButton actionListener from PrimeFaces behave the way is expected? (executing the method each time it is fired)
Thanks!
If you for testing purposes add a <p:growl id="msgs"/>
and add update="msgs"
to the button you'll see that validation fails on subsequent requests (because of required="true"
on the viewParam
).
So you can either
required="true"
. Probably a bad idea since you need it.<f:param name="id" value="#{someBean.id}"/>
<o:viewParam>
.There is a more technical explanation here.