You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Behrang Saeedzadeh <be...@gmail.com> on 2006/12/19 20:59:47 UTC

commandLink problems - once again - this time with selectOneMenu!

Hi,

<em>

I think in a day or two I have to rest in a hospital because JSF is
almost making me schizophrenic! ;-)

</em>

I have uploaded the source/binary of the sample app I am working on it:

   http://files.myopera.com/behrangsa/files/JSF-HOWTO.zip

Just copy the exploded directory to Tomcat's webapps directory and it
should run with no problems.

Click on the h:selectOneMenu link, and then on the Show Items link.
Then select an item from the menu and press the Select link.

I thought this is gonna set the selectedItemId in the backing bean and
show it when the page redisplays. But instead, a validation error
occurs. The version that uses t:saveState doesn't work as well.

Any ideas how can I make this work, without falling back to the session scope?

<em>

What I was able to accomplish in Struts and WebWork, just the same day
I read a tutorial about each one of them, has left me scratch my head
for more than a week. Yes, I could use the session scope, but I can't
ask my customers to restart their app server once an hour! Nor do they
have the resources to buy a supercomputer from Cray!

</em>


P.S: Does anybody know if it's just as difficult (or as inefficient)
to implement this use-case in ASP.NET?

-- 
"Science is a differential equation. Religion is a boundary condition"
- Alan Turing

Behrang Saeedzadeh
http://www.jroller.com/page/behrangsa
http://my.opera.com/behrangsa

Re: commandLink problems - once again - this time with selectOneMenu!

Posted by Behrang Saeedzadeh <be...@gmail.com>.
Hi Simon,

Overall, I was thinking about what you said and I am coming to the
conclusion that the way JSF currently handles this situation might be
indeed just fine. But I am still a little bit in doubt.

> 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.

If the selectOneMenu had cached the SelectItems it created during the
Render Reponse phase, and reused these values, instead of executing
the binding once again and querying the database, we could still
assure that the value the user has selected is something that has been
present in the menu, and thus, not fake.

Also, if I had retrieved the data from database, created the
selectOneMenu programatically, and bound it to the corresponding tag
in the page, JSF could not anymore validate the data against the
database. If I could somehow accomplish this without component
binding... :-)

Kindest regards,
Behi

-- 
"Science is a differential equation. Religion is a boundary condition"
- Alan Turing

Behrang Saeedzadeh
http://www.jroller.com/page/behrangsa
http://my.opera.com/behrangsa

Re: commandLink problems - once again - this time with selectOneMenu!

Posted by Simon Kitching <si...@rhe.co.nz>.
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

Re: commandLink problems - once again - this time with selectOneMenu!

Posted by David Delbecq <de...@oma.be>.
En l'instant précis du 12/21/06 00:00, Behrang Saeedzadeh s'exprimait
dans toute sa noblesse:
>
> That would make the items remain in memory far longer than they are
> actually needed to be. I was hoping to avoid the session.
There is also the application scope, it has some usage for handling
application wide lists :) Also everything that is user specific and
stays longer than request scope has to go in session. So if
selectonemenu was to keep it's list of datas, that would be in session.
>
>> 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.
>
> Could you please explain a little more?
>From my experience is struts, it's quite common to have to direct user
to a .do link that will initialize lists before rendering. So you in
fact need to invoke a first struts action (something.do?dispatch=init).
What you were doing in your example is to provide a link that will call
an action that will 'init' your list before first rendering. That's bad
for 2 reasons.
1) you need an action to access your 'select' form.
2) Your list will empty when you rerender form (eg if you fail validation)

JSF has powerfull mecanism to initialize your beans. You can even
initialize some properties of your beans to values of EL expression and
link between managed beans. All this in your faces-config.xml.
All the init steps can then be done either in the bean code and you can
have your request scope bean preconfigured so it has access to session
or application wide managed beans. This is very interesting when you
need to use request scope bean but have to persist some informations
(like list of items). The request scope bean then acts as a facade.
>
> Yeah. I tried t:saveState. It worked great for me. Thanks for the tip :-)
>
Glad to hear you have a working solution :)
> Regards,
> Behi
>


Re: commandLink problems - once again - this time with selectOneMenu!

Posted by Behrang Saeedzadeh <be...@gmail.com>.
David,

> 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.

That would make the items remain in memory far longer than they are
actually needed to be. I was hoping to avoid the session.

> 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.

Could you please explain a little more?

> 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...

Yeah. I tried t:saveState. It worked great for me. Thanks for the tip :-)

Regards,
Behi

-- 
"Science is a differential equation. Religion is a boundary condition"
- Alan Turing

Behrang Saeedzadeh
http://www.jroller.com/page/behrangsa
http://my.opera.com/behrangsa

Re: commandLink problems - once again - this time with selectOneMenu!

Posted by David Delbecq <de...@oma.be>.
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
>


Re: commandLink problems - once again - this time with selectOneMenu!

Posted by Behrang Saeedzadeh <be...@gmail.com>.
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

-- 
"Science is a differential equation. Religion is a boundary condition"
- Alan Turing

Behrang Saeedzadeh
http://www.jroller.com/page/behrangsa
http://my.opera.com/behrangsa

Re: commandLink problems - once again - this time with selectOneMenu!

Posted by David Delbecq <de...@oma.be>.
Somehow, my answer yesterday didn't make it to mailing list! Here is a
cut and paste from my sent folder, hope this helps you

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.

For details, see sun jsf javadoc, found the doc in 5 minutes  :) 

http://java.sun.com/javaee/javaserverfaces/1.0/docs/api/javax/faces/component/UISelectOne.html

void  validate(javax.faces.context.FacesContext context)
           In addition to the standard validation behavior inherited
from UIInput, ensure that any specified value is equal to one of the
available options.

Thrust JSF, if it tells you there is a validation, that obviously mean
you value didn't pass validation.

So no, jsf is not that hard  :)  But like every framework, sometimes a
problem can get you crazy when you try for hours to find the reason that
is just below you noise.

btw: <h:messages showDetails="true"/> is your friend  :) 

So you solution, always populate your list correctly.





Behrang Saeedzadeh a écrit :
> Sorry but the previous sample app had a small problem. It was not
> related to the commandLink problem nevertheless I've fixed it.
>
> The updated bundle can be found here:
> http://files.myopera.com/behrangsa/files/1JSF-HOWTO.zip
>
> Best regards,
> Behi
>
> On 12/19/06, Behrang Saeedzadeh <be...@gmail.com> wrote:
>> Hi,
>>
>> <em>
>>
>> I think in a day or two I have to rest in a hospital because JSF is
>> almost making me schizophrenic! ;-)
>>
>> </em>
>>
>> I have uploaded the source/binary of the sample app I am working on it:
>>
>>    http://files.myopera.com/behrangsa/files/JSF-HOWTO.zip
>>
>> Just copy the exploded directory to Tomcat's webapps directory and it
>> should run with no problems.
>>
>> Click on the h:selectOneMenu link, and then on the Show Items link.
>> Then select an item from the menu and press the Select link.
>>
>> I thought this is gonna set the selectedItemId in the backing bean and
>> show it when the page redisplays. But instead, a validation error
>> occurs. The version that uses t:saveState doesn't work as well.
>>
>> Any ideas how can I make this work, without falling back to the
>> session scope?
>>
>> <em>
>>
>> What I was able to accomplish in Struts and WebWork, just the same day
>> I read a tutorial about each one of them, has left me scratch my head
>> for more than a week. Yes, I could use the session scope, but I can't
>> ask my customers to restart their app server once an hour! Nor do they
>> have the resources to buy a supercomputer from Cray!
>>
>> </em>
>>
>>
>> P.S: Does anybody know if it's just as difficult (or as inefficient)
>> to implement this use-case in ASP.NET?
>>
>> -- 
>> "Science is a differential equation. Religion is a boundary condition"
>> - Alan Turing
>>
>> Behrang Saeedzadeh
>> http://www.jroller.com/page/behrangsa
>> http://my.opera.com/behrangsa
>>
>
>


Re: commandLink problems - once again - this time with selectOneMenu!

Posted by Behrang Saeedzadeh <be...@gmail.com>.
Sorry but the previous sample app had a small problem. It was not
related to the commandLink problem nevertheless I've fixed it.

The updated bundle can be found here:
http://files.myopera.com/behrangsa/files/1JSF-HOWTO.zip

Best regards,
Behi

On 12/19/06, Behrang Saeedzadeh <be...@gmail.com> wrote:
> Hi,
>
> <em>
>
> I think in a day or two I have to rest in a hospital because JSF is
> almost making me schizophrenic! ;-)
>
> </em>
>
> I have uploaded the source/binary of the sample app I am working on it:
>
>    http://files.myopera.com/behrangsa/files/JSF-HOWTO.zip
>
> Just copy the exploded directory to Tomcat's webapps directory and it
> should run with no problems.
>
> Click on the h:selectOneMenu link, and then on the Show Items link.
> Then select an item from the menu and press the Select link.
>
> I thought this is gonna set the selectedItemId in the backing bean and
> show it when the page redisplays. But instead, a validation error
> occurs. The version that uses t:saveState doesn't work as well.
>
> Any ideas how can I make this work, without falling back to the session scope?
>
> <em>
>
> What I was able to accomplish in Struts and WebWork, just the same day
> I read a tutorial about each one of them, has left me scratch my head
> for more than a week. Yes, I could use the session scope, but I can't
> ask my customers to restart their app server once an hour! Nor do they
> have the resources to buy a supercomputer from Cray!
>
> </em>
>
>
> P.S: Does anybody know if it's just as difficult (or as inefficient)
> to implement this use-case in ASP.NET?
>
> --
> "Science is a differential equation. Religion is a boundary condition"
> - Alan Turing
>
> Behrang Saeedzadeh
> http://www.jroller.com/page/behrangsa
> http://my.opera.com/behrangsa
>


-- 
"Science is a differential equation. Religion is a boundary condition"
- Alan Turing

Behrang Saeedzadeh
http://www.jroller.com/page/behrangsa
http://my.opera.com/behrangsa

Re: commandLink problems - once again - this time with selectOneMenu!

Posted by delbd <de...@oma.be>.
You select one 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.

For details, see sun jsf javadoc, found the doc in 5 minutes :)

http://java.sun.com/javaee/javaserverfaces/1.0/docs/api/javax/faces/component/UISelectOne.html

void  validate(javax.faces.context.FacesContext context)
           In addition to the standard validation behavior inherited
from UIInput, ensure that any specified value is equal to one of the
available options.

Thrust JSF, if it tells you there is a validation, that obviously mean
you value didn't pass validation.

So no, jsf is not that hard :) But like every framework, sometimes a
problem can get you crazy when you try for hours to find the reason that
is just below you noise.

btw: <h:messages showDetails="true"/> is your friend :)

So you solution, always populate your list correctly.


Behrang Saeedzadeh a écrit :
> Hi,
>
> <em>
>
> I think in a day or two I have to rest in a hospital because JSF is
> almost making me schizophrenic! ;-)
>
> </em>
>
> I have uploaded the source/binary of the sample app I am working on it:
>
>   http://files.myopera.com/behrangsa/files/JSF-HOWTO.zip
>
> Just copy the exploded directory to Tomcat's webapps directory and it
> should run with no problems.
>
> Click on the h:selectOneMenu link, and then on the Show Items link.
> Then select an item from the menu and press the Select link.
>
> I thought this is gonna set the selectedItemId in the backing bean and
> show it when the page redisplays. But instead, a validation error
> occurs. The version that uses t:saveState doesn't work as well.
>
> Any ideas how can I make this work, without falling back to the
> session scope?
>
> <em>
>
> What I was able to accomplish in Struts and WebWork, just the same day
> I read a tutorial about each one of them, has left me scratch my head
> for more than a week. Yes, I could use the session scope, but I can't
> ask my customers to restart their app server once an hour! Nor do they
> have the resources to buy a supercomputer from Cray!
>
> </em>
>
>
> P.S: Does anybody know if it's just as difficult (or as inefficient)
> to implement this use-case in ASP.NET?
>