f:viewAction ignored, when commandButton navigates

2019-02-24 07:11发布

问题:

I have a problem with the JSF 2.2 Feature <f:viewAction action="#{...}/>. I placed this tag in my XHTML-Page, it's called viewActionStart.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
    <f:view>
        <f:metadata>
            <f:viewAction action="#{redirect.getView()}" onPostback="true"
                immediate="true" />
        </f:metadata>
    </f:view>
    <h:outputText value="If you see that text, the viewAction was not performed." />
</h:body>
</html>

If I visit this XHTML-Page directly, everything works fine: The method redirect.getView() is called and a redirect to another page is performed.

Now I have my landing page, that is shown before that viewActionStart-Page. There is a button, that basically should navigate to my viewActionStart-Page to show the <f:viewAction> effect. The following code is from this landing page index.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
    <f:view>
        <h:form>
            <h:commandButton action="viewActionStart.xhtml"
                value="To f:viewAction Page" />
        </h:form>
    </f:view>
</h:body>
</html>

If I hit that command button, the content of the viewActionStart.xhtml is shown. Why does JSF ignore the <f:viewAction>? I do not understand why the viewAction does not work on every page load. I tried around with those onPostback and "immediate" attributes, but nothing changes.

Another weird result is, that after I hit the command button and see the content of viewActionStart.xhtml the URL still remains on localhost:8080/UIIncludeTest/index.xhtml. But shouldn't look this URL like localhost:8080/UIIncludeTest/viewActionStart.xhtml after the command button does navigation?

Am I doing something wrong? Or do I simply misunderstood <f:viewAction>? The weird thing, is, that it works if I browse directly to viewActionStart.xhtml.

I'm trying to get this working on:

  • JSF-2.2.6
  • Tomcat-7.0.47
  • PrimeFaces 5.0

I have read the numerous posts related to <f:viewAction> but nothing helped.

回答1:

The <f:viewAction onPostback="true"> applies only on postbacks on the very same view. I.e. it runs only when a <h:form> in the very same view has been submitted. The <f:viewAction> is never intented to be executed upon POST navigation triggered by a submit of a <h:form> of another view. Moreover, the term "postback" in the attribute name also confirms this. This term means in web development world "a POST request on the URL of the page itself".

You need to open it by a GET request instead of a POST request. Replace the <h:commandButton> by <h:button>:

<h:button outcome="viewActionStart.xhtml" value="To f:viewAction Page" />

(note: the <h:form> is not necessary anymore)

Or, if you really intend to perform a POST request first for some unclear reason (it would have been a bit more understandable if you were invoking a bean action method, but you're here merely navigating, so the whole POST request doesn't make any sense), then let it send a redirect:

<h:commandButton action="viewActionStart.xhtml?faces-redirect-true" value="To f:viewAction Page" />

Either way, the URL should now be properly reflected in address bar. This was at its own indeed a strong hint that you was donig things the wrong way ;)

See also:

  • How to navigate in JSF? How to make URL reflect current page (and not previous one)
  • Difference between h:button and h:commandButton