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.
Related
I have a method in my JSF controller that is invoked by an ajax tag nested inside a visual component (really irrelevant which one). The method takes a single argument of type AjaxBehaviorEvent, from which I can obtain a Java representation of the invoking HTML visual component as a UIComponent and also downcast it to its specific corresponding type (e.g. h:inputText corresponding to HtmlInputText).
I understand that, in most cases, the value of the HTML visual component would be retrieved easily by referencing either the controller or entity [g|s]etters to which the form fields are mapped in the view. However, in my particular case, I would like to fetch the value of the visual component (in my case a form field) through its Java object rendering. While studying the faces API, I found ways to read various properties of the object, such as the ID or context but not the value that the component currently holds in the view.
Can anybody explain whether I am just not finding the right way to read it or it is so by design? If the latter, can you explain why it is designed like that? Is it to disable "backdoor" access to form fields as opposed to going through the view mapping?
There are a multitude of ways to pull values off a component. Going by what you already have UIInputt#getValue() and UIInput#getSubmittedValue() will provide the value.
The UIInput#getSubmittedValue() is fit for the purpose only between the APPLY_REQUEST_VALUES and VALIDATE phases of the JSF request. All other phases after, use the UIInputt#getValue(). You'll be using UIInput instead of the raw UIComponent you pulled from the event (UIInput extends UIComponent and it's the parent class for all input components that accept user-edited values). What you'll have will eventually look like:
UIInput theInput = (UIInput)event.getSource();
Object theValue = theInput.getValue();
There are other ways (not as clean) to get values within the request lifecycle also
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?
Inside an input type field I have a value binding to a variable(lets call foo) of type double for the value property in my jsp . I have a setter and a getter for foo and there is also a ValueChangedListener registered for this input . The autosubmit attribute of that field is set to true . When the user clears the input and navigates to the next field ,the code inside valueChangedListener gets invoked and the newValue of the ValueChangedEvent is coming null . How can I prevent this ?
I tried handling this from the setter method but it seems the setter is not getting called and the valueChangedListener is getting called first . Doesn't the spec say that setter should be called first to populate the user edited value to the component and then only the ValueChangedListener gets fired ?
P.S: I am using ADF RichInputText as the input but I think it is not related to ADF but to core JSF machinery. Hence not tagging it as ADF question.
I need to validate the new value and I am not interested in the old value.
A valueChangeListener is then the wrong tool for the job. Use a normal Validator. In order to validate empty but required fields, use required="true". In order to skip custom validators on empty fields, add the following context param to web.xml:
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>false</param-value>
</context-param>
The only disadvantage is that this will also skip #NotNull/#NotBlank JSR303 bean validation, but that shouldn't harm if you aren't using it anyway.
Also why the setter won't be called before the valueChangeListener?
Because the old value is otherwise lost and this would defeat the purpose of the value change listener.
Will the validator run before the valueChangedListener ? I guess only when validation passes , it should invoke a ValueChangedEvent , right ?
That's correct. The value change listener is only invoked when the component has passed validation (i.e. UIInput#isValid() returns true). Noted should be again that when you're not interested in the old value, the value change listener is most likely the wrong tool for the job you had in mind.
There appears to be a difference between managed bean state and component tree state. You can control managed bean state by using annotations like #RequestScoped and #SessionScoped, but it seems you don't have a choice in whether the component tree state is saved or not (although you can choose whether it is saved on the server or client).
It seems like component tree state should only be needed for the duration of a single request as a temporary data structure to help process a request. It should be rebuilt from scratch for each request. With JSF 2.0 partial state saving makes the situation better because only form data is saved, but I don't understand why having even form data from the previous request is useful.
If your application uses only request scope managed beans then it especially doesn't make sense to save component tree state between requests. Even if your application has session scope managed beans I would assume that the managed beans would hold the state and the component tree still wouldn't need to have any state between requests.
Adding to the previous answer, ever since JSF 2.0 something called partial state saving is used by default.
The default view description language in JSF (Facelets) creates the whole component tree from the original Facelet after every request and initializes the components from their corresponding tag attributes. It then marks the state.
Every subsequent state change is then remembered as a delta change, and it's this state that is actually being saved. It might just well turn out that there simply are no such changes, and then the view state is empty (because of a bug, the state was never truly empty, but that has been recently fixed. See http://java.net/jira/browse/JAVASERVERFACES-2203 for details)
So the big question is, what's actually in this state then when it's non-empty?
As BalusC already remarked, this could hold dynamic changes to the component tree. Those changes can either be initiated from backing beans, or from within static components. A simple example of the kind of component that does this dynamic changing is a table component that creates child column components based on the actual number of columns in a data set.
Another important usage for the view state is remembering values that have been changed inside components, but have not been pushed into the model. This can be such things as flicking a switch in a switch component, moving a slider in a dial component etc.
One particular example is the viewParam component, which remembers the request parameter (query string parameter for GET or non-faces POST parameter) with which it was initialized. See this for some more info about that: http://arjan-tijms.omnifaces.org/2011/07/stateless-vs-stateful-jsf-view.html
There is also a strong relation with stateful components remembering UI state and conversion or validation that fails. In this case, the UI components will remember the values entered by the user, and will remember that there was a conversion/validation error.
Yet another usage for the state is optimization. Some components calculate values that they deem to be expensive to calculate and store these in the view state. For instance, UIInput components do this after the first post-back:
private boolean validateEmptyFields(FacesContext ctx) {
if (validateEmptyFields == null) {
ExternalContext extCtx = ctx.getExternalContext();
String val = extCtx.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
if (val == null) {
val = (String) extCtx.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
}
if (val == null || "auto".equals(val)) {
validateEmptyFields = isBeansValidationAvailable(ctx);
} else {
validateEmptyFields = Boolean.valueOf(val);
}
}
return validateEmptyFields;
}
After this validateEmptyFields is stored in the view state so it doesn't have to be calculated again upon the following form submits. An improvement would be if users can choose between re-calculating or storing (the well know time-space optimization).
The very concept of state is what has plagued web application development since its early conception. Everyone wants to have interactions that are essentially stateful, yet almost nobody wants to handle it or even think about it.
JSF has been trying to provide an answer here, but it's obviously not perfect and there's room for improvement. JSF's insistence on being able to restore view state (even empty view state) can be troublesome, although as was mentioned in another answer it does provide an implicit protection against CSRF. JSF 2.2 will get more explicit CSRF protection (see e.g. http://arjan-tijms.omnifaces.org/p/jsf-22.html#869), so maybe we will see some change here in the future.
Having an option to turn off state per component and having an easy hook to restore state incase the framework can't (as in ASP.NET) might also be helpful.
Because the component tree can be altered programmatically depending on the initial request. This is not necessarily reproduceable on the subsequent request whenever the form data has to be processed.
Further I have the impression that you think that the component tree also holds the model values. This is not true. It only holds references (by expression language) to the model values (the managed bean properties). The view state does not copy/duplicate/contain the model state. It's just a pure UI component tree. Perhaps your confusion is based on this. Note that the term "form data" is to be interpreted as submitted values and model values.
See also:
Why JSF saves the state of UI components on server?
If I have many input controls in a form (There are separate validators for each of these input controls - like required,length and so on ) , there is a command button which submits the form and calls an action method. The requirement is - though the input control values are , say , individually okay - the combination of these values should be okay to process them together after the form submission - Where do i place the code to validate them together?
1) Can i add a custom validator for the command button and validate the combination together? like validate(FacesContext arg0, UIComponent arg1, Object value) but even then I will not have values of the other input controls except for the command button's/component's value right ?
2) can i do the validation of the combination in the action method and add validation messages using FacesMessage ?
or do you suggest any other approach?
Thanks for your time.
Point 2 is already answered by Bozho. Just use FacesContext#addMessage(). A null client ID will let it land in <h:messages globalOnly="true">. A fixed client ID like formId:inputId will let it land in <h:message for="inputId">.
Point 1 is doable, you can grab the other components inside the validator method using UIViewRoot#findComponent():
UIInput otherInput = (UIInput) context.getViewRoot().findComponent("formId:otherInputId");
String value = (String) otherInput.getValue();
You however need to place f:validator in the last UIInput component. Placing it in an UICommand component (like the button) won't work.
True, hardcoding the client ID's is nasty, but that's the payoff of a bit inflexible validation mechanism in JSF.
I've just landed on your post after having the same question.
Articles I have read so far identify that there are four types of validation for the following purposes:
Built into the Components (subscribe to individual fields; required=true, LengthValidator, etc)
'Application Validation' added to the Action in the Backing Bean (Business Logic)
Custom Validators (subscribe to individual fields)
Method in the Backing Bean used as a Custom Validator (subscribe to individual fields).
With reference to Validators: The validation mechanism in JSF was designed to validate a single component. (See S/O Question here)
In the case where you want to validate a whole form as a logical grouping of fields, it appears with standard JSF/Apache MyFaces that the most appropriate to do it is as Application Validation, as the set of individual fields take on a collective business meaning at this point.
BalusC has come up with a way of shoehorning form validation into a single validator attached to the last form item (again, see S/O Question here and another worked example on his website here) however it isn't necessarily extensible/reusable, as the references to the ID's of the form have to be hardcoded as you can't append to the validate() method's signature. You'll get away with it if you're only using the form once, but if it pops up a few times or if you generate your ID's programmatically, you're stuck.
The JSF implementation portion of Seam has a <s:validateForm /> control which can take the IDs of fields elsewhere in your form as parameters. Unfortunately, it doesn't appear that any of the MyFaces/Mojara/Sun JSF implementations have an equivalent as it isn't part of the standard.
I've successfully used the 2nd approach:
FacesMessage facesMessage =
new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
FacesContext.getCurrentInstance().addMessage(null, facesMessage);