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

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

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?

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

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

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

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}" />

Modify dynamically JSF snippets by h:commandlink

I have a h:commandlink control in page1. the control uses f:ajax to call to the following h:panelgroup :
I have a h:panelgroup control in page2 (a snippet), which has a ui:include within it.
I have a h:panelgroup control in page3 (a snippet), which has a ui:include within it.
Now according to the choices made on page1, I would like to switch the snippets by clicking on the h:commandlink control.
I have a BIG problem there: it seems that only if I click twice on the commandlink, only then the snippet changes - and not on one click.
I have tried to remove the f:ajax to render the panelgroup, and still it does not work...
There are two potential causes of this problem.
The <f:ajax> is fully re-rendering another <h:form> than where it is sitting in. This way the view state of the other form will get lost which would require invoking the action on the other form twice before it really get executed.
The solution is to not re-render the other <h:form>, but only some container component in that form. E.g.
<h:form id="otherForm">
<h:panelGroup id="content">
...
<h:panelGroup>
</h:form>
with
<f:ajax render=":otherForm:content" />
When there's a rendered attribute on the <h:commandLink> or any of its parent components, then it must evaluate true during the apply request values phase of the postback request in order to get JSF to invoke the bean action associated with the <h:commandLink> during the invoke action phase of that request. Perhaps the bean is request scoped and/or some odd/illogical flow inside the bean caused that the rendered attribute is not properly been preserved.
Best is to maintain those rendered conditions in a #ViewScoped bean and let its action methods return void or null so that the bean lives as long as you're interacting with the same view. Change the rendered conditions during action methods only and not inside setters/getters or something.

Resources