JSF Trouble with beans (scope) - jsf

So I was testing my JSF application and suddenly I can't pull the value I stored in the bean anymore. I switched from Request scope to Session scope and I was able to pull a value, but it seems to be the value of the last page I clicked.
File structure goes something like this:
About.xhtml sets a page number stored on the Bean and then calls Layout.xhtml which calls Bean.Method() to get Content_About.xhtml to load some text to the page depending on the page number declared in the About.xhtml file.
To my understanding the Request scope should work as long as I don't need to access the stored information past the page loading, but it is acting as if the page number hasn't been set.
With a Session scope declared, it loads the text, but it seems as if it is building the page, then changing the stored value in the bean. It requires that I click on the page I want twice to get the correct information on a page.
Any help appreciated.
Further investigation: I am able to do the following, but it shows the correct page number before and after the method call to load the content.
Page Number: #{MainBean.getPage()}
<h:form>
<ui:include src="#{MainBean.Content()}"></ui:include>
</h:form>
Page Number: #{MainBean.getPage()}

Accepting that the ui is built first, using the default value of the stored variable, I proceeded to set the value in the ui declaration when layout is called.
I had something like:
#{MainBean.setLevel(0)}
#{MainBean.setPage(1)}
<ui:include src="Layout.xhtml"></ui:include>
and changed it to:
<ui:include src="#{MainBean.setLayout(0,1)}"></ui:include>
public String setLayout(int lvl, int pg)
{
setLevel(lvl);
setPage(pg);
return GetPath()+"Layout.xhtml";
}
This allows the bean's variable to be set during the construction of the ui and carry forward through the rest of the request.

Related

jsf get disabled field values in requestscoped bean

Could you please give me some directions on how to pass values from disabled or readonly input fields in xhtml page to requestscoped bean?
I thought that I can bypass jsf checking the field state by disabling
fields in javascipt code on form open and then submit form, but that
did not help too.
I cannot use view scope, because I would have to set then almost
every page in my application in view scope.
It is very inconvenient to use hidden fields for this purpose,
because it would double the number of fields on the page.
Maybe I have missed some clean solution?
Thank you in advance for any help.
Disabling fields using JavaScript didn't work probably because you didn't enable them just before sending a form. Values of disabled fields are not sent (see input documentation).
For example the following code works perfectly well:
<h:form>
<h:inputText id="disabledinput" styleClass="disabled"
value="#{someBean.property}"></h:inputText>
<h:outputScript>
$('.disabled').attr('disabled', 'disabled');
</h:outputScript>
<h:commandButton action="#{someBean.action}"
onclick="$('.disabled').removeAttr('disabled'); return true;"
value="Submit" />
</h:form>
onclick attribute executes JavaScript code that enables input just before sending the form.
If you use AJAX request you have to restore disabled state using oncomplete or similar.
The problem with this solution is that user can manipulate the value. E.g. she/he can use javascript console in a browser to change the input to enabled or use some tool (e.g. curl) to prepare or tamper request. So if the value is sensitive or should never be changed by the user consider storing the value in the session.
IMHO if the value was provided by the user in one of the previous steps then it doesn't matter that much. However, if value is calculated (like total value or something) you should not depend on its value as users could change it. Personally I would prefer to store the value on server side (in session or in flash).

Set current displayed tab programmatically in p:wizard

Is it possible to set current displayed tab programmatically in <p:wizard>?
For example, I want that for two different request to the same page which contains a wizard, to have a different tab selected.
What I am currently trying to do, is to have a wizard with many tabs, in the second tab I have a redirection to another page, so when I come back I want to come to the last step which caused the redirection.
Can you please help me ? Thank you a lot !
According to primefaces documentation there's a step attribute for p:wizard tag, which specifies the step of the wizard you're currently in.
attribute: step
default value: 0
type: String
description: Id of the current step in flow
You must bind this attribute to a value of your backing bean and maintain it during redirection and coming back. If your wizard's bean is #ViewScoped you'll loose that info during redirection step, so you have to pass it using a view param or flash scope.
My answer would most probably not meet your complete requirements, but, nonetheless, it may point you towards solution to your problem.
As far as I know, the PrimeFaces Wizard UIComponent is designed for a workflow of one page. That effectively means that inputs will be handled by a backing beans that is in a view scope.
This way, making a redirection on a certain step will clear all data inputs, because your view changes and the old one is destroyed.
Anyway, a means of setting a current tab for display is step attribute of Wizard component. So,
<p:wizard step="#{wizardBean.currentStep}" >...</p:wizard>
will force the wizard to show you step which you specified in your bean. You may be able to get it by using, for example, a view parameter, like in
<f:viewParam name="step" value="#{wizardBean.currentStep}" />
But it will make sense if lifetime of your bean is more that for a view, for example, the bean could be put in session scope.
That said, maybe it is a better idea to do login beforehand. Or, if it is absolutely necessary to do it in step 2 of your wizard, provide for a built-in login functionality in a page itself, or in a popular window?
Also, programmatically the setting you speak of can be achieved via a binding of component to your backing bean and setting the step value in the backing bean, for example, in a preRenderView event.

JSF: Bookmarkability with ViewScoped

I am trying to make my app "Bookmarkable", and i am using view parameters to achieve it.
And i think i still do not get the right way to do it right in JSF, even after reading this, and many others.
My problem is that the get parameters get lost after any non-ajax postback, i mean, the parameter value is still set in the bean and the app works correctly, but it gets removed from the URL making the URL invalid.
For instance, having an URL like http://company.com/users?id=4, as soon as that page executes a non-ajax postback (for uploading data, for instance) the URL becomes just http://company.com/users. The app continues to work correctly, but the link is not any more "Bookmarkable".
Is there any way to prevent the non-ajax postbacks removing the viewParams from the URL?
My use case is to be able to bookmark a page to EDIT an object, and there i need to be able to upload data (if not i would not use non-ajax postbacks). I know i would not need any postback if i would want to bookmark the page to only VIEW the data of the object, but that is not my case.
I could also do a redirect to the same page with the same params, and let the app to recreate the view scoped bean, but then i really do not see any benefit over request scoped beans...
Any suggestion is very appreciated.
This behaviour is "by design". The <h:form> generates a HTML <form> element with an action URL without any view parameters. The synchronous POST request just submits to exactly that URL which thus get reflected as-is in browser's address bar. If you intend to keep the view parameters in the URL, while using ajax is not an option, then you basically need to create a custom ViewHandler which has the getActionURL() overridden to include the view parameters. This method is used by <h:form> to generate the action URL.
public String getActionURL(FacesContext context, String viewId) {
String originalActionURL = super.getActionURL(context, viewId);
String newActionURL = includeViewParamsIfNecessary(context, originalActionURL);
return newActionURL;
}
Or, as you're based on the comments already using OmniFaces, you could also use its <o:form> component which basically extends the <h:form> with the includeViewParams attribute which works much like the same as in <h:link> and <h:button>.
<o:form includeViewParams="true">
...
</o:form>
This way all <f:viewParam> values will end up in the form action URL.
See also:
Handling view parameters in JSF after post

JSF page navigation failing with NullPointerException

I wrote two pages...one a form where data submitted and second just to confirm the transaction actually carried out some calculation.
I have a managed bean i.e. FormDataBean and a class Reservation.java from which i instantiate for each booking made. Now I have at the end of a form a submit button:
<h:commandButton value="Submit" action="confirmation"/>
in the bean I have setters and getters as usual. in a method i defined I create an instance of Reservation, then set the beans variables to the instance variabels, like
reservation.startDate = startDate;
reservation.endDate = endDate;
reservation.checkRange();
The last method, i.e. checkRange() will use the assigned values to instance variables to carry calculation. it should return a string successful or failure.
Now when I enter data in the form, and press submit, it just refreshes the page but nothing is submitted. because it doesn't go to next page :(
Any idea what is happening? I don't need to define a navigation rule, because in other project, I carry out simple calculation and display result in next page and it worsks! Please advice
Thanks,
Your are missing to tell us some of the more important details so the answer is a kind of guesswork.
As you don't use navigation rules I assume you are using JSF 2, aren't you?
With JSF 2 you can directly set the new navigation target, without navigation rules. A forward to "confirmation" should work if your outcome file is named confirmation.xhtml. Check that. With a navigation rule you could forward it do a different file.
This part should work regardless of the rest.
For the bean not getting any values make sure that you are using the correct scope either through annotation or entry in your faces-config.xml. As you have a quite unusal validation mechanism you probably have to use the session scope.
The correct way would be using an actionlistener that does your checks and then sets the navigation depending on your checks. The bean scope could be more restrictive then.
Did you try action="confirmation?faces-redirect=true"?

JSF: bean scope; session vs request

I have a managed bean called UserSearchHandler, it has a doSearch method that populates UserSearchHandler.searchResults which are displayed in a table on the userSearch.xhtml page.
I have another managed bean called UserHandler, it has a showUser method and so on.
In the search results table, the user name is a link that, when clicked, is supposed to show user details on a userView.xhtml page. The table and link looks like this:
<p:dataTable var="user" value="#{userSearchHandler.searchResults" >
// ... and so on ... then
<h:commandLink value="#{user.firstName}" action="#{userHandler.showUser}">
<f:setPropertyActionListener target="#{userHandler.userIdToShow}" value="#{profile.id}"/>
</h:commandLink>
Everything works fine when the managed beans are set to session scope.
However, when I change the scope on the beans to request, the search works and the table gets populated, but when I click on the name link nothing happens. I put a break point on the userHandler.showUser method and it never gets hit when the userSearchHandler is set to "request" scope.
Can anyone help explain why this is, or what I'm doing wrong?
That's because the #{userSearchHandler.searchResults} is empty during the new request and therefore JSF is unable to locate the associated row where the commandlink is been invoked in order invoke the action (and to pass/set properties if any).
You need to ensure that the same #{userSearchHandler.searchResults} is precreated during bean's construction/initialization. If it's to be created based on a specific set of parameters, then you've to pass them along with the form as well.
That's exactly the reason why solutions like Tomahawk's <t:saveState /> and new JSF 2.0 view scope exist.
See also:
What are the main disadvantages of JSF 2.0?
I have a couple of ideas. If you're using a in your navigation you can try taking that out. Doing so would mean the browser will not make a new HTTP request when it renders the second window. It is the new HTTP request which clears the request scoped beans by. If that is not an option, you may be able to pass a parameter in your link such as a record id, which could allow you to pull data from your data source matching that id.

Resources