Rendering Condition in JSF 1.2 [duplicate] - jsf

I know this type of question has been asked million times here, but I couldn't find a solution for my problem in relevant posts.
JSF 1.2
I have a request-scoped bean with a method used as valueChangeListener:
class DoStuff{
...
public void step1ChkStuffIncluded_CheckedChanged(ValueChangeEvent event){
StuffDocument cd = (StuffDocument)getInfo("StuffDocument");
if(cd == null){
Logger.Error("DoStuff", "step1ChkStuffIncluded_CheckedChanged", "No stuff document (null)");
return;
}
if (step1ChkStuffIncludedChecked){
cd.handleChecked();
}
else{
cd.handleUnchecked();
}
}
...
}
by a selectBooleanCheckbox component as follows (.jspx):
...
</h:panelGroup>
<h:panelGroup rendered="#{DoStuff.pnlStep1}">
<p>
<label for="step1ChkStuffIncluded">#{DoStuff.step1ChkStuffIncludedText}</label>
<h:selectBooleanCheckbox
id="step1ChkStuffIncluded"
onchange="submit();"
value="#{DoStuff.step1ChkStuffIncludedChecked}"
valueChangeListener="#{DoStuff.step1ChkStuffIncluded_CheckedChanged}">
</h:selectBooleanCheckbox></p>
</h:panelGroup>
<div id="someDiv">
...
where
xmlns:h="http://java.sun.com/jsf/html"
Whenever the bean's scope is session, both setter and the listener for the checkbox are executed, but not in request scope. Unfortunately I can't find any clues other than that.
Any advise is greatly appreciated. Requests for further clarifications are welcome.

You've there a rendered="#{DoStuff.pnlStep1}" on a parent component. During processing of the form submit, JSF will as part of attack safeguard determine if the input component (and all of its parents) is rendered according to the server side conditions. If it's not rendered, then it will simply be skipped altogether during the processing.
That it works in a session scoped bean but fails in a request scoped bean indicates that the value behind rendered="#{DoStuff.pnlStep1}" is determined based on some request based variable/condition which was present during the request of displaying the form, but is absent during the request of processing the form submit.
To fix this, you need to make sure that you preserve exactly the same variable/condition for the value behind rendered="#{DoStuff.pnlStep1}" during the request of processing the form submit. There are several ways to achieve this, depending on the nature of the condition and how you're submitting the form. One of the ways is to pass the request based variable/condition back as a request parameter by <f:param> or <h:inputHidden>.
The canonical JSF 2.0 fix would be to put the bean in the view scope which is not available in JSF 1.2, but can be simulated using Tomahawk's <t:saveState> component.
See also:
JSF 1.2: How to keep request scoped managed bean alive across postbacks on same view?
How to call an action method of a UICommand Component which was rendered conditionally?

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?

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)

JSF 1.2: How to keep request scoped managed bean alive across postbacks on same view?

Is it possible to keep a request scoped bean alive across postbacks on the same page?
The general problem is, as the bean gets trashed on end of request and recreated on every form submit, for example the booleans behind dynamically manipulated disabled, readonly and rendered get reset to their default values and cause the forms to not work as intented anymore.
I'll assume that the session scope is not an option, otherwise this question makes little sense.
You can do it using Tomahawk <t:saveState>. Add the following line somewhere to the page:
<t:saveState value="#{bean}" />
RichFaces <a4j:keepAlive> does also the same:
<a4j:keepAlive beanName="#{bean}" />
Or if there is room, upgrade to at least JSF 2.x and put the bean in view scope:
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
// ...
}
Regardless of the way, the same bean will be there when you postback to the same view and keep returning null or void from action methods.
See also:
How to choose the right bean scope?
Difference between View and Request scope in managed beans
Not really, unless you store the Bean somewhere e.g. a Map in application scope, to retrieve it later.
Why not just make it Session scoped? This is what Session scope is there for, so multiple Requests during the same Session can hit the same state.

Managed Bean property value not rendered during Render Response Phase

I am not able to figure out what I am doing wrong. Request your inputs. Please.
I have a request scoped managed bean , which has a List of which I render as a datatable in my JSF 1.2 Apache my faces application. When I submit the form , and since there are some server side validations that fails, I add a FacesMessage and show the same JSF page.
In this request-response cycle , In the INVOKE-APPLICATION Phase , I am able to see the values of the List of but the when the page is rendered with the FacesMessage, the datatable is empty.
The other bean-properties and their values are retained in this request-response cycle except for this List / Datatable.
This is how the datatable is constructed in the action method - initial request
if(getInputXMLString() != null
&& getInputXMLString().length() >0)
{
List<NodeDetailsVO> nodes = Utility.inputXMLStringNodeDetailsVO(getInputXMLString());
setSelectedNodes(nodes);
}
When I try the same as above in the postback request (inside the other action method),It works okay.When I add my business Logic inside a private method, and If I call it above this code or after this, It doesn't work.I am only using the getter of the List in the private method. And in the getter method - I only have sysouts inside if and else.
This is how the datatable is rendered in the xhtml page:
<h:dataTable width="80%" cellspacing="0" border="1"
id="nodes_datatable" cellpadding="2"
style="border-collapse:collapse;"
value="#{createBean.selectedNodes}"
binding="#{createBean.selectedNodesHTMLDataTable}"
var="aResult"
columnClasses="columnAlignRight,columnAlignLeft"
>
This is not the normal case. I do see only two possible causes:
The datamodel (the List as you calls it) is been reset somehow. Probably the getter method is doing more than only returning the datamodel and has reloaded it, but some requestbased parameter/condition is missing.
The datatable or one of its parent components has a rendered attribute which evaluated false.

JSF and richfaces: h:commandlink in richfaces table not working properly

When using h:commandlink(or commandbutton) inside a rich:dataTable, the action specified is never invoked, neither is the corresponding managed bean instantiated(whether it is at request or session scope)...
instead, the same request is performed.. (page reloads)..
have seen what appeared to be similar issue on forums, but is not actually the problem i am having..
the h:commandlink /button work ok outside of the rich:datatable..
Does anyone have any advice?
here is a code snippet:
<h:commandLink id="commLink" actionListener="#{hBean.test}" action="#{hBean.viewTranslation}">
<h:outputText value="#{trans.translationName}"/>
</h:commandLink>
</rich:column>
The bean is apparently request scoped and the datamodel is not been loaded during bean's construction (at least, during apply request values phase of the subsequent request). You need to preserve the same datamodel for the subsequent request, else JSF cannot locate the row item associated with the clicked link. The most straightforward way is to load the datamodel in the bean's constructor or #PostConstruct method.
A quick fix/test is to put bean in session scope. The datamodel will then be saved in the session scope and be available in the subsequent request. But this has more impact on user experience (e.g. unexpected results when having the same page opened in different browser windows/tabs in the same session). If you're already on JSF 2.0 (which is likely not the case since you're using RichFaces), then the new view scope would have been the solution.
Related questions:
h:commandLink is not been invoked - contains an overview of all possible causes of this behaviour.
If you are using RichFaces 3.0.0 through 3.3.3, use the tag a4j:keepAlive. It will works even with request scope.

Resources