View scoped bean is instantiated twice on one page, if there is no redirect when going to page - jsf

I have a page where I use #ViewScoped bean. On page I get data from the bean, and call action on it. Something like this:
<h:form>
<h:dataTable value="#{partyBean.foundOrganisations}" var="party">
<h:column headerClass="header">
<f:facet name="header">
#{msgs['company.registration.number']}
</f:facet>
<h:commandLink value="#{party.registrationNumber}" action="#{partyBean.select}">
<f:setPropertyActionListener value="#{party}" target="#{partyBean.selectedParty}" />
</h:commandLink>
</h:column>
</h:dataTable>
</h:form>
partyBean is #ViewScoped. When I get to this page by navigation rule with <redirect />, everything works fine, but when there is no <redirect />, foundOrganisations are taken from one instance of the bean, but setSelectedParty is called on another instance of the bean when link is clicked. Checked by debug.
Why is that? Can I do something to make it work without <redirect />?

I think its perfectly normal. partyBean is renew with new view.
For a submit to same page you can change your commandLink with command button and return null in action method. In this way JSF acts like same view.
Or you can try keep selectedparty value in a hiddenField (not tested in JSF 2.0)

Related

Set f:param in external h:commandButton (JSF2)

I really love actionListener and the possibility to pass whole objects as as parameter, instead needing to pass values as String or creating (hidden) form fields. I'm using JSF 2.1 (Mojarra) and RichFaces (for popupPanel).
Currently I'm stuck with the following problem:
I create a table with a button that opens a popup. In that popup, the user can edit the data of the current user/object in the table.
When I click the button in the popup to save the edits, how can I submit the values from the popup AND tell the bean action which userObject I'm edited?
Currently, my workaround is using a hidden inputText field in the popup, but I don't like it this way. Is there an alternative?
This is what I try to achieve (minimized):
<h:datatable value="#{bean.users}" var="user">
<h:column>
Username #{user.name}
</h:column>
<h:column>
<input onclick="showPopup()"/>
</h:column>
</h:datatable>
<rich:popupPanel>
<h:inputText value="#{bean.text}" />
<h:commandButton value="Action" actionListener="#{bean.doSomething}">
<f:attribute name="selected" value="#{userObjectFromDatatable}" /> <-- HOW? -->
</h:commandButton>
</rich:popupPanel>
Looks pretty straightforward for you to preserve the selected the userObject in a conversation-like scope as in #ViewScoped. See this article for details on the #ViewScope. As an example, Declare a variable of the desired type as an instance variable in your backing bean
UserObject userObject;
//getters and setters
In your table you'll now have something like the following to set the selected object in your backing bean
<h:commandButton value="Action" actionListener="#{bean.doSomething}">
<f:setPropertyActionListener value="#{user}" target="#{bean.userObject}"/>
</h:commandButton>
By setting the variable in your backing bean from within the table, the viewscope will ensure that any other operation you perform on that object will be with the same instance, provided you stay on the same JSF view and you do not navigate away from it.

p:commandButton with p:fileDownload and no ajax only works in second click

I'm using JSF 2.0, Primefaces 3.4.2, Spring 3.1.2.
I'm facing a similar problem of the guy of this link: h:commandButton works from the second click.
Like him I'm not using ajax in the <p:commandButton> but I'm using a <p:fileDownload /> inside the button tag.
I have two views: "list.xhtml" and "downloadView.xhtml". In myBean.java I send a DataModel from view "list.xhtml" to view "downloadView.xhtml" as a request attribute as shown in the code below:
FacesUtil.getServletContext().setAttribute("myDataModelFromRequest", this.myDataModel);
The bean is anotted with #Scope("view")
In view "downloadView.xhtml" I populated succesfully a dataTable with the DataModel sent from request. But the problem happens when I click in the button to download the file. It only works on second try.
I already tried to change the return of my method from null to "downloadView" but the problem was not solved.
In debug mode I noticed that only enter in the "downloadMethod()" on second click.
Anyone have an idea to solve it?
myBean.java
public String viewListMethod() {
//some work here...
FacesUtil.getServletContext().setAttribute("myDataModelFromRequest", this.myDataModel);
return "downloadView";
}
downloadView.xhtml
<h:form id="formId" prependId="false">
<p:dataTable
id="dataTableId" var="myVar" value="#{myDataModelFromRequest}"
selection="#{cargaProcessoControlador.myArray}"
paginator="true" rows="10" paginatorPosition="bottom" paginatorAlwaysVisible="false">
<f:facet name="header">
bla bla bla
</f:facet>
<p:column selectionMode="multiple" style="width:18px" />
//collumns here...
</p:dataTable>
<p:commandButton id="btDownload" ajax="false" value="Download" icon="ui-icon-document" >
<p:fileDownload value="#{myBean.downloadMethod()}" />
</p:commandButton>
</h:form>
The scope "view" on spring doesn´t exist... So you created your own, right? Just to check...
I had that kind of problem once, and I think it was something to do with validation... the
immediate=true attribute solved my problem.
This is something to do with the scope of the page. Your problem is due to partial rendering of page. Initially when you load the page it is not getting loaded fully and because of that the button is not part of that particular view when you try to click on the button for the first time. Try to make you view proper or explicitly render the page from the backing bean before displaying the page

why JSF 2.0 "rendered" does not work without refreshing the page?

When I click a method to render a part of the page, it does not change anything until I manually refresh the page.
Here is the bean:
boolean showPage = true;
public boolean getShowPage(){
return showPage;
}
Here is the view:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents()}" />
</h:form>
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
The panel gets hidden when I manually refresh the page, otherwise it does not.
How is this caused and how can I solve it?
You need to update a parent component of the conditionally rendered component. You can do that by specifying its client ID in the update attribute of the <p:commandButton>:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents}" update=":panel" />
</h:form>
<h:panelGroup id="panel">
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
</h:panelGroup>
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

<h:commandLink> not working inside a <h:dataTable>

I will try to explain myself:
I'm working on a JSF project using java, JSF 2.0 and RichFaces 4.2.1.
When I access my jsf it just loads a search filter and a commandLink. The commandLink will launch a method in my backingBean to load data that it will be displayed in a dataTable.
<h:commandLink id="btnRecords">
<f:ajax render="myCompAjax" event="click" listener="#{myBean.loadRecords}" />
<h:graphicImage value="img/ico_new.gif" alt="#{bundle['button.search']}" />
</h:commandLink>
The datatable is not visible at first, but once you click on the commandLink a flag in the backingBean will change and the table displays with data I just loaded.
<a4j:outputPanel ajaxRendered="true" id="myCompAjax">
<h:dataTable id="recordsTable" value="#{myBean.records}"
var="item" rendered="#{myBean.flagShowTable}">
<h:column headerClass="thPijama" >
<f:facet name="header">
<table><tr class="thPijama"><td></td></tr></table>
</f:facet>
<h:commandLink action="#{myBean.goNextPage}">
<h:outputText value="Go Next Page" />
<h:inputHidden value="#{item}" />
</h:commandLink>
</h:column>
</h:dataTable>
</a4j:outputPanel>
Problem is the commandLink action inside of the dataTable isn't working at all. I just want to navigate to another jsf. In fact, what it does is hiding the dataTable and leaving the filter unchanged. The action method remains unreachable.
Of course, it works if I set the same commandLink outside the dataTable.
I cannot use Session Scope Beans because the people I work for don't approve it.
Can anyone help me?
Thanks for the hint.
I cannot use Session Scope Beans because the people I work for don't approve it.
Are you implying that placing the bean in the session scope instead of the request scope actually solved the problem? If so, then just put the bean in the view scope.
#ManagedBean
#ViewScoped
public class MyBean implements Serializable {
// ...
}
This way the bean will live as long as you're interacting with the same view by ajax requests. The bean is not been shared in other browser tabs/windows in the same session (which is among the architects indeed the major reason to forbid its use in case of simple views).
See also:
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 4 applies to you

why composite compoment does not invoke in the <h:datatable/>

I have a compoment which has a method-signature attribute. It can be activated, but if I put it in a <h:datatable> <h:column/> and trigger this component, it does not work.
When I just refresh this page again or when I put it in another place it can invoked successfully. I would be grateful if somebody can tell me why!
this is my code
<h:column>
<f:facet name="header">op:</f:facet>
<h:commandLink value="alter" action="#{userSession.alterAction}"
rendered="#{userSession.user.power.powerID == 1}">
<f:param name="beanId" value="#{book.bookID}" />
<f:param name="class" value="#{BookBean}" />
</h:commandLink>
<h:commandLink action="#{userSession.detailAction}" value="detail"
rendered="#{userSession.user != null}">
<f:param name="beanId" value="#{book.bookID}" />
<f:param name="class" value="#{BookBean}" />
</h:commandLink>
<h:commandLink action="#{bookAction.bookDelAction}"
onclick="return confirm('are you sure?')" value="delete"
rendered="#{userSession.user.power.powerID == 1}">
<f:param name="beanId" value="#{book.bookID}" />
</h:commandLink>
</h:column>
this manageredBean #{bookAction} is requestScope when i click one of this operation,just like delete ,it doesnot work at all. but if i put the 'delete' commandlink out of <h:datatabel/> .it can invoke backing method successfully. it is so upset!
who can tell me whether <h:datatable/> can Shielding the .i found if i put these code in a <h:form/> .it can invoke too! cound you can tell me the reason!
You need to preserve exactly the same data model (i.e. the one which you have referenced by the value attribute of the <h:dataTable>) in during the request of the form submit as it was during the request of displaying the initial form. The symptoms indicate that you're using a request scoped bean and that the loading of the data model is based on some request parameter which is missing during the form submit and/or the loading is not being done during bean's (post)construction.
Putting the bean in the view scope and/or rearranging the data loading logic should fix it.

Resources