I don't know asp.net
JSF ensure you that never a bean value is set to something invalid. That
is why, before calling the setters, the full form goes throught
validation. And for me, it seems natural that if i put a component in a
form is telling 'select between X, Y and Z', the framework does never
call bean.setSelectedItem('A'), as A is not in the list. Now i agree in
your case you need to prevent double trip to database. Then put list in
another scope than request one.
Btw, i see you are working in two steps action "init" -> show form ->
"action select". If you handle your list initialisation differently, you
can remove the 'init' step, which is typical to struts imho.
you said "If I really needed to assure that the
selected item is still in the database before proceeding any further,
I could do this in the selectItem action method more efficiently. "
That is not true in JSF. In JSF, when your action is called, all your
datas have already been stored in the bean, and your action can assume
those datas as valid. Unlike in struts, you do not have to handle
validation in the action. That does not mean the action will success,
but that guarantes there is no invalid input from the user part. Why
this? because JSF handle all by itself the fact of reshowing the form
when there are invalid entries and pointing out to user what is wrong on
the form (that the use of <h:message for="..."/>)
You asked too
"I think it would be better that we had cached the
value of #{SelectOneMenuBean.selectItems} during Render Response and
just reused those entries during the decode process, although I might
be missing something fundamental here. "
You you could, but then that mean you would have to store this List in
user session until next request, but then problem is that you have no
guarantee that this List is serializable, but J2EE state that anything
stored in user Session MUST be serializable. That's most probably why
they didn't do it in JSF specification. Huh, wait a moment, you want to
keep serializable data between render and action? Great, thats the job
of <t:saveState/> if am not wrong! Of course because those values
transit by client, you can not trust them anymore, but if, as you said,
you want to do validation in action...
As for the why is this behaviour mandatory, ask SUN.
(Note that it's not that hard in JSF to create your own, even complex,
components when you need to. So if you need a selectbox that don't check
value... go on, but then handle the security risks that people might
trick your forms)
En l'instant précis du 12/20/06 14:54, Behrang Saeedzadeh s'exprimait
dans toute sa noblesse:
> David,
>
> Thanks for the response.
>
>> Your selectone bean is request scope. The list of items is populated
>> only during your first action. That mean when user select an item and
>> submit the form, the bean is recreated (request scope) with an empty
>> list (your own initalization code) and jsf can not find a selectItem
>> corresponding to the one you have choosen.
>
> Suppose that we are using Struts or WebWork to handle this scenario.
> In our showItems action we populate the list, then render the result
> to the browser. The user selects one of the items and submits the
> form. In Struts or WebWork, this simply sets the selectedItemId and
> continues to the next page. Why does JSF mandates to ensure that the
> selected item is in the list? If I really needed to assure that the
> selected item is still in the database before proceeding any further,
> I could do this in the selectItem action method more efficiently.
> Actually if this loss of performance was due to gains in productivity,
> that wouldn't be a problem. But I can't see a productivity gain here.
>
> Actually, if I had constructed the menu programatically like this:
>
> List<SelectItem> selectItems = new ArrayList<SelectItem>();
>
> Database d = new Database();
> List<Item> items = d.findAllItems();
> for (Item i : items) {
> SelectItem si = new SelectItem(i.getId(), i.getName());
> selectItems.add(si);
> }
>
> UISelectItems uiSelectItems = new UISelectItems();
> uiSelectItems.setValue(selectItems);
>
> selectOneMenu = (HtmlSelectOneMenu)
> FacesContext.getCurrentInstance().getApplication().createComponent(HtmlSelectOneMenu.COMPONENT_TYPE);
>
> selectOneMenu.getChildren().add(uiSelectItems);
>
> this check wouldn't be a problem because it wouldn't lead to another
> round-trip to the database, as the select items could be restored
> during the restore view phase.
>
> Today I stepped into the MyFaces source code to see how things are
> being done. I found out that during the Render Response phase, the
> value bindings are executed to render the view, i.e.
> #{SelectOneMenuBean.selectItems} is executed during the Render
> Response phase.
>
> Then, again, when I submit the form, #{SelectOneMenuBean.selectItems}
> is at least executed once again, in the decode method of the
> HtmlSelectOneMenu. I think it would be better that we had cached the
> value of #{SelectOneMenuBean.selectItems} during Render Response and
> just reused those entries during the decode process, although I might
> be missing something fundamental here.
>
> Just for the sake of curiosity, do you know if this check to ensure
> that the selected item is still in the list, is also performed in
> ASP.NET?
>
>
> Thanks in advance,
> Behi
>