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.
Related
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?
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
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?
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.
I declare my repeater in a form (lets say in main.xhtml):
<!--<itemRenderer:MetaFieldRenderer item="{kueditmeta.metaFieldFirst}" >
</itemRenderer:MetaFieldRenderer>-->
<ui:repeat var="foo" value="#{kueditmeta.metaFields}" >
<itemRenderer:MetaFieldRenderer item="#{foo}" >
</itemRenderer:MetaFieldRenderer>
</ui:repeat>
My form on submit inspect my MetaFieldRenderer.xhtml composite component in the repeater, I look at an attribute: <cc:attribute name="item" /> by calling MetaFieldRenderer().getModel();
In my FacesComponent back bean I expose getModel() method:
public MetaFieldModel getModel() {
ELContext el = this.getFacesContext().getELContext();
ValueExpression valExp = this.getValueExpression("item");
Object itemValue = valExp.getValue(el);
return (MetaFieldModel) itemValue;
}
itemValue is always null when I nest MetaFieldRenderer in a UIRepeat. But if I uncomment the one outside of the repeater itemValue is not null.
Anyone knows what's going on? Is there a better way to bind from and attribute to my FacesComponent? Am I missing a necessary implementation in my component so the UIRepeat do update its children?
(I use JSF 2.0.3)
I expected the components to populate themselves at pretty much the same phase (or at least before Invoke application (aka: action, navigateTo...) phase). But UIRepeat at Invoke Application phase always contained only one child, the itemRenderer it would use for repeating, the data was not repeated yet (Ho it happen at render phase I guess?).
I came to understand something through those steps:
Restore View phase bring back a plain UIRepeat and its children declare in the xhtml. No UIRepeat doesn't populate anything yet, there is only the itemRenderer without any value in it at that point.
To see how its children (if composite component) are not bound to anything at that moment use the required attribute <cc:attribute required="true"... its gonna throw an error even if you gave the attribute because uirepeat doesn't pass them.
Lesson learned, don't do logic/validation on the composite component backbean, just reflect the model. Now I drive my repeater with a list of model that can validate itself and if the model contains a warn message or whatever fancy stuff I just display it in the composite component.