jsf: redirecting from bean on primefaces ajax even

2019-09-17 14:31发布

问题:

I have this selectable PrimeFaces Tree with an Ajax listener on selection in my index.xhtml:

<p:tree value="#{seccionesArbolView.root}" var="node" selectionMode="single" >
    <p:treeNode>
        <h:outputText value="#{node.nombre}" />
    </p:treeNode>
    <p:ajax event="select" listener="#{seccionesArbolView.onNodeSelect}"></p:ajax>
</p:tree>                    

The listener method is on a session scoped named bean, and should redirect to another page (grupal.xhtml) with some GET parameters. I tried this:

public String onNodeSelect(NodeSelectEvent event) throws IOException {
    Seccion sec = (Seccion) event.getTreeNode().getData();
    String enlace = "grupal.xhtml?faces-redirect=true&id=" + sec.getId() + "&nombre=" + sec.getNombre();
    return enlace;
}

but nothing happens. I read in another question that it might be because of the Ajax petition, so I tried with ExternalContext:

public String onNodeSelect(NodeSelectEvent event) throws IOException {
    Seccion sec = (Seccion) event.getTreeNode().getData();
    FacesContext context = FacesContext.getCurrentInstance();
    String enlace = "faces/grupal.xhtml?id=" + sec.getId() + "&nombre=" + sec.getNombre();
    context.getExternalContext().redirect(enlace);
    context.responseComplete();
}

The problem with this approach is the construction of the link. The way it is done (with the "faces" prefix) works, but everytime the tree is clicked the URL keeps getting bigger, with the addition of another "faces/" (e.g. http://localhost:8080/MyApp/faces/faces/faces/grupal.xhtml?...) and Glassfish issues the warning Request path '/faces/faces/grupal.xhtml' begins with one or more occurrences of the FacesServlet prefix path mapping '/faces'

If the link is constructed without the "faces/" prefix:

String enlace = "grupal.xhtml?id=" + sec.getId() + "&nombre=" + sec.getNombre();

it works, provided that index.html is accessed through the URL http://localhost:8080/MyApp/faces/index.xhtml. But when index.html is accessed through the base URL http://localhost:8080/MyApp/, grupal.xhtml cannot be found, obviously.

I am not sure what is the best solution in this case.

Is there a way to do this with JSF 2.0 navigation (the first approach, that I cannot get to work)?

Is there a way to get the whole base URL to make the redirection with an absolute path?

Is there a way to tell Glassfish to redirect the base URL http://localhost:8080/MyApp/ to http://localhost:8080/MyApp/faces/index.xhtml ?

回答1:

Is there a way to do this with JSF 2.0 navigation (the first approach, that I cannot get to work)?

You can programmatically perform navigation using NavigationHandler#handleNavigation().

public void onNodeSelect(NodeSelectEvent event) {
    // ...
    String outcome = "grupal.xhtml?faces-redirect=true&id=" + sec.getId() + "&nombre=" + sec.getNombre();
    FacesContext context = FacesContext.getCurrentInstance();
    context.getApplication().getNavigationHandler().handleNavigation(context, null, outcome);
}

Is there a way to get the whole base URL to make the redirection with an absolute path?

You can programmatically obtain context path using ExternalContext#getRequestContextPath().

public void onNodeSelect(NodeSelectEvent event) throws IOException {
    // ...
    String uri = "/faces/grupal.xhtml?id=" + sec.getId() + "&nombre=" + sec.getNombre();
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + uri);
}

Is there a way to tell Glassfish to redirect the base URL http://localhost:8080/MyApp/ to http://localhost:8080/MyApp/faces/index.xhtml ?

Use a <welcome-file> in web.xml on index.xhtml and replace the awkward JSF 1.0 style FacesServlet mapping of /faces/* by JSF 2.0 style *.xhtml. See also JSF welcome file is not recognized and JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?