Behrang Saeedzadeh wrote:
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.
"if I really needed": under what circumstances would you NOT need to do this? You have given the user a list of valid options. However you have no control over what gets submitted; a user can potentially fake the POST response to contain whatever they want. Therefore, for safety every app MUST validate the data before using it, or risk a security hold. It seems to me that by building this in to the standard behaviour, JSF is making apps significantly more robust (by making the check effectively mandatory), and saving developer effort by building the check in to the framework rather than forcing developers to manually check each time.
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.
Well, if the set of options is truly static, then you should simply cache them on the server side (eg as a singleton, Application-scope managed bean, Session-scope managed bean or otherwise) and then there is no loss of efficiency at all.
If the set of options can change (eg are really drawn from a database) then it IS necessary to check at submit that the chosen option is still valid; data should not be pushed into your model classes unless it is valid.
Cheers, Simon

