jsf - pass request param to bean in action method not working - jsf

I have a GET parameter url.xhtml?key=test which is displayed correctly on my site using:
value="#{param.key}"
Now i want to pass that param as an argument in an action method call to my bean inside a commandButton?
But it is always empty in the bean?
action="#{bean.action(param.key)}"

That EL expression is evaluated during the request of processing the form submit, not during the request of displaying the form. The request parameter is apparently not been retained in the subsequent request.
You can do that by adding it as a <f:param> to the command component:
<f:param name="key" value="#{param.key}" />

Related

How to invoke a managed bean action method in on* attribute of a JSF component

I'd like to invoke a managed bean action method in an on* attribute. In my particular case I need to logout an user if the user is idle for 3 minutes as below:
<p:idleMonitor onidle="#{mybean.processTimeOut()}" timeout="180000" />
However, the managed bean action method is immediately invoked as the page loads. How is this caused and how can I solve it?
Like as all other on* attributes on all JSF components, the onidle attribute must represent a JavaScript callback, not a JSF backing bean action method. Any EL expressions in on* attributes would be evaluated immediately as String value expressions during generating the HTML output in expectation that they print (part of) JavaScript code.
It's exactly like as if you're doing <h:outputText value="#{mybean.processTimeout()}">. If you had removed the parentheses (), you'd have faced a PropertyNotFoundException which was also a hint at its own of it being evaluated as a value expression instead of a method expression.
In order to invoke a JSF backing bean method using JavaScript, you need an additional <p:remoteCommand>.
<p:idleMonitor onidle="processTimeout()" timeout="180000" />
<p:remoteCommand name="processTimeout" action="#{mybean.processTimeOut}" />
If you're not on PrimeFaces, head to the alternatives posted in this related answer: How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?

Passing request scoped variable passed as EL action method parameter does not work

I am using JSF 2.2 on Glassfish 4.1.
I am trying to pass in a query parameter to as an action method argument as follows:
// Example 1. This does not work.
// at url http://localhost:8080/app/order.xhtml?email=test#email.com
<p:commandButton value="Place order" action="#{orderManager.placeOrder(param['email'])}" />
(Know that param is an implicit EL object.)
In the server log I have configured it to print the method parameter, but I can see that an empty string was passed-in, not "test#email.com" as I expected.
I have confirmed that my overall configuration is working. If I replace the above snippet with the following, then "test#email.com" is output in the server log:
// Example 2. This works.
<p:commandButton value="Place order" action="#{orderManager.placeOrder('test#email.com')}" />
I have also confirmed that my use of EL implicit objects is feasible. The following snippet works if I retrieve the parameter from the FacesContext (after removing the email parameter from placeOrder's signature, of course):
// Example 3. This works.
<p:commandButton value="Place order" action="#{orderManager.placeOrder()}" >
<f:param name="email" value="#{param['email']}"/>
</p:commandButton>
And here is a final mystery, one that truly confuses me, if I use the following snippet, I can retrieve the "email" parameter from both the method parameter and the FacesContext, but recall that the method parameter wasn't retrievable in Example 1!
// Example 4. This works, and BOTH parameters are retrievable!
<p:commandButton value="Place order" action="#{orderManager.placeOrder(param['email'])}" >
<f:param name="email" value="#{param['email']}"/>
</p:commandButton>
Can I pass in an implicit JSF EL object as an action method parameter?
And do you have an explanation for why it seems to work in Example 4, but not Example 1?
The action attribute is evaluated during apply request values phase of the HTTP request triggered by the form submit, which is thus a different HTTP request than the one which produced the HTML output with therin the form (and having the email parameter present in the request).
The <f:param> tag is evaluated during render response phase of the HTTP request which needs to produce the HTML output with therein the form. This thus ends up "hardcoded" in the generated HTML output (on contrary to the EL method arguments in the action attribute!). When the user submits the form, this just gets passed back to the server as a plain vanilla String request parameter (which you would need to convert back if it was originally a complex type).
This has got nothing to do with whether the value is an implicit EL object or not.
That said, there are 2 other ways:
Pass it as hidden input (no, not with <h:inputHidden>).
<h:form>
<input type="hidden" name="email" value="#{param.email}" />
...
</h:form>
Set it as property of a view scoped bean, it'll stay in bean as long as the view lives.
<f:metadata>
<f:viewParam name="email" value="#{viewScopedBean.email}" />
</f:metadata>

Bean's method that returns to the previous page

After performing the appropriate action, the method of my bean must ensure that the browser back to the previous page. How can I handle it?
I am using the CDI Conversation.
Pass the current URI as request parameter along during navigation to the page containing that action.
<h:link value="Go to page containing that action" outcome="pageContainingThatAction.xhtml">
<f:param name="from" value="#{request.requestURI}" />
</h:link>
(use #{view.viewId} instead if you want to pass the view ID)
Set and remember that parameter representing the URI in the view/conversation scoped managed bean.
<f:metadata>
<f:viewParam name="from" value="#{bean.from}" />
</f:metadata>
Finally redirect to that URI in that action method.
public void thatActionMethod() throws IOException {
// ...
externalContext.redirect(from);
}
After asking you a couple of question in comments, I think what you want to do is :
On your button, specify the attribute action to a function in your bean that return a String.
The String returned need to be the navigation path to the page you want to be redirected.
If the validation is wrong on button click, then simply return null and it will stay on same page.
Make sure you define the proper navigation rule in faces-config.xml
See this tutorial for how to configure navigation rules.
See Primefaces commandButton doc for info on action tag.

h:commandButton action method not called on request scoped bean

I have a h:commandButton on a jsf page. And it needs to be rendered based on a condition. The property on the condition is a hidden input to the page. The action method on the button is not called when the rendering condition is specified.
Any ideas?
here is the sample code:
<h:commandButton value="Button"
action="#{bean.method}"
rendered="#{bean.conditon}"
type="submit"/>
<h:inputHidden value="#{bean.condition}" />
I understand that your bean is request scoped, otherwise you wouldn't have this problem. This is a timing problem.
The rendered attribute is also determined during "apply request values" phase of JSF lifecycle. However, the submitted values are only been set in the model during "update model values" phase of JSF lifecycle, which is later. Thus, when rendered attribute is evaluated, it doesn't get the submitted value from the hidden input, but instead the property's default value.
If it's not an option to change the request scope to the view scope, then you'd need to salvage this problem differently. One of the simplest ways changing the <h:inputHidden> to be a <f:param> and inject the value via #ManagedProperty on #{param} map:
<h:commandButton value="Button"
action="#{bean.method}"
rendered="#{bean.conditon}"
>
<f:param name="condition" value="#{bean.condition}" />
</h:commandButton>
(note that I omitted type="submit" as it's the default already)
with
#ManagedProperty("#{param.condition}")
private boolean condition;
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated - point 6

commandLink is not fired in a page with a param in its URI

When I call a method in a page with a param in its URI, the method is not invoked unless I pass the parameters of the uri again. For example if I have:
http://maywebsite/myapp/mypage.xhtml?mykey=myvalue
This method results in error (obviously because it renders the page again without params, but the method foo is never invoked):
<h:commandLink value="Do Action" actionListener="#{mybean.foo}"/>
So I added an ajax to only update the component, but the button is not getting fired:
<h:commandLink value="Do Action" actionListener="#{mybean.foo}">
<f:ajax render="somecomponent"/>
</h:commandLink>
When I passed the param values again, the button invokes the method just fine:
<h:commandLink value="Do Action" actionListener="#{mybean.foo}">
<f:param name="mykey" value="myvalue"/>
<f:ajax render="somecomponent"/>
</h:commandLink>
However, this button is included (ui:include) in many pages with different param keys and values. How can I invoke the method without passing the param values?
Im using glassfish 3.1.2, jsf 2.0
Apparently the bean is request scoped and the parameter plays a role in the way how the command link is rendered (e.g. by the rendered attribute on one of its parent components, or by a dynamic include of the template containing the command link).
All those conditions are namely re-evaluated during apply request values phase of the form submit. The developer has to make sure that all those conditions are exactly the same as when the form was presented to the enduser. So, when the bean is request scoped and the parameter is absent, then the command link appears as non-rendered in the component tree and this way its action won't be invoked.
Putting the bean in the view scope is the easiest way to fix this (unless you're using a dynamic <ui:include>, this is then more complicated, you'd need to turn off partial state saving for the particular view).
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 5

Resources