Hi Gavin, I'll skip over/ignore some aspects (like capturing user typed form updates & actions), and concentrate on the core issue. I'll also try to keep it simple, for the benefit of anybody else reading. Whilst I'm talking here about Seam of course, I'd like to be clear to people that it's not a problem with Seam - rather something Seam can feel the impact of & also help overcome.
For a component like this in a view: <h:commandButton disabled="#{!projectFinder.listOK}" /> JSF uses the #{!projectFinder.listOK} binding twice. Once during the RENDER_RESPONSE phase for determining component render style, then again when JSF rebuilds the component tree. This enables JSF to restore the view then generate a detected event, as if the UI was sitting in memory the whole time. It happens during APPLY_REQUEST_VALUES, where a call is made to UIViewRoot.processDecodes. Here's the JSF1.2-b16 implementation call stack from the second use of the value binding. I believe from looking at the MyFaces source, that the same would happen there: $Proxy97.isListOK() line: not available NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object...) line: 585 BeanELResolver.getValue(ELContext, Object, Object) line: 218 FacesCompositeELResolver(CompositeELResolver).getValue(ELContext, Object, Object) line: 135 FacesCompositeELResolver.getValue(ELContext, Object, Object) line: 58 AstValue.getValue(EvaluationContext) line: 96 AstDeferredExpression.getValue(EvaluationContext) line: 25 AstCompositeExpression.getValue(EvaluationContext) line: 30 ValueExpressionImpl.getValue(ELContext) line: 183 TagValueExpression.getValue(ELContext) line: 71 HtmlCommandButton.isDisabled() line: 169 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object...) line: 585 UIComponentBase$AttributesMap.get(Object) line: 1525 Util.componentIsDisabledOrReadonly(UIComponent) line: 572 ButtonRenderer.decode(FacesContext, UIComponent) line: 108 HtmlCommandButton(UIComponentBase).decode(FacesContext) line: 791 HtmlCommandButton(UIComponentBase).processDecodes(FacesContext) line: 1012 HtmlForm(UIForm).processDecodes(FacesContext) line: 203 UIViewRoot(UIComponentBase).processDecodes(FacesContext) line: 1007 UIViewRoot.processDecodes(FacesContext) line: 499 ApplyRequestValuesPhase.execute(FacesContext) line: 101 The end result for a JSF app is that the #{!projectFinder.listOK} binding referenced on "viewX" must be available during the handling of any action event generated from "viewX". Because "projectFinder" was destroyed at the end of the last web request, a new instance of "projectFinder" will be created during the evaluation of the #{!projectFinder.listOK} binding. This new instance will be a default initialized bean (or component in the case of Seam), which leads to an invalid restoration of view state. In the example of projectFinder in this thread, which is from the issue example (plus isListOK method), the projectList will be set to null - and then be outjected over the top of the projectList value we want to keep. What many JSF developers seem to be after (a hunch), is a way to keep their backing beans around to service the binding evaluations during view reconstruction. It seems a lot are resorting to session scope (but will then have trouble if they need multiple instances of course). Seam might be able to get round this with style. The quick-fix solution, as I posted here, is to outject a listOK Boolean to page scope, and change view references to #{listOK}. Because it's page bound, the view reconstruction will be able to get it's value despite the component that created it being destroyed. Also, avoid heavy business logic in bound method - do that in the action & set up info that getters can access simply from other lifecycle phases. It would be great though if Seam components themselves could be destroyed later, so that the component tree can be rebuilt from the correct instance. There would be a cost to holding/tracking the instance, but savings also. For example, projectList might be built again from db after it gets nulled out, even though we end up with an invalid state for the new projectFinder instance. The "component lifetime & usage lifetime" mismatch is not just for EVENT scope, but for other scopes too. Page fortunately offers a way around it. I'm new to a lot of the tech in this stack, and it would be good to be told I'm wrong about this stuff, but I don't think so. Thoughts? View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3933976#3933976 Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3933976 ------------------------------------------------------- This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 _______________________________________________ JBoss-user mailing list JBoss-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jboss-user