开发者

JSF 2 ViewScope questions

Quoting from this nice article,

The new view scope should solve exactly those i开发者_JAVA技巧ssues. A @ViewScoped bean will live as long as you're submitting the form to the same view again and again. In other words, as long as when the action method(s) returns null or even void, the bean will be there in the next request. Once you navigate to a different view, then the bean will be trashed.

And these questions come into mind:

  1. If my current view is index.xhtml, and if I specify explicitly return "index"; or <h:commandButton action="index.xhtml" ..>, which is basically returning to the same view, the bean will be recreated again .. why?
  2. Can a viewscoped bean survive a redirection?
  3. And if it can, how can I specify it? I can't imagine doing something like return "?faces-redirect=true" or <h:commandButton action="?faces-redirect=true" ..>, and yes, I would like to skip defining the navigation in faces-config.xml using the <redirect/>.


If my current view is index.xhtml, and if i specify explicitly return "index"; or , which is basically returning to the same view, the bean will be recreated again .. why ?

If you explicitly specify an outcome (read: a view), then a new view will be created. You have to return null or void from the action method (or just leave out the action attribute of the command component).

I must admit that I understand your confusion and that the term "view" can be interpreted differently, depending on the context. I think I'll revise the wording in the linked article sooner or later.

Can a Viewscoped bean survive a redirection ?

No. Only session scoped beans can and objects in the flash scope also (which ends immediately once the redirect has been finished, that's maybe which you actually need for the functional requirement you had in mind when asking this question).


The view state can survive redirection if the javax.faces.ViewState is supplied. The currently most simple solution I found, is implementing a navigation handler.

In faces-config.xml:

<faces-config>
    <application>
        ...
        <navigation-handler>com.intersult.jsf.util.RedirectNavigationHandler</navigation-handler>
    </application>
    ...
</faces-config>

The Java class:

public class RedirectNavigationHandler extends ConfigurableNavigationHandler {
    private NavigationHandler parent;

    public RedirectNavigationHandler(NavigationHandler parent) {
        this.parent = parent;
    }

    @Override
    public void handleNavigation(FacesContext context, String from, String outcome) {
        if (!context.getPartialViewContext().isPartialRequest()) {
            if (outcome == null)
                outcome = context.getViewRoot().getViewId();
            if (!outcome.endsWith("?faces-redirect=true"))
                outcome += "?faces-redirect=true";
            String viewState =
                context.getExternalContext().getRequestParameterMap().get(ResponseStateManager.VIEW_STATE_PARAM);
            outcome += "&javax.faces.ViewState=" + viewState;
        }
        parent.handleNavigation(context, from, outcome);
    }
}

This has some impact: Each redirect is not an independent request anymore. It depends on the view state, which can not neccesarily be restored. So have a fallback strategy, if it is expired eg. redirect on view expired exception.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜