RequestScoped bean destroyed in confirmDialog - jsf

I have RequestScoped bean because I'm redirecting the user from dataTable with records to edit page. In this dataTable I have delete buttons:
<p:column>
<p:commandButton update=":deleteNewsDialog" oncomplete="deleteNewsDlg.show()" icon="ui-icon-closethick">
<f:setPropertyActionListener value="#{news}" target="#{newsBean.news}" />
</p:commandButton>
</p:column>
And here is the dialog:
<p:confirmDialog id="deleteNewsDialog" message="Czy na pewno chcesz usunąć wiadomość o tytule "#{newsBean.news.title}"?"
header="Usuwanie wiadomości" severity="alert"
widgetVar="deleteNewsDlg" appendToBody="true">
<h:form>
<p:commandButton value="Usuń" actionListener="#{newsBean.delete}" update=":newsesTableForm:newsesTable, :newsesTableForm:newsGrowl"/>
<p:commandButton value="Anuluj" oncomplete="deleteNewsDlg.hide();"/>
</h:form>
</p:confirmDialog>
When newsBean.delete is fired, newsBean not longer exists so I get a lot of ugly validation exceptions. I have other pages like this with ViewScoped beans and there it is working like a charm. Help?

A request scoped bean has a lifetime of exactly one HTTP request/response. So retrieving the entire view with the form is already one HTTP request/response. The request scoped bean is trashed by end of the response. When you fire an ajax request on the view, then you're essentially sending a new HTTP request. This will thus create a new request scoped bean which get trashed by end of HTTP response. So every ajax request on the same view get its own request scoped bean instance.
This is not what you want if you need to maintain data related to the view. You need to put the bean in the view scope instead. The bean will live as long as you're interacting with the same view by ajax and return null or void in action listener methods. Note that when you return a String, even if empty, the view will be recreated and thus the view scoped bean will be trashed.
See also:
How to choose the right bean scope?

Related

Why JSF postAddToView event listener method is called during postback calls?

I added postAddtoView event listener to below component. I was expecting the
orderView.populateForm listener method is being called once during creation of the initial view (https://javaserverfaces.java.net/nonav/docs/2.2/javadocs/javax/faces/event/PostAddToViewEvent.html
).
For any postback call where view is restored I do not expect a new component instance is added to view. Hence no event to fire.
However, event listener method is being called for each postback call.
<h:form id="orderForm">
<p:panelGrid id="attributePanel" columns="#{orderView.numberOfGridColumns}">
<f:event type="postAddToView" listener="#{orderView.populateForm}" />
</p:panelGrid>
<p:commandButton ajax="true" value="Create" process="#form" update="#form"/>
</h:form>
OrderView is a view scoped CDI bean. As far as I understand view scoped beans are stored in the partial view state and by default partial view state saving is enabled. (BalusC gives a nice explanation here about the issue Should PARTIAL_STATE_SAVING be set to false?) To see it has an effect, I disabled/enabled partial state saving. It did not help.
Thanks in advance.
PS: I am running on Mojarra 2.2.12/ Glassfish 4.1

One <p:dialog> for multiple beans

I have a <p:dialog> in my general layout. I have its Header attribute hardcoded at the moment.
What I want is to access it from different beans and change its Header at run-time according to my choice.
I am using it to show a loading message to the user at the moment and want to update the loading text according to the current backend processing, e.g "waiting for server's response" etc.
<p:dialog id="main-status-dialog"
widgetVar="mainStatusDialog"
modal="true"
header="Loading..."
draggable="false"
closable="false"
resizable="false"
appendToBody="true">
Now I am calling it from different JSF pages on button clicks e.g <h:link outcome="/generalInformation" value="General Information" onclick="mainStatusDialog.show()" />
It works fine but always Show me "Loading..." because I have a hardcoaded Attribute. So how can I make it dynamic? Please note that I don't want to do it only for one page or bean, but from any page it Access it, i can Change ist Header accordingly.
Thanks!
You can use a managed property with #ManagedProperty of one of your managed beans (e.g HeaderBean)and change it every time accordingly and set the header value to this value, and it whould look dynamically updated.
#ManagedProperty("#{headerBean}")
private HeaderBean headerBean;
And in your header managed bean make a String property value where you will store the value of the header:
#ManagedBean(name = "headerBean")
#RequestScoped
public class HeaderBean implements Serializable
{
private String value = null;
// getter and setter methods
And in your p:dialog:
<p:dialog id="main-status-dialog"
widgetVar="mainStatusDialog"
modal="true"
header="#{headerBean.value}"
draggable="false"
closable="false"
resizable="false"
appendToBody="true">
Take a look at the following liks to find more about it:
The BalusC Code: Communication in JSF 2.0
Injecting Managed beans in JSF 2.0
#ManagedProperty - Inject one request scoped bean into another request scoped bean
EDIT:
You can use RequestContext to update the dialog from your beans, If you take a look at Better ajax operations and callbacks in JSF with PrimeFaces you will see that:
RequestContext API enables developers to do 2 simple things. 1st you can tell what you want to update in the xhtml based on conditions in actions that you define in your Managed Beans.To update a component from serverside, you can just write:
The code you need to update the p:dialog from your managed beans is:
RequestContext.getCurrentInstance().
addPartialUpdateTarget("header_id");
You can also use update attribute in your commandLink like this:
<h:link outcome="/generalInformation" value="General Information" oncomplete="mainStatusDialog.show()" update=":main-status-dialog"/>

Reaching backingbean method in datatable column JSF/PrimeFaces

I am unable to reach my backing beans method when calling it in a <p:commandLink> inside a datatable column.
My commandlink works fine when put outside the datatable, but then I cannot directly pass the selected row variable.
Here is my code:
<h:form id="reviewLists" prependId="false">
<p:messages />
<p:panel header="Beoordelingen" style="margin-bottom:10px;">
<p:dataTable value="#{reviewFinderBean.employees}" var="employee" >
<p:column headerText="Medewerker" >
<h:commandLink value="#{employee.name}" action="#{reviewFinderBean.showReviewsForEmployee(employee)}" />
</p:column>
</p:dataTable>
</p:panel>
</h:form>
When checking the http requests my browser makes I see it does another post (ajax) as expected, I have tried to use prependId="false" as I thaught the generated component names might have been unresovable but that didnt help.
The ajax post is fired but somehow is never resolved to the correct backingbean method on the server
<f:setPropertyActionListener> also doesnt resolve to any property when set correctly and used in the the datatable column.
First of all, get rid of prependId="false". It makes things worse in ajax processing and updates.
In order to fix the problem, you need to rewrite the bean in such way that it returns exactly the same data model (the value behind #{reviewFinderBean.employees}") during processing the form submit as it was during displaying the form. JSF will namely re-iterate over it in order to find the associated row where the command is been invoked.
If you want to keep the bean in the request scope, then you need to recreate exactly the same datamodel in its (post)constructor. If your bean is already in the view scope, then you need to make sure that the getter method is totally free of business logic so that the data model don't potentially change.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 4

java ee - JSF 2.0 ViewScoped Bean after redirect to new window NPE

I use tip from this post https://stackoverflow.com/a/13838907 to open new tab, however when I go back to old one I get nullPointerException and my ViewScoped bean data are lost.
<h:form target="_blank">
<p:commandButton value="open new tab" action="#{otherBean.newTab}" ajax="false" />
</h:form>
<h:form>
<p:commandButton value="this wll cause NPE" action="#{pageBean.action}"/>
</h:form>
Click first button, go back to previous tab, click second button. PageBean is created once again and all data are lost. Both beans are ViewScoped.
Indeed, the view scoped bean in the initial tab/window get killed by returning a String navigation case outcome. You would like to return null or void to keep it alive. Based on the newTab() code as shown in your other question, you need to replace the navigation case by a Faces#redirect() call (assuming that it's indeed OmniFaces which you're using there for Faces#setFlashAttribute()). You only need to set Flash#setRedirect() to true beforehand to instruct the flash scope that a redirect will occur.
public void newTab() throws IOException {
Faces.setFlashAttribute("foo", bar);
Faces.getFlash().setRedirect(true);
Faces.redirect("otherView.xhtml");
}
ViewScope beans only live as long as you post back to same view.
If you post back to other views in your action data will be lost since the ViewScope bean will be recreated.

JSF ViewScope and Bean creation

I have a problem that i don't understand:
I request a new site. A site has a link that opens a dialog. The link is inside a form.
The dialog is not inside the form.
A reduced code example:
<p:outputPanel id="layout-center" >
<h:form>
<p:commandLink id="option_field_user_profile" actionListener="#{controllerBean.getBean('userProfileBean', component).init}" oncomplete="#{controllerBean.getBean('userProfileBean', component).show}" >
<h:outputText value="#{msg.mProfile}"/>
</p:commandLink>
</h:form>
</p:outputPanel>
<p:dialog header="#{userPreferencesBean.header}" widgetVar="#{userPreferencesBean.widgetVar}" appendToBody="#{userPreferencesBean.appendToBody}" resizable="#{userPreferencesBean.resizable}" id="#{userPreferencesBean.xhtmlId}" dynamic="#{userPreferencesBean.dynamic}" modal="#{userPreferencesBean.modal}" closable="#{userPreferenceBean.closable}">
<ui:include src="/WEB-INF/templates/modification/userPreferences.xhtml" />
</p:dialog>
UserPreferencesBean is in ViewScope. My problem is now that the #PostConstruct method from the UserPreferencesBean is called twice with the non-postback request i.e. the Bean is constructed twice although it should be the same view. If i move the dialog inside the form for testing purposes it is called once, like expected. But since the dialog has its own form this is not a solution, for sure.
When the site is loaded and I hit F5, the PostConstruct method is executed once.
Has somebody an idea?
This is caused because you referenced a view scoped bean property in the view build time attribute id of the <p:dialog>. If you fix the id to be static, or to reference a request or application scoped bean property instead, then your view scoped bean will behave as expected.
See also:
JSTL in JSF2 Facelets... makes sense? - for some background explanation on view build time and view render time; the id and binding attributes of UI components are evaluated during view build time.

Resources