Given the following scenario : A jsf component's (e.g a CommandButton) render attribute depends on an application scoped managed property. Since the property is shared across all sessions, the following might easily happen : User A loads a jsf page and the button's render attribute is true, so it is rendered. Now user B also loads the page and the render attribute is still true. Now user A clicks the button which causes the property to change its value and the button is not rendered anymore. User B still has the old view and although the render attribute is false now, he can click the button because he didn't update his view in the meantime. What happens now if user B clicks the button?
I thought the button's action is fired anyway because the render attribute is just used for rendering the button and has no influence anymore, once the page is rendered. But after doing some tests it seems to me that the render attribute is also checked again after clicking the button and if the attribute is false then, the action is not performed. Can someone confirm this ?
Disclaimer: I'll ignore the strange design for now.
But after doing some tests it seems to me that the render attribute is also checked again after clicking the button and if the attribute is false then, the action is not performed. Can someone confirm this ?
Yes, that's correct. This is part of safeguard against possibly tampered requests wherein the hacker is trying to simulate the invocation of an action component which is actually not rendered by the server side (such as an admin-only command button which is only rendered when the current user has the admin role). The rendered (and disabled and readonly) attributes are always re-checked during processing the form submit.
In your particular case, you'd like to have a copy of the condition responsible for the rendered attribute in the view scope so that only this copy will be used as long as you're interacting with the same view. This can be achieved by just injecting the application scoped property as a managed property of a view scoped managed bean and then referencing it in the rendered attribute instead.
#ManagedBean
#ViewScoped
public class ViewBean {
#ManagedProperty("#{appBean.rendered}")
private boolean rendered;
// ...
}
with
<h:commandButton ... rendered="#{viewBean.rendered}" />
Related
I have two view htmls(V001 & V002) both of which are to be rendered using the same jsf page. There is a continue button in my JSF Page which performs the action of storing the V001 DOM in Cache and fetches the V002 from Content server and displays it to the user. This is achieved through a managed bean.
In view V002, I have a button which I need to be rendered based on whether the view is V002 or not.
However the issue is the rendered condition is executing before the continue action and hence always evaluate to false since the view change from V001 to V002 happens only when the continue button action is executed.
NB: My bean is request scoped and I am using JSF 1.1
I'm using PrimeFaces 5.
I would like to open a dialog when a button is pressed.
<p:commandButton value="add upload" actionListener="#{theForm.openUpload}" >
public void openUpload() {
this.item = new Item();
RequestContext.getCurrentInstance().openDialog("uploadForm");
}
There will be a save button in the dialog to save the inputs.
<h:commandButton value="#{text['button.add']}" id="add" styleClass="btn btn-default" actionListener="#{theForm.confirmAdd}"/>
public void confirmAdd() {
RequestContext.getCurrentInstance().closeDialog("uploadForm");
}
My managed bean is #ViewScoped. Will the command button break the view scope if the dialog is in an external file as done by PrimeFaces Dialog Framework? Whenever I click the "add upload" button, the #PostConstruct method is called again just like the scope is lost.
Comments section of the official blog says it won't break the view scope, but here the forum a core developer says openDialog() creates a new view, therefore it breaks the view scope.
Can someone confirm this?
PrimeFaces' Dialog Framework basically shows another view in an <iframe> tag. I wouldn't call that breaking a view scope, but the dialog view will have it's own scope, because it is practically a different page. That may or may not be desirable in different circumstances. As PrimeFaces' User Guide says:
Dialog Framework (DF) is used to open an external xhtml page in a
dialog that is generated dynamically on runtime.
p:dialog
Exists in the same view scope.
Can easily have the same conversation context.
Statically defined, the dialog and its components get created immediately on view build. You can only delay rendering, e.g. with a dynamic=true.
Declarative definition means it's more readable and maintainable, because the dialog's existence is not hidden somewhere in java code.
Dialog Framework
Has its own view scope.
Developer has to worry about passing parameters, propagating conversation context. (And PF didn't support includeViewParams until 5.1.)
Dynamic creation means dialog and its components won't be created until the dialog is actually opened, but a new dialog will be created each time it's opened. If the dialog is opened many times, the total performance hit will be larger, plus many dialog views can exhaust JSF view limit and expire other views.
Imperative dynamic creation allows for more resource efficiency in certain cases. E.g. show one specific dialog out of dozens based on user input. Or a rarely used dialog, which could be opened from any page of an application.
My recommendation would be to use p:dialog by default. Only use Dialog Framework in cases like I mentioned in the last bullet point.
That's normal because you have already instantiated theForm(ManagedBean) in your main.xhtml. SO the scope is already used within the main.xhtml.
When you clicked to open the dialog: the dialog is a new view, then a new instance of theForm (ManagedBean) is created.
We had some problems with #ViewScoped in the JBoss 7.1/Mojarra 2.1.7 and we changed to Omnifaces
I suggest you to use #org.omnifaces.cdi.ViewScoped instead of #javax.faces.bean.ViewScoped
I tested with both your example and here on the log you can see the difference:
Log with #org.omnifaces.cdi.ViewScoped
18:58:40,887 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-2) #postconstruct
18:58:40,890 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-2) openUpload()
Log with #javax.faces.bean.ViewScoped
19:01:19,753 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-5) #postconstruct
19:01:19,753 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-5) #postconstruct
19:01:19,754 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-5) openUpload()
I have a jsf page with few input components and two h:selectOneMenu components.
On selection of a value in the first drop down I'm calling a valuechange listener and submitting the form. Then I populate the value into the other drop down depending on the value selected from the first drop down. Now I enter other fields and click on the submit button.
It throws me the below mentioned exception.
My Backing bean is in Request scope. I hope it will work fine for me if I change it to session bean which is not right to do in my application. I'm populating the data to SelectItem variable from the "ValuechangeListener" method.
JSF version is 1.2, I can't upgrade it to 2.0 at this point.
RequestScope in this case is not enough. You need at least ViewScope.
This is because the Bean will get reset with every request. The listeners of your Bean will be called for another instance of that bean and will change that. After that you do some changes in the browser and the next time you send a request, your bean has already been destroyed. Thus everything you did in your listeners got lost and that's why you run into problems.
If you work with ajax, or stay on the same page and keep manipulating it, then you should switch to a higher scope.
Does anyone have a solution for such a problem:
In my app I'm using a complex, programmatically build dashboard based on the primefaces dashboard. To overcome problems with nonunique id's of the panels building the dashboard, I'm binding this component to a request-scoped bean. I'd also like to rebuild the dashboard based on some changable parameters after clicking a commandButton.
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired (in the Invoke Application phase). So, although the dashboard is rebuild eventually, it's not beeing refreshed in the rendered response.
On the other hand, if I try to set immediate attribute of the button to true, the actionListener is fired in the Apply Request Values phase, but still after the getter. Than the lifecycle goes directly to the Render Response phase, and the outcome is the same.
Anyone?
Thank you for the answer. Let me add a bit detail to my problem.
I store a model of a sports tournament as a property of a session scoped bean. It goes like this: the bean has a property "tournament". This class has a list of groups, each with it's table of matches. The idea was to use three different programmatically built components as renderers of this tournament model.
The dashboard would be used for drag-and-drop edition of contestant placement in groups. For viewing match tables and editing their matches I use a tab panel, with panel grid for every table. Finally, I use a panel grid to show a tournament tree. Every of those three components render some part of the model for the user to edit.
Since the model (and therefore those rendering components) are dynamically build depanding on chosable parameters like number of groups for example, i had a problem with id uniqnes when binding them to a session-scoped bean. So I bound them to a request scoped bean. With every request changing the model (mostly ajax) I wanted to rerender those components depending on the parameters set by the user (also stored in the session scoped bean).
The problem is, that when I rebuild the model in the invoke application phase (in a action listener fired by the "rebuild-my-model" button), the components bound to a request-scoped bean have already been "get-ed" from the bean (or so it seems), and they do not refresh on the page.
I would be very gratefull for a clue to what i'm doing wrong, and perhaps a suggestion, if the approach mentioned above is completelly stupid :)
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired
I'm not sure why exactly that forms a problem for you. Perhaps you're incorrectly doing business logic in the getter method instead of in the action listener method? Or perhaps you're manually creating the component instead of referencing the JSF-created one and thus always overridding the one in the JSF view?
A proper JSF getter method basically look like this:
public UIComponent getDashboard() {
return dashboard;
}
It should not contain any other line of code. The same applies to the setter method by the way. Any actions wherein you need to manipulate the component's children needs to be done in an action(listener) method, not in a getter/setter method.
I guess I knew the difference, but right now I find myself confused. :P
Both of them seem to be do the same thing, except that partialSubmit is used on submit buttons to submit the form using AJAX and autoSubmit is used on editable components, which submits only its own contents. Am I right in saying this?
The accepted answer isn't 100% correct for ADF. The partialTriggers attribute is involved in the lifecycle.
From Enabling Partial Page Rendering Declaratively
The autoSubmit attribute on an input component and the partialSubmit
attribute on a command component are not the same thing. When
partialSubmit is set to true, then only the components that have
values for their partialTriggers attribute will be processed through
the lifecycle. The autoSubmit attribute is used by input and select
components to tell the framework to automatically do a form submit
whenever the value changes. However, when a form is submitted and the
autoSubmit attribute is set to true, a valueChangeEvent event is
invoked, and the lifecycle runs only on the components marked as root
components for that event, and their children. For more information,
see Section 4.4, "Using the Optimized Lifecycle".
They are both AJAX enabled calls occurring from custom properties of custom JSF components. The autoSubmit essentially asynchronously postsback content specific to the component for keeping the server side managed bean values current with the content within the component on the client side.
A partialSubmit is another asynchronous AJAX call that will serve to immediately postback a component value on some kind of component event, like losing focus on an ICEFaces inputText component for example.
The interesting thing to note is that the entire ViewState is posted back on each type of asynchronous submit, so if the values of other components HAD changed on the page before the submit, the bound server side managed bean properties will have their values refreshed as well, even though the client side components MAY not be refreshed to reflect any server side data changes that may have occurred.
In fact, the entire JSF server side lifecycle occurs on each postback, read the following article on implementing a debug PhaseListener that allows you to see what Phases are occurring after each asynchronous submit operation occurs.
http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html