How to deal with "transient" input elements that have no backing bean representation? - jsf

I have come across some situations in which input controls are used that do not have the value attribute set, i.e. they have no direct representation in the backing bean.
User input is handled entirely by ajax listeners. An example are the input elements of the column filters in the primefaces table.
However, when dealing with such input fields, MyFaces warns me about each:
Feb 09, 2017 3:04:51 PM javax.faces.validator.BeanValidator validate
WARNING: cannot validate component with empty value: my_form:myTableId:j_id_1s
In a way, this problem has already been mentioned here: p:datatable filter: cannot validate component with empty value
My question is: What is the best practice in situations like this?
An input element should always have a reference in the backing bean, everything else is a design error
Just use a "dummy" value that points to an unused field in the bean.
Suppress the validation of that input element. (How?)
Suppress the MyFaces warning somehow. (How?)

1. An input element should always have a reference in the backing bean, everything else is a design error
Not true.
2. Just use a "dummy" value that points to an unused field in the bean.
No. That's ridiculous in short term and confusing in long term at best.
3. Suppress the validation of that input element. (How?)
You could do. You can use <f:validateBean> for that.
<h:inputXxx>
<f:validateBean disabled="true" />
</h:inputXxx>
4. Suppress the MyFaces warning somehow. (How?)
Based on its source code there doesn't seem to be any way. You'd best ask them to log it only during Development stage.

Related

Required asterisk is not displayed in input fields Primefaces 6.0

I have created a form using Primefaces 6.0 and in the bean I have used constrained validators like #NotNull and #NotEmpty in the bean fields. However the asterisk near the label of the input text are not automatically rendered. The asterisk is only displayed when I set and an inputText as "required=true". My problem is that I would like to use the validation messages provided by the bean validation JSR so I would not like to put "required"to the input texts. I have also read that after primefaces 5.0 the validation constraints are automatically detected and the asterisk is rendered automatically. Has anyone faced a similar problem? Have I missed any configuration?
i think whatever you want is possible by some custom code, use CSS for asterisk (*) in read color, do not put required=true use custom validate. have look https://www.primefaces.org/showcase/ui/csv/custom.xhtml
if you did not put required=true your form will submmited to bean and you have to check and bean level for validation.
That is a nice to have feature that doesn't exist (yet).
If you want it implemented, log an enhancement feature.
Or extend bean validation component ;-)

Can JSF be configured to not invoke Entity setter unless the field actually changed?

When a JSF form field is wired into an entity bean field (which is mapped to a DB field), each setter in the entity bean is called regardless of whether the user changed the form field value in the front end, i.e. the setters on unchanged fields are invoked the same as those that have changed but their new value is the same as the old value.
My question is simple: Is there a way to configure JSF to only call the setters mapped to the fields that have changed in the front end? The reason for this is that I have a requirement by which I have to detect deltas on every persist and log them, more about which can be read in this question.
Maybe I didn't understand you clearly, but why are you mapping directly your entity beans to a JSF view ?! IMHO it would be better if you add managed beans between your JSF pages and the entities in order to better separate your business logic from data access.
Any way, I think the easiest solution to impelement for that case is by making use of Value Change Events which are invoked "normally" after the Process Validations phase (unless you make use of the immediate attribute).
The good news about Value Change Events (regarding your example) is they are invoked ONLY after you force form submit using JavaScript or Command components AND the new value is different from the old value.
So, as an example on how to use value change listeners, you can add valueChangeListner attribute to each of your JSF tags like following:
<h:inputText id="input" value="#{someBean.someValue}"
valueChangeListener="#{someBean.valueChanged} />
Then, implement your valueChanged() method to look something like:
public void valueChanged(ValueChangeEvent event) {
// You can use event.getOldValue() and event.getNewValue() to get the old or the new value
}
Using the above implementation, may help you to separate your logging code (it will be included in the listeners) from your managed properties setters.
NB: Value Change Listeners may also be implemetend otherwise using the f:valueChangeListener Tag, but this is not the best choice for your example (you can find some examples in the section below, just in case)
See also:
Valuechangelistener Doubt in JSF
JSF 2 valueChangeListener example
When to use valueChangeListener or f:ajax listener?

EL function not found in validator attribute

El function cannot be found using within validator attribute, which is dependent on dynamic or repeated values?
Function 'el:min' not found
#{el:min(a + b, c)}
<f:validateLongRange maximum="#{el:min(foo.bar, 10)}"/>
Just printing out the value is working where it is not working in the validator.
The error message Function 'el:min' not found was so misleading.
The problem was never the construct but it was an underlying NullPointerException on the nested property.
Since in one case the value was depending on a different component selection it was updated via ajax and the default value was null. Since the default value was null this misleading exception was thrown.
The value was a nested property, so it was not catched within the el function
Solution: disable the validator on default
<o:validator validatorId="javax.faces.LongRange" maximum="#{el:min(foo.bar, 10)}"
disabled="#{foo eq null}"/>
This construct should work just fine. The problem is most likely the scope of the variables which you've there and the timing (i.e. when do you need them? when are they "behind the scenes" changed?).
You need to understand that taghandlers like <f:xxx> run during view build time (like JSTL <c:xxx>). So their attribtues are resolved during view build time and would be filled with bean's default values. Perhaps you're performing some business logic on them while submitting the form and expecting that they would be reflected into the taghandler attribute. But this is not true. They were already evaluated during view build time and won't re-evaluate the values during processing the form submit.
If this is indeed the case, then you've basically the same problem which is already outlined and answered with various possible solutions in this answer: How to set converter properties for each row of a datatable? Apart form homegrowing a Validator for this, you could use OmniFaces <o:validator> for this:
<o:validator validatorId="javax.faces.LongRange" maximum="#{el:min(a + b, c)}" />

JSF Problem with selectInputDate overriding a set value

I have a problem with selectInputDate:
I have a backing bean which I am binding to the selectInputDate. I have a menu which, when the menu changes, I set the date to now to the same property the selectInputDate is bound to.
For some reason, the date changes correctly, but the selectInputDate then calls a set and overrides the value with the old value...
Any idea why selectInputDate would call the setter?
<ice:selectInputDate popupDateFormat="dd-MMM-yyyy" renderAsPopup="true" value="#{dateContoller.date}"/>
<ice:selectOneMenu value="#{dateContoller.dateRange}" valueChangeListener="#{dateRangeDateContoller.dateRangeChanged}" >
....
</ice:selectOneMenu>
(dateRangeChanged sets the current date to now)
The valueChangeListener is intend to run some code logic whenever the newly submitted value differs from the original value. But you're apparently actually not interested in the change of the value, you're actually interested in resetting the submitted value.
Just get rid of the valueChangeListener and do your thing in the bean's action method.
If that is not an option for some reason, then you need to elaborate more about the problem for which you thought that using a valueChangeListener is the right solution. There may be workarounds to keep the valueChangeListener anyway, such as calling FacesContext#renderResponse(), so that JSF won't run the update model values (and invoke action!) phases anymore, or using ValueChangeEvent#queue() to let it re-execute itself during invoke action phase.
To learn a bit more about the JSF lifecycle and when/why/how the one and other get called/invoked, you may find this practical article useful.

JSF validation error, lost value

I have a update form, with composite keys All composite keys are displayed in outputbox as I have hidden field for each composite keys. These outputbox values are empty after validation error. How do I resolve this. I am on the same page so doesn't it has to have the values.
This is indeed a non-intuitive behaviour of the h:inputHidden (I've ever filed a issue against it at the Mojarra issue list, but they didn't seem to do anything with it). The whole problem is that the component's value unnecessarily is also taken into the entire validation cycle while there's no means of user-controlled input. It will get lost when the validation fails. There are at least three ways to fix this non-intuitive behaviour.
First way is to use the binding on the h:inputHidden instead:
<h:inputHidden binding="#{bean.hidden}" />
This way the value won't undergo the unnecessary validation cycle. This however requires changes in the way you get/set the values in the backing bean code. For example:
private HtmlInputHidden hidden = new HtmlInputHidden(); // +getter +setter.
public void setHiddenValue(Object hiddenValue) {
hidden.setValue(hiddenValue);
}
public Object getHiddenValue() {
return hidden.getValue();
}
Second (and IMHO the preferred way) is to use Tomahawk's t:saveState instead.
<t:saveState value="#{bean.property}" />
The major advantage is that you don't need to change anything in the backing bean code. It will restore the value early before the apply request values phase. You only need to add extra libraries if not done yet, but as Tomahawk provides much more advantages than only the t:saveState, such as the in basic JSF implementation missing components/features t:inputFileUpload, t:dataList, t:dataTable preserveDataModel="true", t:selectOneRadio layout="spread" and so on, it is worth the effort.
The third way is to store it in a session scoped bean, but you actually don't want to do that for request scoped variables. It would only give "wtf?" experiences when the enduser has multiple tabs/windows open in the same session.

Resources