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 unpredi
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.
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:
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.
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.