6

As described in this question I try to perform some field validation in a form on the backing bean side. For this I would like to access the violating fields to mark them. From searching the web there seem to be two ways to do this:

  • store the components in the backing bean for access and use them in the JSF pages via the binding attribute.
  • Use standard value binding in the JSF pages and when needing access to a component from the bean, look it up via UIViewRoot.findComponent(String id)

As far as I can see both ways have drawbacks: Component bindings blows up the backing bean with variables and getters/setters, some sites strongly discourage the use of component binding at all. In any case, a request scope is advised. On the other hand, findComponent() always traverses the tree, which may or may not be costly, right? (Plus, at the moment I can't find my component at all, but that is another problem)

Which would be the way to go? Are these interchangeable alternatives and if not, based on what criteria do you chose? Currently I just don't have enough insight to make a decent decision...

Community
  • 1
  • 1
Louise
  • 1,451
  • 1
  • 18
  • 40
  • Same question in [this other forum](http://www.jguru.com/forums/view.jsp?EID=1522894#), but alas, no answers ;) – Louise Sep 18 '12 at 09:22

1 Answers1

9

First of all, regardless of the choice, both are a poor practice. See also How does the 'binding' attribute work in JSF? When and how should it be used?

If you had to make the choice, component bindings are definitely faster and cheaper. It makes logically completely sense that a tree scan as done by UIComponent#findComponent() has its performance implications.

Indeed, the backing bean holding the component bindings must be request scoped, but you could easily inject a different scoped backing bean holding the business logic in it by @ManagedProperty.

A cleaner approach would be to use a Map as holder of all component bindings. You only need to add the following entry to faces-config.xml:

<managed-bean>
    <managed-bean-name>components</managed-bean-name>
    <managed-bean-class>java.util.HashMap</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

This can just be used as

<h:inputSome binding="#{components.input1}" />
<h:inputSome binding="#{components.input2}" />
<h:inputSome binding="#{components.input3}" />

And this can be obtained in other beans as

Map<String, UIComponent> components = (Map<String, UIComponent>) externalContext.getRequestMap().get("components");

This way you don't need to worry about specifying individual properties/getters/setters. In the above example, the Map will contain three entries with keys input1, input2 and input3, each with the respective UIComponent instance as value.


Unrelated to the concrete question, there may be a much simpler solution to the concrete problem as you described in the other question than performing the validation in the action method (which is actually Bad Design). I've posted an answer over there.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • does it mean that using normally property binders is not a good practice. We should prefer component bindings in this case? – benz Sep 19 '12 at 09:02
  • I didn't mean to imply that. Using component value bindings should be preferred, but this is out of your current question, right? – BalusC Sep 19 '12 at 11:52
  • That's correct. I saw the question and thought to ask. I will shoot a question regarding it separately. – benz Sep 20 '12 at 05:37
  • @BalusC: As you have marked the HashMap(RequestScoped) in which there will be component instances, will not injecting it in a broader scope (View/ Session) will result in something like this - [The scope of the object referenced by expression [.., request,] is shorter than the referring managed beans () scope of session. I used to get this even though it was solved by passing a request scoped bean as a parameter to the action method of the session scoped bean. – Farhan stands with Palestine Apr 22 '16 at 16:41
  • @Shirgill: Nice catch. Not sure why I had it backwards, perhaps I had CDI in mind. Answer has been fixed, thanks! – BalusC Apr 22 '16 at 19:46