You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Jakob Korherr <ja...@gmail.com> on 2009/12/11 11:14:11 UTC

Re: [Trinidad] Cannot Add Item to SelectManyShuttle After Initial Rendering

Hi Gregg,

The problem is, that the SelectItem, which you add via javascript, is not
included in SelectItemSupport.getSelectItemCount(component).

Looking at the code of shuttle.js, I found out that addItem() also adds the
new item to a hidden field in the form with name clientId:items. So the
server should know that you added the related item. However, I could not
find the server side code, which does that.

Maybe anyone else knows where this is accomplished.

Regards,

Jakob Korherr

2009/12/11 <gs...@verizon.net>

> I have a Select Many Ordered Shuttle working in a faces page. The tag
> documentation contract for the shuttle states:
>
> ------------------------------------------
>  -- JavaScript proxies --
>
> In some cases, developers will need to use JavaScript to manipulate or use
> the contents of the lists.  This may be required as actions for the buttons
> or icons in the shuttle footers or outside the shuttle all together. Thus, a
> set of Javascript utility methods are available that operate on the lists.
>  These are located in the shuttle.js Javascript library, which is
> automatically loaded if you use the shuttle.
>
> These methods can be accessed by creating a ShuttleProxy instance based on
> the shuttle client ID and form.
>                // create the proxy object
>                var proxy2 = new ShuttleProxy("testShuttle2", "testForm2");
>
> Once the proxy is created, you can use it to gain information about the
> lists or to manipulate the lists in the shuttle.  The proxy provides the
> following functions:
> ...
> addItem(leadingList, index, text, value, description) : adds an item at the
> given index to a list.  The item is added to the leading list if leadingList
> is true, otherwise it is added to the trailing list. The index should be 0
> based.  Thus, to insert an item at the end of a list, set index to
> shuttleProxy.getItemCount(leadinglist).  The text parameter specifies the
> display text for the item, while the value parameter specifies the value
> that represents this item upon form submission. The description parameter
> specifies a description of the item. The description parameter can be
> omitted
> ....
>
> -------------------------------------------
>
> I have written the JavaScript code to add an item to the shuttle and this
> works at the client end; however, when I try and submit the shuttle lists,
> the server end fails when it gets to class
> org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SelectManyShuttleRenderer
> when it is decoding the submitted list in method getSubmittedValue as shown
> below:
>
>   protected Object getSubmittedValue(
>     FacesContext context,
>     UIComponent  component,
>     String       clientId)
>   {
>     // Since we override getSubmittedValue() entirely,
>     // detect auto submit manually
>     detectAutoSubmit(context, component, clientId);
>
>     String trailingId = clientId + ":trailing:items";
>     String paramValue = (String) context.getExternalContext().
>                                 getRequestParameterMap().get(trailingId);
>     if ((paramValue == null) || "".equals(paramValue))
>       return new String[0];
>
>     List<String> list = new ArrayList<String>();
>     StringTokenizer tokenizer = new StringTokenizer(paramValue, ";");
>
>     // don't let the submitted list get any bigger than the number of
>     // total items in the shuttle
>     int availableItems = SelectItemSupport.getSelectItemCount(component);
>     int numItems = 0;
>     while (tokenizer.hasMoreElements())
>     {
>       numItems++;
>       if (numItems > availableItems)
>       {
>         _LOG.severe("SELECTED_SHUTTLE_ITEMS_EXCEEDED_TOTAL_NUMBER",
> clientId);
>         return new String[0];
>       }
>
>       list.add(tokenizer.nextToken());
>     }
>
> The check to confirm that the number of submitted items is not greater than
> the original shuttle list already in existence at the server end, stops any
> user from adding an additional item to the shuttle. I understand that this
> may have been done to protect against an attack where someone sends in a
> huge list of shuttle items, BUT this seems to be in direct conflict with the
> shuttle contract above that states that I should be able to add one or more
> items to a shuttle at the client end. I don't believe the intention was
> simply to add items to the shuttle at the client end without submitting it.
>
> I was unable to find any examples, working or otherwise, anywhere that
> demonstrate said functionality.
>
> Given the above, if this getSubmittedValue code is correct and the addItem
> contract is also correct, how does one add an item to an existing shuttle
> AND submit it to the server?
>
>                                        -=> Gregg <=-
>
>
>

Re: [Trinidad] Cannot Add Item to SelectManyShuttle After Initial Rendering

Posted by Gregg Leichtman <gs...@verizon.net>.
I  commented out the code shown below and the round trip worked
perfectly, so should I conclude that it is necessary to drop this check
in order to meet the contract, since I don't believe that the client
programmer should have to override a package private method in order to
use the addItem function?

I also noticed, by placing breakpoints in my bean, that the
getSubmittedValue method of the shuttle renderer is, of course, called
during the request parameter decoding stage before my bean's
valueChanged method is ever invoked. In fact the only chance my bean's
code ever gets to try and circumvent this problem is in a setter in my
bean associated with the submit action. This setter does not, of course,
get passed the valueChanged event and gets invoked prior to the
getSubmittedValue decoding which does not seem to be the correct place
to try and "fix" this problem. It seems to me that this check, although
probably well-intentioned, assuming that it is there to prevent client
programmer mistakes or overflow attacks, may need to be removed with a
documented cavaet to the user of the shuttle that they should put in
code to do said check AFTER the decoding stage. If this view is correct
and assuming that the JSF standard is not violated, then possibly a
method such as confirmValidSubmittedValue should be created such that
the client programmer of the shuttle can override the method with any
logic they need. The original logic in the parent method supplied by the
toolkit would simply include the check logic below (altered accordingly
to account for being executed in a stage following the decoding stage),
but at the client programmer's discretion could, for example, include
code to limit the number of additions within a given time window to help
thwart an attack.

  protected Object getSubmittedValue(
    FacesContext context,
    UIComponent  component,
    String       clientId)
  {
    // Since we override getSubmittedValue() entirely,
    // detect auto submit manually
    detectAutoSubmit(context, component, clientId);

    String trailingId = clientId + ":trailing:items";
    String paramValue = (String) context.getExternalContext().
                                getRequestParameterMap().get(trailingId);
    if ((paramValue == null) || "".equals(paramValue))
      return new String[0];

    List<String> list = new ArrayList<String>();
    StringTokenizer tokenizer = new StringTokenizer(paramValue, ";");

    // don't let the submitted list get any bigger than the number of
    // total items in the shuttle
//    int availableItems = SelectItemSupport.getSelectItemCount(component);
    int numItems = 0;
    while (tokenizer.hasMoreElements())
    {
      numItems++;
//      if (numItems > availableItems)
//      {
//        _LOG.severe("SELECTED_SHUTTLE_ITEMS_EXCEEDED_TOTAL_NUMBER",clientId);
//        return new String[0];
//      }

      list.add(tokenizer.nextToken());
    }




On 12/11/2009 05:16 AM, Rafa Pérez wrote:
> Maybe you can force an update of the SelectItems via PPR when the new item
> is added. This way, you can handle this element at server side.
>
> HTH,
>
> -- Rafa
>
> On Fri, Dec 11, 2009 at 11:14 AM, Jakob Korherr <ja...@gmail.com>wrote:
>
>   
>> Hi Gregg,
>>
>> The problem is, that the SelectItem, which you add via javascript, is not
>> included in SelectItemSupport.getSelectItemCount(component).
>>
>> Looking at the code of shuttle.js, I found out that addItem() also adds the
>> new item to a hidden field in the form with name clientId:items. So the
>> server should know that you added the related item. However, I could not
>> find the server side code, which does that.
>>
>> Maybe anyone else knows where this is accomplished.
>>
>> Regards,
>>
>> Jakob Korherr
>>
>> 2009/12/11 <gs...@verizon.net>
>>
>>     
>>> I have a Select Many Ordered Shuttle working in a faces page. The tag
>>> documentation contract for the shuttle states:
>>>
>>> ------------------------------------------
>>>  -- JavaScript proxies --
>>>
>>> In some cases, developers will need to use JavaScript to manipulate or
>>>       
>> use
>>     
>>> the contents of the lists.  This may be required as actions for the
>>>       
>> buttons
>>     
>>> or icons in the shuttle footers or outside the shuttle all together.
>>>       
>> Thus, a
>>     
>>> set of Javascript utility methods are available that operate on the
>>>       
>> lists.
>>     
>>>  These are located in the shuttle.js Javascript library, which is
>>> automatically loaded if you use the shuttle.
>>>
>>> These methods can be accessed by creating a ShuttleProxy instance based
>>>       
>> on
>>     
>>> the shuttle client ID and form.
>>>                // create the proxy object
>>>                var proxy2 = new ShuttleProxy("testShuttle2",
>>>       
>> "testForm2");
>>     
>>> Once the proxy is created, you can use it to gain information about the
>>> lists or to manipulate the lists in the shuttle.  The proxy provides the
>>> following functions:
>>> ...
>>> addItem(leadingList, index, text, value, description) : adds an item at
>>>       
>> the
>>     
>>> given index to a list.  The item is added to the leading list if
>>>       
>> leadingList
>>     
>>> is true, otherwise it is added to the trailing list. The index should be
>>>       
>> 0
>>     
>>> based.  Thus, to insert an item at the end of a list, set index to
>>> shuttleProxy.getItemCount(leadinglist).  The text parameter specifies the
>>> display text for the item, while the value parameter specifies the value
>>> that represents this item upon form submission. The description parameter
>>> specifies a description of the item. The description parameter can be
>>> omitted
>>> ....
>>>
>>> -------------------------------------------
>>>
>>> I have written the JavaScript code to add an item to the shuttle and this
>>> works at the client end; however, when I try and submit the shuttle
>>>       
>> lists,
>>     
>>> the server end fails when it gets to class
>>>
>>>       
>> org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SelectManyShuttleRenderer
>>     
>>> when it is decoding the submitted list in method getSubmittedValue as
>>>       
>> shown
>>     
>>> below:
>>>
>>>   protected Object getSubmittedValue(
>>>     FacesContext context,
>>>     UIComponent  component,
>>>     String       clientId)
>>>   {
>>>     // Since we override getSubmittedValue() entirely,
>>>     // detect auto submit manually
>>>     detectAutoSubmit(context, component, clientId);
>>>
>>>     String trailingId = clientId + ":trailing:items";
>>>     String paramValue = (String) context.getExternalContext().
>>>                                 getRequestParameterMap().get(trailingId);
>>>     if ((paramValue == null) || "".equals(paramValue))
>>>       return new String[0];
>>>
>>>     List<String> list = new ArrayList<String>();
>>>     StringTokenizer tokenizer = new StringTokenizer(paramValue, ";");
>>>
>>>     // don't let the submitted list get any bigger than the number of
>>>     // total items in the shuttle
>>>     int availableItems = SelectItemSupport.getSelectItemCount(component);
>>>     int numItems = 0;
>>>     while (tokenizer.hasMoreElements())
>>>     {
>>>       numItems++;
>>>       if (numItems > availableItems)
>>>       {
>>>         _LOG.severe("SELECTED_SHUTTLE_ITEMS_EXCEEDED_TOTAL_NUMBER",
>>> clientId);
>>>         return new String[0];
>>>       }
>>>
>>>       list.add(tokenizer.nextToken());
>>>     }
>>>
>>> The check to confirm that the number of submitted items is not greater
>>>       
>> than
>>     
>>> the original shuttle list already in existence at the server end, stops
>>>       
>> any
>>     
>>> user from adding an additional item to the shuttle. I understand that
>>>       
>> this
>>     
>>> may have been done to protect against an attack where someone sends in a
>>> huge list of shuttle items, BUT this seems to be in direct conflict with
>>>       
>> the
>>     
>>> shuttle contract above that states that I should be able to add one or
>>>       
>> more
>>     
>>> items to a shuttle at the client end. I don't believe the intention was
>>> simply to add items to the shuttle at the client end without submitting
>>>       
>> it.
>>     
>>> I was unable to find any examples, working or otherwise, anywhere that
>>> demonstrate said functionality.
>>>
>>> Given the above, if this getSubmittedValue code is correct and the
>>>       
>> addItem
>>     
>>> contract is also correct, how does one add an item to an existing shuttle
>>> AND submit it to the server?
>>>
>>>                                        -=> Gregg <=-
>>>
>>>
>>>
>>>       
>>     
>   



Re: [Trinidad] Cannot Add Item to SelectManyShuttle After Initial Rendering

Posted by Rafa Pérez <ra...@gmail.com>.
Maybe you can force an update of the SelectItems via PPR when the new item
is added. This way, you can handle this element at server side.

HTH,

-- Rafa

On Fri, Dec 11, 2009 at 11:14 AM, Jakob Korherr <ja...@gmail.com>wrote:

> Hi Gregg,
>
> The problem is, that the SelectItem, which you add via javascript, is not
> included in SelectItemSupport.getSelectItemCount(component).
>
> Looking at the code of shuttle.js, I found out that addItem() also adds the
> new item to a hidden field in the form with name clientId:items. So the
> server should know that you added the related item. However, I could not
> find the server side code, which does that.
>
> Maybe anyone else knows where this is accomplished.
>
> Regards,
>
> Jakob Korherr
>
> 2009/12/11 <gs...@verizon.net>
>
> > I have a Select Many Ordered Shuttle working in a faces page. The tag
> > documentation contract for the shuttle states:
> >
> > ------------------------------------------
> >  -- JavaScript proxies --
> >
> > In some cases, developers will need to use JavaScript to manipulate or
> use
> > the contents of the lists.  This may be required as actions for the
> buttons
> > or icons in the shuttle footers or outside the shuttle all together.
> Thus, a
> > set of Javascript utility methods are available that operate on the
> lists.
> >  These are located in the shuttle.js Javascript library, which is
> > automatically loaded if you use the shuttle.
> >
> > These methods can be accessed by creating a ShuttleProxy instance based
> on
> > the shuttle client ID and form.
> >                // create the proxy object
> >                var proxy2 = new ShuttleProxy("testShuttle2",
> "testForm2");
> >
> > Once the proxy is created, you can use it to gain information about the
> > lists or to manipulate the lists in the shuttle.  The proxy provides the
> > following functions:
> > ...
> > addItem(leadingList, index, text, value, description) : adds an item at
> the
> > given index to a list.  The item is added to the leading list if
> leadingList
> > is true, otherwise it is added to the trailing list. The index should be
> 0
> > based.  Thus, to insert an item at the end of a list, set index to
> > shuttleProxy.getItemCount(leadinglist).  The text parameter specifies the
> > display text for the item, while the value parameter specifies the value
> > that represents this item upon form submission. The description parameter
> > specifies a description of the item. The description parameter can be
> > omitted
> > ....
> >
> > -------------------------------------------
> >
> > I have written the JavaScript code to add an item to the shuttle and this
> > works at the client end; however, when I try and submit the shuttle
> lists,
> > the server end fails when it gets to class
> >
> org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SelectManyShuttleRenderer
> > when it is decoding the submitted list in method getSubmittedValue as
> shown
> > below:
> >
> >   protected Object getSubmittedValue(
> >     FacesContext context,
> >     UIComponent  component,
> >     String       clientId)
> >   {
> >     // Since we override getSubmittedValue() entirely,
> >     // detect auto submit manually
> >     detectAutoSubmit(context, component, clientId);
> >
> >     String trailingId = clientId + ":trailing:items";
> >     String paramValue = (String) context.getExternalContext().
> >                                 getRequestParameterMap().get(trailingId);
> >     if ((paramValue == null) || "".equals(paramValue))
> >       return new String[0];
> >
> >     List<String> list = new ArrayList<String>();
> >     StringTokenizer tokenizer = new StringTokenizer(paramValue, ";");
> >
> >     // don't let the submitted list get any bigger than the number of
> >     // total items in the shuttle
> >     int availableItems = SelectItemSupport.getSelectItemCount(component);
> >     int numItems = 0;
> >     while (tokenizer.hasMoreElements())
> >     {
> >       numItems++;
> >       if (numItems > availableItems)
> >       {
> >         _LOG.severe("SELECTED_SHUTTLE_ITEMS_EXCEEDED_TOTAL_NUMBER",
> > clientId);
> >         return new String[0];
> >       }
> >
> >       list.add(tokenizer.nextToken());
> >     }
> >
> > The check to confirm that the number of submitted items is not greater
> than
> > the original shuttle list already in existence at the server end, stops
> any
> > user from adding an additional item to the shuttle. I understand that
> this
> > may have been done to protect against an attack where someone sends in a
> > huge list of shuttle items, BUT this seems to be in direct conflict with
> the
> > shuttle contract above that states that I should be able to add one or
> more
> > items to a shuttle at the client end. I don't believe the intention was
> > simply to add items to the shuttle at the client end without submitting
> it.
> >
> > I was unable to find any examples, working or otherwise, anywhere that
> > demonstrate said functionality.
> >
> > Given the above, if this getSubmittedValue code is correct and the
> addItem
> > contract is also correct, how does one add an item to an existing shuttle
> > AND submit it to the server?
> >
> >                                        -=> Gregg <=-
> >
> >
> >
>