[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