Primefaces Binding Page attributes - jsf

I'm new for Primefaces .Now I'm migrating RichFaces to Primefaces 5.1. In RichFaces every form has binding initForm to bind Page Attributes.In same form binding use PrimeFaces or any other attribute to bind page attributes.
I'm use below code in Richfaces:
<f:subview id="testSubView">
<h:form id="testForm" binding="#{test.initForm}">
........
</h:form>
<f:subview>
Test.java
public HtmlForm initForm()
{
fetchIntialPageAttributes();
return initForm
}
private void fetchIntialPageAttributes()
{
userTextbox="";
messagePanelRender=true;
userCommandButton=true;
userCommanButtonValue="save";
}
Now doubt initially bind when form load same binding attribute use in Primefaces.

Use <f:event type="postAddToView">, or perhaps <f:event type="preRenderView">, instead to trigger a managed bean listener method right after the component was added to view during view build time, or perhaps right before the view render time.
<h:form id="testForm">
<f:event type="postAddToView" listener="#{test.fetchIntialPageAttributes}" />
...
</h:form>
Do note that this all is not specific to PrimeFaces (nor RichFaces), but just to JSF itself. The binding attribute was during the JSF 1.x era actually a hack/workaround for this. That's one of reasons why JSF 2.0 added those new component system events and the <f:event> tag. An ideal JSF 2.x page does not use binding on a backing bean property anywhere.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?

Related

JSF - Invoke bean method at page load [duplicate]

Is there a way to execute a JSF managed bean action when a page is loaded?
If that's relevant, I'm currently using JSF 1.2.
JSF 1.0 / 1.1
Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.
public Bean() {
// Do your stuff here.
}
JSF 1.2 / 2.x
Use #PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.
#PostConstruct
public void init() {
// Do your stuff here.
}
This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.
JSF 2.0 / 2.1
Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
JSF 2.2+
Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).
public String onload() {
// Do your stuff here.
// ...
return "some.xhtml";
}
See also:
How do I process GET query string URL parameters in backing bean on page load?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.
Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.
This is how to do it -
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
</f:metadata>
</html>
And in the myController.java
public void onPageLoad(){
// Do something
}
EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.
JSF 2.2 has a new feature which performs this task using viewAction.
<f:metadata>
<f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
#PostConstruct is run ONCE in first when Bean Created.
the solution is create a Unused property and Do your Action in Getter method of this property
and add this property to your .xhtml file like this :
<h:inputHidden value="#{loginBean.loginStatus}"/>
and in your bean code:
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public String getLoginStatus() {
// Do your stuff here.
return loginStatus;
}
Calling bean action from a <p:remoteCommand> will be a good idea, keep attribute autoRun="true"
Example below
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />

How to use component binding in JSF right ? (request-scoped component in session scoped bean)

Mojara 2.1.21
I've updated my question based on comments. I have two situation where a component is bound to server session bean. (Additional links with information: Binding attribute causes duplicate component ID found in the view and https://stackoverflow.com/a/12512672/2692917)
Version 1:
single.xhtml:
<h:outputText value=... binding="#{mysessionbean.out}" />
java:
#SessionScoped #Named public class Mysessionbean {
UIOutput out;
//getter and setter ....
}
Version 2:
template.xhtml:
<h:outputText value=... binding="#{mysessionbean.out}"
view1.xhtml:
<ui:composition template="template.xhtml" />
view2.xhtml:
<ui:composition template="template.xhtml" />
java:
#SessionScoped #Named public class Mysessionbean {
UIOutput out;
//getter and setter ....
}
Version 1 is ok. (At least I've not encounter any errors so far). But in version 2 the duplicate id error is occured if I navigate from one page to another. Why does it happen ?
Is it safe to use (request-scoped) component (in version 1) with session scoped binding ?
Are there another use cases to consider ?
Edit:
Functional requirement 1:
I want to use Primefaces datatable in a view. I need some info from this datatable. (Such as selected row or row index). So binding the datatable helps me to retrieve this info.
Functional requirement 2:
Components binding in composite components. They will be bound to session scoped bean. (And used mainly on one page, but what if I used it on another page ?
Requirements 3
The situation as in "Version 2". Template with primefaces menu and session scoped binding. For this I've used the EL-Binding.
In JSF 2.x, unless you want to manipulate components programmatically (which is at its own also rather fishy), there is no sensible real world use case to bind components to a backing bean. For sure not if they are further not been used in the backing bean itself, or if it are solely their attributes which are been flattened out.
As to the functional requirement of getting the current row of the data table, there are much better ways listed here, How can I pass selected row to commandLink inside dataTable?, for example if your environment supports EL 2.2:
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:commandLink value="Foo" action="#{bean.foo(item)}" />
The two last requirements are totally unclear. At least, if you're doing something like:
<x:someComponent binding="#{bean.someComponent}" />
with in bean
someComponent.setSomeAttribute(someAttribute);
someComponent.setOtherAttribute(otherAttribute);
then you should instead be doing
<x:someComponent someAttribute="#{bean.someAttribute}" otherAttribute="#{bean.otherAttribute}" />
Or, if you intend to be able to use the component somewhere else in the view like so
<h:inputText ... required="#{not empty param[bean.save.clientId]}" />
...
<h:commandButton binding="#{bean.save}" ... />
and the instance is further nowhere been used in the bean, then just get rid of the unnecessary property altogether:
<h:inputText ... required="#{not empty param[save.clientId]}" />
...
<h:commandButton binding="#{save}" ... />
If there is really, really no way for some unclear reason, then split all request scoped properties of the session scoped bean out into a separate request scoped bean which you in turn bind to form actions. The session scoped one can just be injected as a #ManagedProperty of the request scoped one.
See also:
Binding attribute causes duplicate component ID found in the view
How does the 'binding' attribute work in JSF? When and how should it be used?
We ran into a similar problem and I just want to share our solution:
Problem:
In a view there was a (extended largely customized) datatable.
<x:dataTable binding="#{bean.someSomeDataTable}" />
After navigating to another page and back we wanted the datatable to have the exact same state. Previously we solved that by binding the datatable to to backing bean. This worked fine with JSPs. With Facelets we could not do that (Duplicate ID errors). So we used the binding, but only saved/restored the state of the datatable component.
public HtmlDataTable getSomeDataTable()
{
HtmlDataTable htmlDataTable = new HtmlDataTable();
if (tableState != null)
htmlDataTable.restoreState(FacesContext.getCurrentInstance(), tableState);
return htmlDataTable;
}
public void setSomeDataTable(HtmlDataTable table)
{
tableState = table.saveState(FacesContext.getCurrentInstance());
}

JSF component binding - some confusion

From web pages like this one,
http://www.jsftutorials.net/components/step5.html
I understand that the binding attribute in JSF tag/view component is to bind the view component to a Java instance of the UI component in the backing bean.
E.g., that's what is done in the following code:
<h:inputText value="#{ myBean.someProperty}" binding="#{ myBean.somePropertyInputText}"/>
But sometimes I see code like this:
<h:commandButton id="t1" binding="#{foo}" value="Hello, World!" onclick="alert('I am #{id:cid(foo)}'); return false;" />
where id:cid is a taglib function which is defined as follow:
public static String cid(UIComponent component) {
FacesContext context = FacesContext.getCurrentInstance();
return component.getClientId(context);
}
In the above code, binding="#{foo}" does not bind to "a Java instance of the UI component in the backing bean".
So what is the meaning of expressions such as binding="#{foo}" ?
It just binds the component to the current Facelet scope. This is particularly useful if you don't need it in the backing bean at all. This saves your backing bean code from useless properties which aren't been used in any of the other methods at all. Note that it also works that way in JSF 1.2. Not sure about JSF 1.0/1.1 though as it uses a different and JSF-proprietary EL API.
See also:
JSF component binding without bean property

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

Invoke JSF managed bean action on page load

Is there a way to execute a JSF managed bean action when a page is loaded?
If that's relevant, I'm currently using JSF 1.2.
JSF 1.0 / 1.1
Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.
public Bean() {
// Do your stuff here.
}
JSF 1.2 / 2.x
Use #PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.
#PostConstruct
public void init() {
// Do your stuff here.
}
This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.
JSF 2.0 / 2.1
Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
JSF 2.2+
Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).
public String onload() {
// Do your stuff here.
// ...
return "some.xhtml";
}
See also:
How do I process GET query string URL parameters in backing bean on page load?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.
Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.
This is how to do it -
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
</f:metadata>
</html>
And in the myController.java
public void onPageLoad(){
// Do something
}
EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.
JSF 2.2 has a new feature which performs this task using viewAction.
<f:metadata>
<f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
#PostConstruct is run ONCE in first when Bean Created.
the solution is create a Unused property and Do your Action in Getter method of this property
and add this property to your .xhtml file like this :
<h:inputHidden value="#{loginBean.loginStatus}"/>
and in your bean code:
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public String getLoginStatus() {
// Do your stuff here.
return loginStatus;
}
Calling bean action from a <p:remoteCommand> will be a good idea, keep attribute autoRun="true"
Example below
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />

Resources