You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by "Simon Kitching (JIRA)" <de...@myfaces.apache.org> on 2009/02/22 22:31:04 UTC

[jira] Commented: (ORCHESTRA-30) ViewController does not invoke initView on new instance of same view

    [ https://issues.apache.org/jira/browse/ORCHESTRA-30?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12675711#action_12675711 ] 

Simon Kitching commented on ORCHESTRA-30:
-----------------------------------------

Hmm. We can find which viewcontroller we are about to init by simply calling
          Object viewController = manager.getViewController(viewId);
and then do the init only if we have not invoked that particular instance before.

Unfortunately, that doesn't work; the returned "view controller" bean remains unchanged even when the conversation in which it lives is invalidated. Why? Because it is not actually the controller bean, but instead a spring proxy to it which is cached in request scope for performance. This caching is perfectly valid (even across invalidations) because the proxy looks up its bean dynamically. But it means that this reference is no good for determining if we are invoking the same controller bean or not.

We could:
(a) somehow check if the ref is a proxy, and if so fetch the "real" reference (ecch)
(b) ensure that these proxies are removed from the request-scope when their conversation is invalidated (ecch)
(c) find some other way of deciding when to call initView again.

Option (a) really couples the ViewController and the bean-lookup processes more than is desirable. It shouldn't be any business of anything else how the DI adapter decides to proxy managed beans.

Option (b) means that the Conversation class needs to be aware that the DI adapter might cache proxies in request scope. That also seems undesirable.

But option (c) is also tricky.
(1) We can't invoke init whenever the viewroot *instance* changes, because code that simply returns "" from a navigation method will trigger that, even when the controller bean has not been invalidated. That is a major behaviour change from earlier Orchestra releases.
(2) We can't set a global flag when any conversation is invalidated and use that, because the conversation that was invalidated might not be the one in which the controller lives.

Maybe we can determine the name of the conversation in which the controller bean lives, then see if that has been recreated?



> ViewController does not invoke initView on new instance of same view
> --------------------------------------------------------------------
>
>                 Key: ORCHESTRA-30
>                 URL: https://issues.apache.org/jira/browse/ORCHESTRA-30
>             Project: MyFaces Orchestra
>          Issue Type: Bug
>    Affects Versions: 1.2
>            Reporter: Simon Kitching
>
> The "lifecycle" methods for backing beans are executed via the ViewControllerPhaseListener. In particular, for the initView call it checks at the beginning of every phase whether the current view has had the initView run on it for the current request-cycle, and if not then runs it.
> It therefore needs to remember whether initView has been executed for a view in this request. This is done by keeping a map keyed by viewId.
> However it is reasonable for an action method to "reset" a view by calling
>   Conversation.getCurrent().invalidate()
>   return "";
> In this case, the new view is rendered and a new backing bean is created, but the viewId is the same so the ViewController does not call the initView lifecycle method.
> One possible workaround is to define a navigation-case using <redirect/>, which means the new view is rendered in a new request-cycle and therefore the ViewController is run.
> The code could be changed to use System.identityHashCode(viewRoot) rather than viewRoot.getViewId() as the map key; that would ensure we run the lifecycle methods when the viewRoot *object* changes even if it has the same viewId.
> But perhaps what we really want is to run the lifecycle method if the backing bean is new, regardless of whether the view-tree is new or not? Looks like we need to more clearly define exactly what "initView" means....

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.