Jsf life cycle - render response after validation failure - jsf

I'm hoping BalusC or one of you JSF experts can help me understand the finer points of the JSF life cycle, particularly rendering.
What I'm struggling to understand is that during render response, values are obtained from the model and displayed to the user. Now, if there were validation errors, the model is not updated, so the renderer must have to show the user the invalid value from the component tree. That's all well and good but how does the renderer determine whether to read from the model, or read from the component tree? If it's from the component tree, does that mean if a request passes validation and an event handler updates model values just prior to rendering, will those values be reflected to the user?
I've read lots about the jsf life cycle but nothing I've found goes into it deeply enough to answer my questions. I want to understand precisely how this stuff works.

During the apply request values phase, all request parameters are set as submitted value on UIInput by setSubmittedValue().
During the validations phase, only and only if the value is valid, the submitted value is set to null and the converted and validated value is set on UIInput by setValue(). So if the value is not valid, then the submitted value won't be set to null.
During the update model values phase, the model value is updated with that value.
During the render response phase, the UIInput renderer first checks if getSubmittedValue() doesn't return null. If it doesn't (so, validation has failed), then display it. Otherwise just display the model value.

Related

Debugging JSF Life Cycle - what exactly happens in each phase

I have decided to dig completely into JSF 2.0 as my project demands deep knowledge of it. I am reading JSF Lifecyle Debug, a well written and awesome article on JSF Life cycle. While reading this article, I have following confusions.
If it's an initial request, in Restore View Phase an empty View is created and straight Render Response Phase happens. There is no state to save at this point. What actually happens in render response phase then? I am confused a little while I am running the example.
The article states that, retrieved input value is set in inputComponent.setSubmittedValue() in Apply Request Values phase. If validation and conversion passes, then the value gets set in inputComponent.setValue(value) and inputComponent.setSubmittedValue(null) runs. On same point article states that, now if in the next post back request, value is changed, it is compared with the submitted value which would always be null on every post back, value change listener will be invoked. It means if, we don't change the value even, as submittedValue would be null, valueChangeListener will always be invoked? I am confused on this statement. Can someone elaborate on this?
Article states the usage of immediate attribute. If immediate attribute is set on an input component, than ideally Process Validation Phase is skipped, but all of the conversion and validation happens in Apply Request Values. My point is, still when the conversion and validation is happening, what's the advantage of skipping the third phase?
What does the term retrieved value means?
I would like to know, if lets say there are five fields on the view. Does JSF makes a list of some collection of these values and Apply Request Values and Process Validations phase iterate over them one by one?
At the last point of this article where it states, when to use immediate attribute. As per my understanding, if immediate attribute is set in both input component and command component, It will skip the phases from Apply Request Values to Invoke Application for any attribute not having immediate. Then what does the last statement mean "Password forgotten" button in a login form with a required and immediate username field and a required but non-immediate password field.
I know these are very basic confusions but clarity on these topics will definitely help sharpen the JSF knowledge.
1: What actually happens in render response phase then?
Generating HTML output for the client, starting with UIViewRoot#encodeAll(). You can see the result by rightclick, View Source in webbrowser (and thus NOT via rightclick, Inspect Element in webbrowser, as that will only show the HTML DOM tree which the webbrowser has built based on the raw HTML source code and all JavaScript events thereafter).
2: it is compared with the submitted value which would always be null on every post back
Nope, it's being hold as an instance variable. JSF doesn't call getSubmittedValue() to compare it.
3: My point is, still when the conversion and validation is happening, what's the advantage of skipping the third phase?
This is answered in the bottom of the article, under Okay, when should I use the immediate attribute?. In a nutshell: prioritizing validation. If components with immediate="true" fail on conversion/validation, then components without immediate="true" won't be converted/validated.
4: What does the term retrieved value means?
The "raw" value which the enduser has submitted (the exact input value which the enduser entered in the input form). This is usually a String. If you're familiar with servlets, then it's easy to understand that it's exactly the value as you obtain by request.getParameter().
5: Does JSF makes a list of some collection of these values and Apply Request Values and Process Validations phase iterate over them one by one?
Almost. The collection is already there in flavor of the JSF component tree. JSF thus basically iterates over a tree structure, starting with FacesContext#getUIViewRoot().
6: Then what does the last statement mean "Password forgotten" button in a login form with a required and immediate username field and a required but non-immediate password field.
This way you can reuse the login form for the "password forgotten" case. If you submit the "login" button, then obviously both the username and password fields must be validated. However if you submit the "password forgotten" button, then the password field shouldn't be validated.
That said, you may find the below JSF phases/lifecycle cheatsheet useful as well for a quick reference:
fc = FacesContext
vh = ViewHandler
in = UIInput
rq = HttpServletRequest
id = in.getClientId(fc);
1 RESTORE_VIEW
String viewId = rq.getServletPath();
fc.setViewRoot(vh.createView(fc, viewId));
2 APPLY_REQUEST_VALUES
in.setSubmittedValue(rq.getParameter(id));
3 PROCESS_VALIDATIONS
Object value = in.getSubmittedValue();
try {
value = in.getConvertedValue(fc, value);
for (Validator v : in.getValidators())
v.validate(fc, in, value);
}
in.setSubmittedValue(null);
in.setValue(value);
} catch (ConverterException | ValidatorException e) {
fc.addMessage(id, e.getFacesMessage());
fc.validationFailed(); // Skips phases 4+5.
in.setValid(false);
}
4 UPDATE_MODEL_VALUES
bean.setProperty(in.getValue());
5 INVOKE_APPLICATION
bean.submit();
6 RENDER_RESPONSE
vh.renderView(fc, fc.getViewRoot());
See also:
Difference between Apply Request Values and Update Model Values
JSF - Another question on Lifecycle
What's the view build time?

JSF Lifecycle with immediate=true

When I read article Listen and debug JSF lifecycle phases
wrtten by #BalusC, I have some trouble understanding the article.
While Add immediate="true" to UIInput and UICommand, It says:
Note for all components with immediate: as the Update model values phase is skipped, the value bindings aren't been set and the value binding getters will return null. But the values are still available...
Note for other components without immediate: any other UIInput components inside the same form which don't have immediate="true" set will not be converted, validated nor updated, but behind the scenes the inputComponent.setSubmittedValue(submittedValue) will be executed before the action() method will be executed. You can retrieve...
Is that means no matter with or without immediate, the Update model values phase will always skipped because the immediate="true" in the h:commandButton? If so, the value in backing bean will not change, right?
However, in the last paragraph of the article, it summarized "when to use immediate=true" and mentioned:
If set in both UIInput and UICommand components, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s) which does not have this attribute set. Use this to skip the processing of the entire form except for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required and immediate username field and a required but non-immediate password field.
I am confused because I thought Process validations Phase and Update model values Phase are skipped no matter there are/aren't immediate once you set immdediate=true in h:commandButton in the same form.
I must misunderstood something, please help me clarify it.
Thanks in advance!
That part indeed needs clarification.
What is meant in the summary, is the job which is normally executed in the mentioned phases (i.e. applying request values, processing validations and updating model values), even though they happen in the apply request values phase.
I have updated the article accordingly.

Why conversion is not skipped?

I have two input components on my page. Each of them has a converter (It's a converter which checks for empty values, like JSF required one, but for some reasons I cannot use jsf one so I've made my own converter).
I also have a ice:selectBooleanCheckbox:
<ice:selectBooleanCheckbox
styleClass="graUserAppUserGroupAddChk"
value="#{userGroupTableNewRecordBean.addNewDomain}"
partialSubmit="true"
immediate="true"
valueChangeListener="#{userGroupTableNewRecordBean.addDomainListener}"></ice:selectBooleanCheckbox>
As you see I put immediate=true attribute on it, becase when I select this checkbox I do want the conversion phase to be skipped but it does not work, the converters still show their warnings. Do you know why?
I also add a valueChangeListener on this checkbox and called there the renderResponse directly, based on this quote:
So in the value changed listener method for the dropdown lists, just
call renderResponse() from the
FacesContext object and validation and
conversion is bypassed and you can
still do what you want.
public void addDomainListener(final ValueChangeEvent valueChangeEvent) {
// skip validation
logger.info("listener calleddddddddddddd");
FacesContext.getCurrentInstance().renderResponse();
}
Maybe a JSF guru can help?
Thanks a lot...
UPDATE: I know that a solution would be to put the checkbox in a separate form but I cannot afford this...
UPDATE 2: I've corrected some code about listener, so now it is called when clicked but still the converter fails and render response phase is not done...
UPDATE 3: This is not an icefaces issue... I've tried with a h:selectBooleanCheckbox and it happens the same...
The whole question and the functional requirement behind this all is pretty confusing. Why are you using a converter instead of a validator to validate the inputs? Why are you using a converter/validator if you don't seem to care about the conversion/validation outcome?
As you see I put immediate=true attribute on it, becase when I select this checkbox I do want the conversion phase to be skipped but it does not work, the converters still show their warnings.
Putting the immediate="true" on input components does not skip conversion/validation. They just shifts conversion/validation to an earlier phase (i.e. it takes place in apply request values phase instead of validations phase). You basically need to remove immediate="true" from those inputs and put it on the command link/button in order to skip conversion/validation of those inputs. See also Debug JSF lifecycle:
Okay, when should I use the immediate attribute?
If it isn't entirely clear yet, here's a summary, complete with real world use examples when they may be beneficial:
If set in UIInput(s) only, the process validations phase will be taken place in apply request values phase instead. Use this to prioritize validation for the UIInput component(s) in question. When validation/conversion fails for any of them, the non-immediate components won't be validated/converted.
If set in UICommand only, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s). Use this to skip the entire processing of the form. E.g. "Cancel" or "Back" button.
If set in both UIInput and UICommand components, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s) which does not have this attribute set. Use this to skip the processing of the entire form expect for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required but non-immediate password field.
Solved it finally...
I post here the sum up of the question and the solution.
I had a checkbox in my popup. When I select it I want to show some hidden fields but this did not work because I also had two required fields on the same page so jsf PROCESS_VALIDATIONS phase came up...
I thought that putting immediate=true will solve this, but it did not...
So, in my ValueChangeListener of the checkbox I had to manually skip the jsf validation phase:
public void addDomainListener(final ValueChangeEvent valueChangeEvent) {
// skip validation
final PhaseId phaseId = valueChangeEvent.getPhaseId();
final Boolean newValue = (Boolean) valueChangeEvent.getNewValue();
if (phaseId.equals(PhaseId.ANY_PHASE)) {
valueChangeEvent.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
valueChangeEvent.queue();
this.addNewDomain = newValue;
FacesContext.getCurrentInstance().renderResponse();
}
}

JSF : immediate true causes problem in searching the product

I am facing the problem of immediate = "true" in my project.
I have applied immediate = "true" on search commandLink to By Pass the validation.
but it affects the search functionality.
it does not execute the search method...
what is the problem can anyone explaine...
is there any way to bypass the validation and search the product without using immediate="true"
Thanking in advance
Your functional requirement is still unclear (which brings those contra-questions: Why is the validator there? Why/when do you want to bypass this? Do you have multiple buttons? etc..etc..), so I can't be of more help than recommending you to get yourself through this article to learn about the why of the immediate attribute and to help yourself with the problem: Debug JSF lifecycle.
Here's a summary of relevance:
Okay, when should I use the immediate attribute?
If it isn't entirely clear yet, here's a summary, complete with real world use examples when they may be beneficial:
If set in UIInput(s) only, the process validations phase will be taken place in apply request values phase instead. Use this to prioritize validation for the UIInput component(s) in question. When validation/conversion fails for any of them, the non-immediate components won't be validated/converted.
If set in UICommand only, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s). Use this to skip the entire processing of the form. E.g. "Cancel" or "Back" button.
If set in both UIInput and UICommand components, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s) which does not have this attribute set. Use this to skip the processing of the entire form expect for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required but non-immediate password field.

JSF getValue() v.s. getSubmittedValue()

I've been developing a few JSF applications lately and am disturbed with the inconsistency in the web component APIs.
I've noticed that there is extremely unpredictable behavior when calling .getValue() or .getSubmittedValue() on a JSF component object in server side code. Sometimes when I call .getValue() on a drop down list box, I've noticed that I get the value as it was BEFORE I selected my value (so the value from the last page refresh), of which .getSubmittedValue() gets me the correct value, as such:
UIInput name = new UIInput(); // This is the control I have in a bean.
public void submit(ActionEvent ae)
{
someMethod(name.getValue().toString()); // Retrieves the "old" value
someMethod(name.getSubmittedValue().toString()); // Retrieves the correct value
}
Also, I've noticed that calling .getSubmittedValue() on a form field sometimes results in a null pointer exception because that value has not been instantiated in the component object, in which case when I call .getValue() in that circumstance I get the correct value, for example:
HtmlInputText name = new HtmlInputText(); // This is the control I have in a bean.
public void submit(ActionEvent ae)
{
someMethod(name.getValue().toString()); // Retrieves the correct value
someMethod(name.getSubmittedValue().toString()); // Throws NullPointerException
}
Is this just a "quirk" of the JSF framework, or am I just using the API COMPLETELY incorrectly?? Any insight into these two methods would be greatly appreciated. Cheers.
Since this is the #1 result in Google for searching on getValue vs. getSubmittedValue I'd just like to add that the difference between these is critical in validation (i.e. when writing a custom validator)
To quote the API documentation for getSubmittedValue():
This is non-null only between decode
and validate phases, or when
validation for the component has not
succeeded. Once conversion and
validation has succeeded, the
(converted) value is stored in the
local "value" property of this
component, and the submitted value is
reset to null.
Source: http://myfaces.apache.org/core11/myfaces-api/apidocs/javax/faces/component/UIInput.html#getSubmittedValue()
This means that if the validation/conversion has taken place for the binding you are trying to access, you should call getValue() otherwise you'll have to call getSubmittedValue() and deal with parsing it yourself. The order in which these occur seems to be dictated by the order they appear in the UI, but I don't think that's guaranteed. Even if it is, you shouldn't count on that as changing field in your UI shouldn't break your code.
You can detect if the validation/conversion has been done by just looking at what isLocalValueSet() returns. If it returns true, then the valdation/conversion has been done, so you should call getValue(). Otherwise you'll need to call getSubmittedValue() and that'll give you the raw input the user entered and you'll likely want to parse it into something more meaningful.
For example, a calendar object would return a Date object when getValue() was called, but a String object when getSubmittedValue() was called. It's up to your converter to parse the string into a Date so it can be validated.
It'd be great if the JSF spec had a method which would do this for us, but AFAIK it doesn't. If certain dates need to be before other dates, and some are only required in certain circumstances, one will need to write several validators to handle this. So it can easily become an issue. This is similar to the fact that you can't do any kind of validation on a blank field, which means you can't make that field conditionally required. If validation was run on all fields, even blank ones, a custom validator could be written to throw an exception if it should be required and is not. There are some things with JSF which are just a pain; unless/until they're fixed, we just have to deal with them.
To speak to the specifics of the issue in the original post: the difference here is where you're at in the life cycle. The submit method seems like an action listener for a button, which puts it at the end of the life cycle; actions and action listeners are triggered in the "Invoke Application" phase which comes prior to the render response, but after validation. If you're going to program in JSF, you should learn and understand the life cycle. It's worth the time.
To quote the documentation on EditableValueHolder.getSubmittedValue:
Return the submittedValue value of
this component. This method should
only be used by the encodeBegin()
and/or encodeEnd() methods of this
component, or its corresponding
Renderer.
Generally, you would not even be calling getValue. Instead, the component's value attribute should be bound to your model (a bean, maybe). Your business logic would interact with the model, not the component.
If the submitted value is not being set as the value, then I'd guess that some validation is failing. The only problem with that is that your event is being fired. Two guesses for the problem here:
You have a stale reference to the component object.
You've set the immediate attribute on a UICommand which means that the event is fired in a phase where the component will be in an inappropriate state.
It isn't possible to be certain with the information provided.
I work on xpages which are based on JSF so.. it could be the same...
Anyway, getSubmittedValue(); always returns what you see in firebug/chrome develepers network tab. That is value within sent packet. I have it shown (chrome) in headers tab, in form data section, named $$xspsubmitvalue.
On the other hand, getValue() is component specific. <-- not 100% sure here.
TL;DR answer:
UIViewRoot viewRoot = context.getViewRoot();
UIInput input = (UIInput)viewRoot.findComponent(":form:inputID");
String inputValueString;
if (input.isLocalValueSet()) {
inputValueString = (String)input.getValue(); //validated and converted already
} else {
inputValueString = (String)input.getSubmittedValue(); //raw input
}
or at least that's what the other answers are saying to do...
Just use .getSubmittedValue() and deal with the consequences of having to convert raw input (if necessary, if that raw input needs conversion). .getValue() is broken in this regard, even with the code above. It delays the submitted value if you use it and that's unacceptable.

Resources