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

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?

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?

JSF Changing language from selectMenu doesn't invoke PostConstruct

I have in the header.xhtml change language selectOneMenu. Which by choosing changes the language properly of any xhtml file. But there are few pages where the language strings are set in the Java class itself which is invoked by the Post-Construct.
Header.xhtml
<h:selectOneMenu value="#{client.language}" onchange="submit()" >
<f:selectItems value="#{client.languages()}" />
</h:selectOneMenu>
In the managed bean, I have ViewScoped and then the PostConstruct. My problem here is- after changing the language from the menu, some string set by the Java are not translated. That's because it is invoked by the PostConstruct which is not invoked when the language is changed. But when I goto that page by clicking the link, then the strings are translated. Its just that as soon as I change language the strings aren't translated.
I think the problem here is because the PostConstruct is not invoked when the language is changed. How do I invoke it?
Your question is basically about the behavior of #PostConstruct. This method will be called once after the bean has been created and after the injection of fields has happened e.g. fields decorated with #EJB and #Resource annotations.
Since you use #ViewScoped bean, then this will be created once per view. Refreshing the page will create a new view, that's why your instance of the #ViewScoped bean will be recreated and you will process the data in the desired language.
Possible solutions:
Mark the bean that handles the view as #RequestScoped.
Use proper i18n internationalization for your output messages. Do not rely on messages being constructed from your managed bean.
In my case, I would use the latter rather than the former. Also, after changing the language, the best option is to fire a new non-ajax request-response cycle to the server.
More info:
How to choose the right bean scope?
Localization in JSF, how to remember selected locale per session instead of per request/view
I have tried to do it like you did in the past with no luck either. Here is how I work around the problem (using JQuery):
<h:selectOneMenu value="#{client.language}" onchange="$(document).find('.submitBtn').click();" >
<f:selectItems value="#{client.languages()}" />
</h:selectOneMenu>
<h:commandButton style="visibility: hidden;" styleClass="jsfHidden submitBtn" action="#{yourpostconstructmethod}"/>

Manipulating a disabled attribute in client side; does JSF test properly if component is disabled?

Primefaces 3.5.10, Mojarra 2.1.21, Omnifaces 1.5
I am thinking about security issues.
I set the component attribute with the component.getAttributes() method. This method returns a HashMap with attributes. Is it safe to set the ("disabled", true)-pair in this map to disable the component (for example p:inputText-component)? I use it from an actionListener, (Phase 5 or 4) of jsf pipeline. So possibly it has implications for render phase only. But I could manipulate the disabled attribute from input method on the client and then post the manipulated values. Does the server make test if the component is disabled and rejects the changes ?
What is the best way to go ?
all components in panelGrid will be disabled:
xhtml:
<p:panelGrid>
<my:component/>
<p:input value=#{mybean.value} />
</p:panelGrid>
Bean:
for (UIComponent component : l) {
component.getAttributes().put("disabled", true);
recursion(....);
}
But I could manipulate the disabled attribute from input method on the client and then post the manipulated values.
Yes, the enduser could.
Does the server make test if the component is disabled and rejects the changes ?
Yes, JSF does it based on component tree state, not on the submitted value. So that part is safe. It does that by the way also for readonly and rendered attribtues.
See also:
Why JSF saves the state of UI components on server?
Which properties in a JSF backing bean can be set by a user?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated (point 5)

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

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