EL function not found in validator attribute - jsf

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)}" />

Related

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

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.

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 variable resolution in JSF: is there a way to control when it happens?

I often face the following problem. I have a JSF application and a facelet where I write EL expressions, like this:
<h:outputText value="#{myBean.foo}">
As long as myBean, as a variable, has a life long enough, there's no problem to evaluate myBean.foo at any given time, but if myBean is a variable that references some bean within a short period of time, when myBean.foo is evaluated it might be too late, so that JSF complains that myBean resolves to null. This is something well-known, but the problem is that it is not clear to me what to expect in different situations.
Concrete example n. 1: if you try the following with PrimeFaces OrderList:
<p:orderList value="#{bean.myValue}" var="item">
<p:column>
<p:commandLink action="#{bean.doSomething(item)}" />
</p:column>
</p:orderList>`
This is not going to work, because when doSomething is called, the item variable is no longer defined (although the object it references is still alive) and hence it's resolved to null. It's a known issue. However the same pattern works fine with <p:dataTable>, for instance. Anyway, I'm not interested right now in this specific problem, I just want to explain my doubt.
Concrete example n. 2: I have written a composite component with a backing bean. The backing bean extends UINamingContainer and uses its StateHelper to retain a model object. This composite allows to write child tags and I would like to write something like this:
<myns:myCc var="myVar">
<h:inputText value="#{myVar.foo}" />
</myns>
With "myVar" I want to give a name to the model object. To make this work, I tried to store the model object in the request map at the beginning of encodeChildren method and remove it afterwards: this works for rendering, but if I then process the input with a commandButton action, it does not work because when the action gets executed it says that myVar can't be resolved: in other words, it tries to resolve the entire expression too late. I then tried to "permanently" save the model object in the view scope map, but it doens't work either. However, if I change this to:
(assuming modelObject is the property field in the backing bean that stores my model object)
it works. So, it is not a problem in my model, but in the way I try to make the model object available to EL expressions for child tags.
Concrete example n. 3: I often use the <ui:param> tag to give beans a shorter name and to ease templating. For instance:
<ui:param name="bean" value="#{longNamedAndPageSpecificBean}" />
So that, in the remainder of the page I can just use #{bean.foo} instead of #{longNamedAndPageSpecificBean.foo}. This works fine even for actions passed to command buttons. However, if I pass a method expression like #{bean.myActionMethod} to a composite component attribute declared with method-signature, when this method expression is actually invoked I receive an error that bean resolves to null... The reason why it works in one case (with commandButton actions) and not in the other (with actions used by the composite component) is a big source of confusion for me.
I would appreciate if someone can help me to understand better this JSF aspect and suggest better approaches/workarounds with the aforementioned concrete examples.
Your question looks too large, but i could say that, during the build time only Session and request scoped values are avaiaible.
The same thing is true for the Execution phase.
Only the render phase should ensure the avaibility of temporal vars "myVar".
The best way to understand what its realy hapening is to debug because its depends on the component implementation

How to call an action method of a UICommand Component which was rendered conditionally?

action method is not called Please refer to this question - , One of my UICommand Component is rendered conditionally , it was said in the answer of the linked question - point 5 - that if the Component's or any of its parents rendered or disabled attributes are false - then the action method will not be called ? If thats the case- How do i achieve the same functionality? Is there a work around ? or a trick ? or any other approach ?
Thanks!
To the point, you'd like to retain the property responsible for the rendered condition in the subsequent request. There are several solutions for this problem:
Put bean in session scope. It's easy, but it hurts. It's bad for user experience since changes will be reflected in all tabs/windows the user has open in the same session.
Use <h:inputHidden> to transfer the property. In theory easy, but in practice it hurts as well. The value will namely get lost whenever a validation/conversion error has occurred in any of other inputs in the same form. This is an odditity in how JSF handles hidden input elements. A workaround is to use <h:inputHidden binding="#{bean.hidden}"> and do a hidden.getValue() and hidden.setValue() in bean.
If you're using <h:commandLink> instead of <h:commandButton>, then you can use <f:param> to transfer the property. It will be available as request parameter, you can check for it in bean's (post)constructor.
Use Tomahawk's <t:saveState>. The perfect solution as far. This will retain the value (or even a complete bean) in the subsequent request.
If you're already on JSF 2.0, the #ViewScoped would have solved this all. It behaves like the <t:saveState>.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
The trick is to have 'rendered' evaluate to true when it is time to run the action and then change the condition to false in the action method.
Let's say you have a link rendering based on a boolean in your bean called 'editing'. Then your action would look something like this:
public String myAction() {
// whatever you want your action to do
editing = false;
}
Edit: this assumes that the bean is either session scoped or the boolean get propagated between requests.
In my case, Javascript came for rescue, Which means, whatever was to be displayed conditionally , put them in a HTML Portion and don't display them display: none until the desired event occurs.
HTML Portion can have any JSF Tags(including CommandButtons) as you wish and would work (invoking the action methods and the stuff )perfectly okay.

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.

Resources