Hit a bean method and redirect on a GET request

16,137

Use <f:viewAction> to trigger a bean method before rendering of the view and simply return a navigation outcome (which will implicitly be treated as a redirect).

E.g.

<f:metadata>
    <f:viewParam name="token" value="#{authenticator.token}" />
    <f:viewAction action="#{authenticator.check}" />
</f:metadata>

with

@ManagedBean
@RequestScoped
public class Authenticator {

    private String token;

    public String check() {
        return isValid(token) ? null : "main.jsf";
    }

    // Getter/setter.
}

If you're not on JSF 2.2 yet, then you can use the <f:event type="preRenderView"> workaround in combination with ExternalContext#redirect().

<f:metadata>
    <f:viewParam name="token" value="#{authenticator.token}" />
    <f:event type="preRenderView" listener="#{authenticator.check}" />
</f:metadata>

with

@ManagedBean
@RequestScoped
public class Authenticator {

    private String token;

    public void check() throws IOException {
        if (!isValid(token)) {
            FacesContext.getCurrentInstance().getExternalContext().redirect("main.jsf");
        }
    }

    // Getter/setter.
}

See also:

Share:
16,137
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm using JSF 2 and PrimeFaces 2.1 on GlassFish.

    I have a page that is intended to allow people to perform an action after following a callback URL (e.g. as link embedded in email or as callback URL parameter of some external authentication or payment service). In my case I need to reset the password. The callback URL has a token GET parameter like so:

    http://example.com/app/resetPasswordForm.jsf?token=abc123

    On page load of resetPasswordForm.jsf, I need to check if the token is valid and redirect to the main app screen if it's not valid.

    My thinking is to have a bean method like:

    public String resetPasswordHandler.showResetForm(String token) {
      if /* token is valid */ {
        return "resetPasswordForm.jsf";
      } else {
        return "main.jsf";
      }
    }
    

    But how would I cause that method to get hit on page load?

    Not sure how to proceed -- suggestions are welcome.

  • Admin
    Admin over 12 years
    Looks great and works! One more question, when I add a FacesMessage to the FacesContext because the externalContext.redirect, the faces message does not appear on "main.jsf". Is that normal, and is there a way to make that work?
  • BalusC
    BalusC over 12 years
    Yes, that's normal. Faces messages are request scoped. A redirect instructs the browser to fire a brand new HTTP request. You need to either pass a request parameter in redirect URL and let displaying of the message intercept on that, or to call Flash#setKeepMessages() with true in order to revive them through a cookie (which in turn has currently however a curious bug in Mojarra in certain circumstances, so be aware of that, see also java.net/jira/browse/JAVASERVERFACES-1751 ).
  • Salih Erikci
    Salih Erikci over 9 years
    Can you please explain how to do it with a Validator on <f:viewParam>
  • Farhan Shirgill Ansari
    Farhan Shirgill Ansari about 8 years
    @BalusC: The action method for view-action component gets fired during application logic invoke phase right before the action method which is binded to some command-button. Whereas, for pre-render view, its get fired during Render response phase. I am a little confused as to whether it will be okay to perform redirection with pre-render view. Wouldn't it be late enough then.
  • BalusC
    BalusC about 8 years
    @Shirgill: redirect is still possible as long as response isn't committed (i.e. as long as JSF hasn't rendered the response).