jsf navigation to another method - jsf

I am developing an application using jsf 2.0 and i have the following situation:
I have 2 managed beans.
On the first managed bean i have a method that process some data and then store the result in session.After the data was stored in session i need to invoke a method on the second bean that will display the information from session.
The problem is that if i return a string from the first bean method that correspond to the seconds bean method view the data is not processed, and of course not displayed.
What i need is some navigation rule that from the first bean would redirect me to the second bean method, and the second bean method would return a string with the corresponding view name.
update
maybe a
<f:event listener="#{secondBean.methodToBeInvoked}" type="preRenderView" />
would help me achieve that.
Is this the right approach ?

Related

Does JSF prevent calls to unrendered managed bean actions by tampered requests

A method in a managed bean is protected by JSF? See the code:
Managed Bean
#ManagedBean
public class My {
public void test() {
System.out.println("called");
}
}
XHTML
<h:form>
<h:commandButton rendered="true" action="#{my.test}" value="Teste" />
</h:form>
If the button is not rendered (rendered="false"), a HTTP POST request (as the button would do) can be done and call the test() method?
In other words, JSF prevents calls to managed beans methods by tampered requests?
In other words, JSF prevents calls to managed beans methods by tampered requests?
Yes.
JSF re-evaluates the component's rendered attribute during apply request values phase. If it's false, then in case of UICommand components the ActionEvent simply won't be queued, regardless of whether the (tampered) HTTP request parameter indicates that the button is being pressed.
JSF has similar safeguard against tampered requests on the disabled and readonly attributes, also those of UIInput components. And, in UISelectOne/UISelectMany components, JSF will validate if the submitted value is indeed part of the provided available options.
JSF does this all also with help of the view state. If JSF were stateless, there would be more risk that one or other may fail if those attributes suddenly become request scoped instead of view scoped.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 5
Validation Error: Value is not valid
How to disable/enable JSF input field in JavaScript?
What is the usefulness of statelessness in JSF?

View-scoped bean recreated on POST when URL parameters not used

I have a view-scoped JSF-managed bean that's backing an xhtml view where I read one parameter from the URL using f:viewParam.
The view presents a form to the user. However, when the user submits the form by pressing the p:commandButton it seems that the view-scoped bean is recreated (I added a #PostConstruct annotation to verify this) and so doesn't remember the instance variable read from the f:viewParam (invId in the code below).
I originally navigate to the view with a GET that includes a URL parameter but the POST message that's send when the user presses the p:commandButton doesn't include the URL parameter. So I am thinking that when the JSF runtime doesn't see the URL parameter on the POST it considers this to be a different view and is recreating the JSF-managed bean. When I change the view scope to session-scoped the code works.
Here's the code:
view
<f:metadata>
<f:viewParam name="invId" value="#{registerBean.invId}"/>
</f:metadata>
<h:form id="registrationForm">
....
<p:commandButton value="register" action="#{registerBean.register}"
icon="ui-icon ui-icon-newwin" ajax="false"/>
</h:form>
backing bean
#ManagedBean
#ViewScoped
public class RegisterBean implements Serializable {
#ManagedProperty(value="#{invId}")
private String invId;
...
update
It turns out that this wasn't related to the URL parameters at all. Following BalusC advice below I removed the c:when tags my view was using (relying on rendered attributes instead for the same effect), and now the view-scoped bean is no longer recreated and the invId field is properly retained.
The problem is not visible in the code posted so far, but it's for JSF 2.0/2.1 a known issue that a view scoped bean will be recreated when one of its properties is been bound to an attribute of a taghandler like JSTL <c:if> or Facelets <ui:include> or a view build time attribute of JSF component, such as id and binding, while partial state saving is enabled (as by default).
The background explanation is that any EL expressions in those attributes are executed during building and restoring the view. As view scoped beans are stored in the view and thus only available after restoring the view, such an EL expression evaluation would cause a brand new and separate view scoped bean to be created. This is basically a chicken-egg issue. It's fixed in the upcoming JSF 2.2.
There are basically 3 solutions:
Change the view accordingly so that those EL expressions are only evaluated during view render time. E.g. replace <c:if>/<c:choose> by rendered.
Or bind those attributes to a request scoped bean (design notice: you can just inject a view scoped bean as a managed property of a request scoped bean).
Turn off partial state saving, if necessary only for the particular view.
See also:
JSTL in JSF2 Facelets... makes sense?
#ViewScoped fails in taghandlers

JSF 2.0 Managed Property object has two different instances, when I to open page and to do ajax request

all
I novice in JSF2 (used Mojarra + primeFaces on tomcat7) and I get strange behavior of ManagedProperty object:
#ManagedBean
#ViewScoped
public class CreateFactMB implements Serializable{
#ManagedProperty(value="#{collectionFactTable}")
private CollectionFactTable collectionFactTable; //SessionBean
...
//setters/getters
I printed object when I open page (refresh brouser) I see one instance of collectionTree
mbeans.CollectionFactTable#12803ba
But when I do ajax request
<p:commandButton id="btn1" value="Save" update="growl"
actionListener="#{createFactMB.doUpdate}" />
In doUpdate I see another instance of my collectionTree
mbeans.CollectionFactTable#625c49
It's problem because I can not do change while ajax action (because I have just copy)
Anybody can help me? What I'M doing not right?
I think you have a misunderstanding of how SessionScoped persistence works in JSF. This behavior is expected and normal.
At the beginning of the request all of the managed beans are instantiated regardless of scope. In the Restore View phase, the session based persistence values are set to the new managed bean object, effectively restoring the SessionScoped bean back to its last state before the last Response was sent.
Once the Response is complete and has been sent the data in these managed bean instances is persisted and the objects dereferenced for garbage collection. The process begins anew at the next request, regardless if it is Ajax or not.

JSF Required=Yes not working inside a datatable?

I searched everywhere but could not find a solution to this. I am trying to used
required=yes to validate whether a value is present or not. I am using it inside inputtext.
The problem is it does not work inside a datatable. If I put the text box outside the datatable it works. I am using JSF 1.7 so I don't have the validateRequired tag from JSF 2.0.
I even used a validator class but it is still not working. Does anyone know why does required=yes or validator='validationClass' inside a inputtext inside a datatable is not working.
I appreciate the help.
Thanks.
First of all, the proper attribute values of the required attribute are the boolean values true or false, not a string value of Yes. It's an attribute which accepts a boolean expression.
The following are proper usage examples:
<h:inputText required="true" />
<h:inputText required="#{bean.booleanValue}" />
<h:inputText required="#{bean.stringValue == 'Yes'}" />
As to the problem that it doesn't work inside a <h:dataTable>, that can happen when the datamodel is not been preserved properly (the datamodel is whatever the table retrieves in its value attribute). That can in turn happen when the managed bean is request scoped and doesn't prepare the datamodel during its (post)construction which causes that the datamodel is null or empty while JSF is about to gather, convert and validate the submitted values.
You need to ensure that the datamodel is exactly the same during the apply request values phase of the form submit request as it was during the render response phase of the initial request to display the form with the table. An easy quick test is to put the bean in the session scope. If that fixes the problem, then you definitely need to rewrite the datamodel preserving logic. You could also use Tomahawk's <t:saveState> or <t:dataTable preserveDataModel="true"> to store the datamodel in the view scope (like as JSF2's new view scope is doing).
Finally, JSF 1.7 doesn't exist. Perhaps you mean JSF 1.2?

JSF 2 : Accessing managed bean's instance in the phase listener object?

Is it possible to get a reference to the to-be-executed managedbean in the before-invokeApplication-phaselistener ?
Before the invoke application phase, it should be clear which managedBean that is going to execute the method.
For the sake of the example, assume there's 1 main manage bean to handle 1 jsf page.
So what i need is basically :
The user access the program from the menu
Because it's accessed from the menu, the main manage bean's init() method gets called to initialize stuffs like preparing data, doing authorization checks
Subsequent submits dont need to call the init() method anymore until it's reaccessed from the menu
To implement the point #2, im thinking of intercepting one of the phases
I've checked the API docs about getting the managed bean in the phases implementation, but i couldnt seem to find any.
After typing this question, i realize i could do this in #PostConstruct or the managed bean's constructor, but that would do only at the first time the bean is constructed, and my need is to call the method everytime the jsf is being accessed from the menu.
Any suggestions ?
Regards,
Albert Kam
You can access your managed beans via the ELContext/ELResolver. This is explained nicely in the MyFaces wiki (also works in vanilla JSF).
For example:
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
NeededBean neededBean = (NeededBean) FacesContext.getCurrentInstance().getApplication()
.getELResolver().getValue(elContext, null, "neededBean");
See the MyFaces wiki entry for further explanation, and implementations for other JSF versions.
Your idea of using #PostConstruct is a good one. Consider changing your scope to something liked #ViewScoped, so the logic is executed everytime you navigate to that view.
Also, have a look at the PreRenderViewEvent (for JSF 2). This code is embedded in your facelet page:
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}"/>
<f:event type="preRenderView" listener="#{bean.doSomething}"/>
</f:metadata>
The f:event listener is executed before every page view.

Resources