[jsr-314-open] [Fwd: [NEW] <f:ajax> and <f:validateBean> - consistent wrapping solution needed?]

Pete Muir pmuir at REDHAT.COM
Wed Mar 25 06:19:29 EDT 2009


I agree, this has two benefits I see - first the state saving memory  
improvement, secondly, consistency...

Dan is also out this week, but I'm sure he will go over with Ryan what  
needs doing when he gets a minute :-)

On 24 Mar 2009, at 23:26, Andy Schwartz wrote:

> Gang -
>
> Need to bring this up one more time... Last week we found that our  
> choice of implementations for "wrapping" f:ajax/f:validateBean has  
> implications for delta state saving, so wanted to describe the  
> problem here and see whether we can agree to a solution.
>
> Some quick background on the delta state saving strategy - I'll  
> defer to Ed and Ryan on the API specifics and also on current status  
> with respect to 2.0 specification. The solution that Ryan has been  
> working on is very similar to the Trinidad approach that we've  
> discussed in the past. Roughly speaking, we're looking at:
>
> 1. Facelets tag handlers are applied and we build up the component  
> tree.
> 2. Once a component has been "populated" (attributes set, attached  
> objects attached), we lock the component state down.
> 3. From that point on through state saving, we keep track of  
> modifications (attributes modified, atached objects added/removed).
> 4. At state saving, if nothing has changed (the most common case by  
> far), we have no state to save - our saved state is null.
> 5. If the component has been modified, we save state. The amount of  
> state that we save for the modified component is implementation  
> specific. The goal is to only save the deltas, though there may be  
> cases where we may save the full state for a specific component  
> instance.
> 6. At restore time, we first build up the component tree by applying  
> the Facelets tag handlers.
> 7. Components which did not save any state are fully initialized -  
> don't need to restore any state.
> 8. Components which did save state restore it over the initialized  
> component instance.
>
> That's it in a nutshell. The end result is that the total size of  
> saved state per component/page is reduced significantly. One really  
> nice part of this solution is that this is all completely  
> transparent to the application developer - ie. the page author does  
> not need to make any changes to take advantage of this optimization.
>
> So, what does this have to do with f:ajax/f:validateBean? The issue  
> has to do with the timing of our current implementations.
>
> In the f:ajax implementation, we apply "inherited" AjaxBehavior  
> instances at tag handler execution time. So, by the time that we  
> reach #2 above, components that are wrapped inside of an f:ajax tag  
> have the appropriate AjaxBehavior instances attached.
>
> With our current f:validateBean implementation, we do not apply  
> "inherited" validators until the encode phase, which, of course, is  
> after we've locked down the component state (ie. after #2). As a  
> result, these validators are treated as component modifications/ 
> deltas - and as such impact the amount of state that we save.
>
> In order to avoid this penalty, I would like to propose that we  
> standardize on a tag handler-time solution for both f:ajax and  
> f:validateBean - ie. I would like to see f:validateBean migrated  
> over to a strategy that matches our current f:ajax behavior. My  
> guess is that the implementation changes should not be all that  
> challenging, though I have only taken a superficial look at the  
> f:validateBean wiring. The spec changes should be minimal.
>
> Are people okay with this proposal - ie. okay with standardizing on  
> the f:ajax wrapping behavior? Seems to me that this was the EG's  
> preference back when we discussed f:ajax wrapping behavior last  
> year, so hope that this is acceptable now.
>
> Dan -
>
> I think that you are most familiar with the current f:validateBean  
> implementation.  Assuming that you are okay with the proposal, would  
> you be willing to take a look at what we do for f:ajax and maybe  
> sync up with Ryan to discuss what it would take to convert this over  
> to the f:ajax strategy? The f:ajax approach is fairly simple:
>
> - When we encounter f:ajax, we create an AjaxBehavior and push it  
> onto a stack.
> - When we encounter a ClientBehaviorHolder component that can accept  
> the AjaxBehavior instance, we create/configure a new AjaxBehavior  
> instance and attach it to the ClientBehaviorHolder
> - When we reach the end of the f:ajax tag, we pop the AjaxBehavior  
> stack.
>
> Note that for creating/configuring the AjaxBehavior instances, we  
> use the technique that you hinted at in a previous email - ie. we  
> use the intial AjaxBehavior instance as a template and save/restore  
> its state to configure new instances.
>
> I am actually out of the office this week - just checking email  
> intermittently. I'll do my best to help/answer questions on this,  
> though there may be some gaps between my access to email.
>
> Andy
>
> -------- Original Message -------- Message-ID: 	<49B67A17.8070609 at oracle.com 
> >
> Date: 	Tue, 10 Mar 2009 10:32:55 -0400
> From: 	Andy Schwartz <andy.schwartz at oracle.com>
> User-Agent: 	Thunderbird 2.0.0.19 (Windows/20081209)
> MIME-Version: 	1.0
> To: 	JSR 314 Open Mailing list <JSR-314-OPEN at JCP.ORG>
> Subject: 	[NEW] <f:ajax> and <f:validateBean> - consistent wrapping  
> solution needed?
> Content-Type: 	text/plain; charset=ISO-8859-1; format=flowed
> Content-Transfer-Encoding: 	7bit
>
> Gang -
>
> In JSF 2.0 we are introducing two core tags that wrap/enhance  
> component
> subtrees: f:ajax and f:validateBean.
>
> f:ajax is used to enable Ajax behavior for a subtree, eg:
>
>> <h:panelGroup>
>>  <!-- Turn on Ajax for the two input texts -->
>>  <f:ajax event="valueChange">
>>      <h:inputText value="foo"/>
>>      <h:inputText value="bar"/>
>>  </f:ajax>
>> </h:panelGroup>
>
>
> f:validateBean is used to enable bean validation for a subtree, eg:
>
>> <h:panelGroup>
>>  <!-- Turn on bean validation for the two input texts -->
>>  <f:validateBean validationGroups="Group1, Group2"/>
>>      <h:inputText value="foo"/>
>>      <h:inputText value="bar"/>
>>  </f:validateBean>
>> </h:panelGroup>
>
> Of course, both tags can also be used in their nested form to enable
> Ajax/bean validation on a single component.
>
> We currently use different implementation strategies for the  
> "wrapping"
> behavior.
>
> f:ajax uses a handler execution-time solution.  AjaxHandler  
> maintains a
> stack that keeps track of the current nested state of <f:ajax> tags.
> Before apply child handlers, AjaxHandler pushes the current Ajax- 
> related
> info onto this stack.  When child/descendent handlers are applied,
> ComponentTagHandlerDelegateImpl checks this stack to get at the  
> current
> Ajax-related state and performs the necessary work to wire up an
> AjaxBehavior to the component.  Finally, after child handlers have  
> been
> processed, AjaxHandler pops the stack, and we're done.
>
> The end result of the f:ajax solution is that once handlers have
> finished executing, we have a fully configured component tree.  No
> further processing is necessary to apply "inherited" Ajax behavior.
>
> f:validateBean uses a solution which is split between tag/handler
> execution-time, validation-time and render-time.
> BeanValidatorHandler/ValidatorTagHandlerDelegateImpl set up well known
> properties on the parent component's attribute map (eg.
> BeanValidator.VALIDATION_GROUPS_KEY,
> UIInput.DEFAULT_VALIDATOR_IDS_KEY).  These are used during later
> lifecycle phases (eg. BeanValidator.validate(), UIInput.encodeEnd())  
> to
> determine which inherited validators to apply and how these validators
> should be configured (eg. what validation groups to use).
>
> The end result of the f:validateBean solution is that the handlers  
> only
> do part of the job - we need to do additional work during later
> lifecycle phases to take advantage of the information that has been
> stored away by the handlers.
>
> While these two different strategies may at first seem like
> implementation details, and thus not especially significant, the  
> choice
> of implementation does have impact on both our API and on spec'ed
> behavior (or, on behavior that should be defined by the spec).
>
> In terms of API, for f:validateBean the choice of implementation leaks
> through a bit into the API in the form of the property keys that are
> used to communicate between the handler implementations and the
> component/validator implementations.
>
> In terms of behavior, the different implementation strategies and up
> with subtly different results which may cause confusion.
>
> For example, in the following f:ajax case:
>
>> <h:panelGroup>
>>
>>  <!-- Turn Ajax on for this one -->
>>  <f:ajax event="valueChange">
>>      <h:inputText value="foo"/>
>>  </f:ajax>
>>
>>  <!-- But not for this one -->
>>  <h:inputText value="bar"/>
>>
>> </h:panelGroup>
>
>
> This should work as expected.  That is, Ajax should be enabled for the
> "foo" inputText, but not for the "bar" input text.
>
> In a similar f:validateBean case:
>
>> <h:panelGroup>
>>
>>  <!-- Turn bean validation on for this one -->
>>  <f:validateBean validationGroups="Group1, Group2"/>
>>      <h:inputText value="foor"/>
>>  </f:validateBean>
>>
>>  <!-- But not for this one -->
>>  <h:inputText value="bar"/>
>>
>> </h:panelGroup>
>
>
> Unless I am missing something in the spec/implementation, I believe  
> that
> the validation-related properties are going to end up being attached  
> to
> the parent panelGroup when the BeanValidatorHandler is applied.   
> Which,
> if I understand this correctly, means that the validation will be
> applied to both the "foo" and the "bar" inputText.  If this is the  
> case,
> this is definitely not the desired behavior.
>
> I suspect that similar problems would arise when we've got multiple
> <f:validateBean> under a single parent, eg:
>
>> <h:panelGroup>
>>
>>  <!-- Turn on Group1 validation for this one -->
>>  <f:validateBean validationGroups="Group1"/>
>>      <h:inputText value="foo"/>
>>  </f:validateBean>
>>
>>  <!-- Turn on Group2 validation for this one -->
>>  <f:validateBean validationGroups="Group2"/>
>>      <h:inputText value="bar"/>
>>  <f:validateBean/>
>>
>> </h:panelGroup>
>
>
> Though I haven't had a chance to test this out - just based on code
> inspection seems like this would be a problem.  (Though our <f:ajax>
> implementation strategy handles this case just fine.)
>
> Since there may be other subtle inconsistencies, it would make sense  
> to
> try to unify our implementation strategies across these two core tags.
> Of course, I am biased towards the <f:ajax> approach.  Seems to have
> better behavior in terms of targeting only the wrapped subtrees, has
> less exposure in the public API, and also just seems cleaner to me to
> produce a fully configured component tree as a result of handler  
> execution.
>
> Looking at the code, I didn't notice anything that would make it
> difficult to re-factor the <f:validateBean> code  to use a handler- 
> time
> strategy like <f:ajax>.  I think our users would benefit from the
> consistency.  Any thoughts on whether we should/can go this route?   
> Did
> I miss anything in the <f:validteBean> behavior that would prevent us
> from using a handler-time solution?
>
> Andy

--
Pete Muir
http://www.seamframework.org
http://in.relation.to/Bloggers/Pete




More information about the jsr-314-open-mirror mailing list