navigation rule causes JSF1064: Unable to find or serve resource

LeoCella picture LeoCella · Jan 22, 2015 · Viewed 7.5k times · Source

I've the following xhtml page, that is wrapped in the major part of the other pages in my project:

<ui:composition  xmlns="http://www.w3.org/1999/xhtml"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:h="http://xmlns.jcp.org/jsf/html"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:p="http://primefaces.org/ui">
<h:head>
    <title></title>
</h:head>
<h:form>  
    <p:menubar>
        <p:menuitem value="Home" url="/protected/personal/HomeCalendar.xhtml" icon="ui-icon-home"/>
        <p:menuitem value="#{topbarBean.username}" url="#" style="text-decoration: underline" />
        <f:facet name="options">
            <p:inputText style="margin-right:20px" placeholder="Search"  value="#{searchBean.searched}"/>
            <p:commandButton action="#{searchBean.search()}" type="submit" icon="ui-icon-search" />
        </f:facet>
       </p:menubar>
</h:form>
</ui:composition>

This is the navigation rule that I've wrote:

<navigation-rule>
    <from-view-id>/Components/TopBar.xhtml</from-view-id>
    <navigation-case>
        <from-action>#{searchBean.search()}</from-action>
        <from-outcome>searchingResults</from-outcome>   
        <to-view-id>/protected/SearchResults.xhtml</to-view-id>
    </navigation-case>
</navigation-rule>

and this the referred Bean:

@RequestScoped
@ManagedBean
public class SearchBean implements Serializable {

private String searched;
private final String resultsOutcome = "searchingResults";
private List<User> users;
private List<Event> events;

@EJB
UserFacade uf;

@EJB
UserManager um;

@EJB
EventFacade ev;

@PostConstruct
public void init(){
    try {
        setEvents(um.getEventsVisibilityMasked(um.getLoggedUser().getId()));
    }
    catch (NotFoundException ex) { 
        Logger.getLogger(SearchBean.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public void setSearched(String searched) {
    this.searched = searched;
}

public String getSearched() {
    return searched;
}


public void search() {
    FacesContext fc = FacesContext.getCurrentInstance();
    fc.getApplication().getNavigationHandler().handleNavigation(fc, null, resultsOutcome);
}

public List<User> getUsers(){
    return users;
}
public void setUsers(List<User> users){
    for(User user:users)
    this.users.add(user);
}

public List<Event> getEvents(){
    return events;
}
public void setEvents(List<Event> events){
    for(Event event:events)
    this.events.add(event);
}    
}

The error is the following one: JSF1064: Unable to find or serve resource, /protected/personal/searchingResults.xhtml.

This path is not specified anywhere, if it could be helpful I've the following structure :

-Index,xhtml
-Web Pages { components , protected}
-components{TopBar.xhtml}
-protected {event,persona,user,SearchResults.xhtml}
-event{eventCreate,eventPage,eventEdit}
-personal{HomeCalendar,ManageSettings,ManageInvitations}

I don't understand if the problem regards the navigation-rule or the next xhtml page.

Answer

BalusC picture BalusC · Jan 22, 2015

That can happen if JSF can't find the matching navigation rule. It'll then switch to implicit navigation. I.e. the outcome will be used as the actual view ID, relative to the current context.

Apparently the current view ID is sitting somewhere in /protected/personal. An outcome of searchingResults which doesn't match any navigation rule will then trigger an implicit navigation to /protected/personal/searchingResults.xhtml.

You've 2 options:

  1. Fix the current view ID. The <from-view-id>/Components/TopBar.xhtml</from-view-id> is apparently wrong. You can find out the right one as follows:

    System.out.println(FacesContext.getCurrentInstance().getViewRoot().getViewId());
    

    It's usually the one matching the context-relative URI in browser's address bar as long as you don't use POST for page-to-page navigation. Use this value in <from-view-id>.

  2. Get rid of navigation cases altogether and rely on implicit navigation. Remove the <navigation-case> altogether from faces-config.xml and change the outcome value and action method as below:

    private final String resultsOutcome = "/protected/SearchResults.xhtml";
    
    public String search() {
        return resultsOutcome;
    }
    

    The NavigationHandler approach was also quite clumsy. Even with navigation cases, just return the outcome outright instead of fiddling with NavigationHandler.

See also: