JSF button action triggered twice - jsf

I already asked this question in the WildFly forum but did not get any answers so far. So I´m trying here.
Since I upgraded from WildFly 8.1 to 8.2 I have problems with a commandButton inside a tabView connected to a bean.
Here is a simple JSF page:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<p:tabView binding="#{testBean.tabView}">
<p:tab title="Tab">
<p:commandButton value="Inside" action="#{testBean.testInside}"/>
</p:tab>
</p:tabView>
<p:commandButton value="Outside" action="#{testBean.testOutside}"/>
</h:form>
</h:body>
</html>
and the bean:
#Named
#SessionScoped
public class TestBean implements Serializable {
private TabView tabView = new TabView();
public TabView getTabView() {
return tabView;
}
public void setTabView(TabView tabView) {
this.tabView = tabView;
}
public void testInside() {
System.out.println("inside");
}
public void testOutside() {
System.out.println("outside");
}
}
Clicking the "Inside" button triggers testInside() two times. The "Outside" button (outside of the tabView) behaves normally and triggers it´s method only once. Removing the tabView binding eliminates the problem. I´m using PrimeFaces 4.0.
Thanks for any ideas
Jan

It's a Mojarra 'issue', introduced by a performance optimization fix in 2.2.7.
this is a Mojarra "issue", I've discovered it when working on RF-13920, it was introduced by JAVASERVERFACES-3193. The components that use binding are not recreated during a request to the server but their children are. With the original children still in place inserting the new children causes the "duplicate id" error.
So it looks like your button is added twice, but since you do not have an explicit id assigned, you do not get the duplicate id error... Might be interesting to give that a try (adding an explicit id)
The JSF specification states that binding should only be used in Request scope, so I don't think it should be treated as a bug if this fails in Conversation scope.
The last remark is the interesting one. As is posted in the next post on the jboss site:
But now I think I have a satisfying solution for this issue and I can confirm, that with request-scoped backing beans for the component binding the exception and duplicate id problem does not occur anymore, even with Mojarra 2.2.8 from Wildfly-8.2.0.Final!
This is even true if the rest of the logic for the page remains in a (say) conversation scoped bean. You just need to have a request-scoped bean for the binding attribute, which then can be referenced in EL and other beans.
Check also this post

You can try doing in other way. Use remoteCommand out of the tab with the same action of the commandButton.
Then use the JavaScript function created by the remoteCommand in the onclick event of the commandButton.
Here is the example using your code.
It's functional.
<h:form>
<p:remoteCommand id="myfun" name="myfun" action="#{testBean.testInside}" />
<p:tabView binding="#{testBean.tabView}">
<p:tab title="Tab">
<p:commandButton value="Inside" onclick="myfun();"/>
</p:tab>
</p:tabView>
</h:form>

Related

Primefaces commandButton not updating datatable. Is update attribute required

I changed my <h:commandButton> tag to a PrimeFaces <p:commandButton> tag on a search page and my datatable stopped displaying the results. After adding an update attribute things worked again. I'm just trying to understand whether it is how I implemented the overall functionality (viewscope, action vs actionListener, etc) or is the update attribute really required?
<h:form id="search_form">
<p:inputText id="search" value="#{searchBean.searchString}" />
<p:commandButton update="search_form" value="Search" action="#{searchBean.searchByString}" >
</p:commandButton>
<p:dataTable id="output" var="res" value="#{searchBean.results}" emptyMessage="No results found with given criteria">
etc...
#ViewScoped
#ManagedBean
public class SearchBean {
#Inject
private SearchRepository searchRepository;
private List<Results> res;
private String searchString;
public SearchBean() {
}
public String searchByString()
{
this.setRes(searchRepository.searchBySingleString(searchString));
}
One of the differences between h:commandButton and p:commandButton is that the second one performs an ajax request by default, while the first executes a plain POST request.
In an ajax request, you must specify what you want to process when form is sent and what to update when response happens. The p:commandButton updates nothing by default, that's why your table is not being properly filled.
See also:
Prime Faces Command Button vs. Default Command Button
Primefaces commandButton

How to integrate Hibernate Validator into Tomcat 7?

I've successfully integrated JSF (Mojarra) and CDI (Weld), but can't get Hibernate Validator to work.
The following jars are added to WEB-INF/lib:
validation-api-1.1.0.Final.jar
hibernate-validator-5.1.0.Final.jar
jboss-logging-3.1.3.GA.jar
classmate-1.0.0.jar
Tomcat 7 comes with EL 2.2 jars so I didn't add them.
My JSF page:
<!DOCTYPE html>
<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>Test</title>
</h:head>
<h:body>
<h:form>
<h1><h:outputText id="hello" value="Hello, #{testController.name}!"/></h1>
<p:inputText id="name" value="#{testController.name}"/>
<h:message id="error" for="name"/>
<h:commandButton value="Change Name">
<f:ajax execute="name" render="hello error"/>
</h:commandButton>
</h:form>
</h:body>
</html>
And my backing bean:
#Named
#ApplicationScoped
public class TestController {
#NotNull
#Size(min = 3, max = 5)
private String name;
#PostConstruct
private void init() {
name = "Bill";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
It's expected that when the size of the name is smaller than 3 or bigger than 5, an error message is shown, but it turns out to be not. Seems the Hibernate Validator is not working . I did see it's detected but was no longer logged:
Mar 11, 2014 9:31:40 PM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 5.1.0.Final
Is there anything wrong?
Update
Finally I figured out it's a Mojarra regression. The Hibernate Validator works now with MyFaces.
Just to avoid confusion (as I have been confused, looking for the error despite it had already been solved because I didn't see the update section at the end of the post), let me add the answer on behalf of the OP:
It seems the OP used a Mojarra version that was broken. They solved the problem by migrating to MyFaces (see the update to their question). FWIW, I tried their example using Mojarra 2.2.12, and it worked fine.
When you say you integrated with Tomcat 7, how did you do that? There is some glue code in application servers which make sure that for example the ValidatorFactory is visible to JSF. Not sure whether something like this would be required for you as well.
Have you enabled debug/trace logging to verify whether Validator bootstraps or get called?
Also you could try to add to the JSF page, but this should be optional.
Aren't you missing the <f:validateBean> tag on the page? I think you might also need to call the Validator.validate(bean) method in order to get it to fire.

JSF 2.0 ViewScoped life cycle

My problem is that one of my ViewScoped bean is created several time within the same view. The constructor of ViewScopedBean is created every time I select a node in the tree.
<h:form>
<p:tree value="#{treeBean.root}" var="node"
selectionMode="single" selection="#{viewScopedBean.selectedNode}">
<p:ajax event="select" update="selectedNode, treeBeanUpdate, otherBeanUpdate, panel" listener="#{treeBean.onNodeSelect}" />
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
Selected Node: <h:outputText value="#{viewScopedBean.selectedNode}" id="selectedNode"/><br/>
Current TreeBean: <h:outputText value="#{treeBean}" id="treeBeanUpdate"/><br/>
Current OtherBean: <h:outputText value="#{viewScopedBean}" id="otherBeanUpdate"/><br/>
<p:outputPanel id="panel">
<ag:profileComponent managedBean="#{viewScopedBean.profileBean}"/>
</p:outputPanel>
</h:form>
If I remove this part (reference to a composite component), the constructor of ViewScopedBean is not called:
<p:outputPanel id="panel">
<ag:profileComponent managedBean="#{viewScopedBean.profileBean}"/>
</p:outputPanel>
All the beans used are set as #ViewScoped.
#ManagedBean
#ViewScoped
public class ViewScopedBean implements Serializable {
private TreeNode selectedNode;
private ProfileBean profileBean;
public ViewScopedBean() {
System.out.println("Constructor of ViewScopedBean " + this);
}
#PostConstruct
public void init() {
System.out.println("ViewScoped init" + this);
profileBean = new ProfileBean();
}
}
Is it the correct behaviour? If not what can cause it?
Update: I tried to use an empty composite, and I have the same problem.
<?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:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="managedBean" required="true"/>
</composite:interface>
<composite:implementation>
</composite:implementation>
</html>
But if I made the managedBean not required, that's fine.
Another thing I don't get is when the constructor is called, it seems that the object created is not used.
Initiating the view (console output):
Constructor of ViewScopedBean xxx.bean.ViewScopedBean#4e1d2b8e
2 clicks on the tree:
Constructor of ViewScopedBean xxx.bean.ViewScopedBean#4eb64f2e
Constructor of ViewScopedBean xxx.bean.ViewScopedBean#66863941
Then I open the debug window <ui:debug/>, the viewScopedBean is set to xxx.bean.ViewScopedBean#4e1d2b8e
The view scoped bean will be recreated on every request from/to the same view, when you use JSTL tags like <c:if>, <c:forEach> and so on in the view, or when you bind a JSF component as a property of the view scoped bean using binding attribute. That's apparently what's happening in your composite component.
You need to rewrite your composite component as such that it does not utilize any JSTL tags. Binding some JSF component as a property of the bean can also be avoided in many ways, but if that is really not avoidable, then disabling the partial state saving in web.xml should work in most of the cases:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
If that doesn't work for you, then you really have to share your composite component implementation code with us so that we can point out the caveats and propose the right approaches.

JSF Backing Bean constructor called multiple times

I'm trying out JSF 2.0 (after using ICEfaces 1.8 for the past few months) and I'm trying to figure out why in JSF 2.0 my backing bean constructor gets called multiple times.
The bean is supposed to be instantiated once upon creation, but the "Bean Initialized" text shows up whenever I click the commandButton, indicating a new Bean object being instansiated.
The facelet page:
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<div id="content">
<h:form id="form">
<h:commandButton value="Toggle" action="#{bean.toggleShowMe}"/>
</h:form>
<h:panelGrid rendered="#{bean.showMe}">
<h:outputText value="Show me!"/>
</h:panelGrid>
</div>
</h:body>
</html>
The backing bean:
#ManagedBean
#RequestScoped
public class Bean {
private boolean showMe = false;
public boolean isShowMe() {
return showMe;
}
public void setShowMe(boolean showMe) {
this.showMe = showMe;
}
public void toggleShowMe(){
System.out.println(showMe);
if(showMe==true){
showMe=false;
}else{
showMe=true;
}
}
/** Creates a new instance of Bean */
public Bean() {
System.out.println("Bean Initialized");
}
}
Thats all it is. Just a simple test. The same behaviour shows itself if I use ICEfaces 2.0 and in place of the panelGrid I use:
<ice:panelPopup visible="#{bean.showMe}">
I'd appreciate any help here. I'm at a loss to explain it.
Update: In response to Aba Dov, I #SessionScoped the bean, figuring it wouldn't be calling the constructor upon each request and ran into the same behavior. What am I missing?
You have declared the bean to be placed in the request scope and you're firing a new HTTP request everytime by the command button. Truly the bean will be created on every request.
If you want that the bean lives as long as the view itself (like as IceFaces is doing under the covers for all that ajax stuff), then you need to declare the bean view scoped (this is new in JSF 2.0).
#ManagedBean
#ViewScoped
public class Bean implements Serializable {}
In my case the problem was I imported "javax.faces.bean.ViewScoped" instead of importing "javax.faces.view.ViewScoped".
Hope it could help someone.
The bean is called every time there is a request from the page.
when you click the <h:commandButton> the form is submitted and a request is sent to the server
in order to prevent it you can use <t:saveState> or <a4j:keepAlive> tags for your been.
for example <a4j:keepAlive beanName="YourBean" />
those tags stores the bean instance in the component tree .
also make sure that your class implements Serializable. so it can be serialized
Hope this helps
The bean should be in the ViewScoped.

Why does #PostConstruct callback fire every time even though bean is #ViewScoped? JSF

I am using datatable on page and using binding attribute to bind it to my backing bean. This is my 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:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" actionListener="#{testBean.action}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
This is my bean :-
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;
#ManagedBean(name="testBean")
#ViewScoped
public class testBean implements Serializable {
private List<String> stringCollection;
public List<String> getStringCollection() {
return stringCollection;
}
public void setStringCollection(List<String> stringCollection) {
this.stringCollection = stringCollection;
}
private HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
#PostConstruct
public void init(){
System.out.println("Post Construct fired!!");
stringCollection = new ArrayList<String>();
stringCollection.add("a");
stringCollection.add("b");
stringCollection.add("c");
}
public void action(){
System.out.println("Clicked!!");
}
}
Please tell me why is the #PostConstruct firing each and every time i click on button? It should fire only once as long as i am on same page beacause my bean is #ViewScoped. Further, if i remove the binding attribute then everything works fine and #PostConstruct callback fires only once. Then why every time when i use binding attribute? I need binding attribute and want to perform initialisation tasks like fetching data from webservice, etc only once. What should i do? Where should i write my initialisation task?
Interesting, when you're using component binding on a view scoped bean, the view scope breaks.
I am not sure if that is a bug in JSF2, I would have to read the entire JSF2 specification first. As far now your best bet is to drop the component binding for now and pass the selected item via new EL 2.2 method argument syntax:
<h:dataTable var="item" value="#{testBean.stringCollection}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
</h:column>
</h:dataTable>
See also:
How can I pass selected row to commandLink inside dataTable?
Invoke direct methods or methods with arguments / variables / parameters in EL
Benefits and pitfalls of #ViewScoped
Update (Dec 2012): this is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, the binding attribute runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.
This is reported as JSF issue 1492 and JSF spec isssue 787 which will be fixed for JSF 2.2. Until then, your best bet is to use binding on request scoped beans exclusively, or to look for alternate ways for the particular functional requirement.
Update (Mar 2015): The JSF 2.2 fix was backported to Mojarra 2.1.18. So if you're still using JSF 2.0/2.1, you'd best upgrade to at least that version. See also a.o. What is component binding in JSF? When it is preferred to be used? and JSTL in JSF2 Facelets... makes sense?
As other said, I would say that the best thing to do is to drop component binding (you don't need it here).
But I would add that you can achieve the same as you're trying to do in a more object-oriented fashion by using action parameters, like this:
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
... and in your java code:
public void action(Item item){
System.out.println("Clicked!!" + item);
}
If you have a viewscoped bean and if you want to retain values that were entered on the form or don't want postconstruct fired, you should return null from your action method.
If you return some outcome (e.g. invalid) and then point the invalid outcome to the same page using faces-config.xml, then the viewscoped bean gets recreated and thus it causes postconstruct to fire again.
Other solution:
Binding the HtmlDataTable in a request scope bean.
Inject this request scope bean in the view scope bean.
JBoss Seam use this solution for binding JSF componentes to a conversation scope component.
The balusc's answer helped me a lot, i would like to say that i had that bug with mojarra version 2.1.7, i am currently using 2.1.29-01 released in january-2015 and this bug is fixed, my problem was binding a tabview to a viewscoped bean. With this version I dont have that bug and binding and postconstruct is working fine.
I use Jboss 5.2 and i have to use mojarra 2.1.x so i hope this answer help other people in the same situation.
http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01
http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01

Resources