Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What URL to use to link / navigate to other JSF pages

I am confused about how to link between files in a Java Server Faces project, when some of the files are in sub-folders. (I was going to attach screenshots so you can see the Nebeans project view, and files view of the example I am trying.... but I'm not allowed to add images yet).

I my example project I have files called "index.xhtml" and "calculate/calculate.xhtml". I also have a file called "template.xhtml" which is used by both. The question is what url format to use in the template that will work for both files.

In straight html I would just use something like the following to provide a link back to the home page that would work from any location:

<a href="/index.html">Home</a>

But I can't figure out what counts as the root folder for a JSF application, and whether to use the "project view" folder structure or the "files list" folder structure.

like image 223
Ant Waters Avatar asked Jun 06 '15 13:06

Ant Waters


1 Answers

First of all, JSF is a HTML code generator. So it's not different in JSF than in "plain" HTML. You should just not look at file system structure in webapp project when creating links in HTML. You should look at public URL structure of those resources. It's namely the webbrowser who has got to invoke and download those resources, not the webserver. The webbrowser knows absolutely nothing about the file system structure in the webserver. This is not specific to JSF projects. This applies to all web projects.

Relative URLs are not relative to their location in the file system structure in webapp project. They are relative to the request URL of the currently opened HTML document, exactly the one you see in browser's address bar. Noted should be that when a <base> element is present in the HTML document, then all relative URLs in the HTML document not starting with / will become relative to it.

Given a webapp which is configured with FacesServlet mapping URL pattern of *.xhtml, and is deployed to localhost:8080 with a context path of /context, the URL of a /index.xhtml file in project's web root will be as below:

http://localhost:8080/context/index.xhtml
----   -------------- ------- -----------
  |           |          |         `-- resource
  |           |          `-- path (can be multiple folders)
  |           `-- domain (and port)
  `-- scheme

When you're currently in http://localhost:8080/context/index.xhtml, and you want to create a link to http://localhost:8080/context/calculate/calculate.xhtml, then all the ways below will ultimately point to exactly the same absolute URL.

  • A relative URL starting with // is relative to the current scheme.

    <a href="//localhost:8080/context/calculate/calculate.xhtml">link</a>
    
  • A relative URL starting with / is relative to the domain.

    <a href="/context/calculate/calculate.xhtml">link</a>
    
  • A relative URL not starting with / is relative to the path.

    <a href="calculate/calculate.xhtml">link</a>
    

And when you're currently in http://localhost:8080/context/calculate/calculate.xhtml, and you want to link to http://localhost:8080/context/index.xhtml, then the same rules apply:

  • A relative URL starting with // is relative to the current scheme.

    <a href="//localhost:8080/context/index.xhtml">link</a>
    
  • A relative URL starting with / is relative to the domain.

    <a href="/context/index.xhtml">link</a>
    
  • A relative URL not starting with / is relative to the path.

    <a href="../index.xhtml">link</a>
    

As you probably realize by now, a relative URL starting with / is not dependent from the current path and domain. So, that's the URL you really want to use everywhere in your web application without worrying about maintenance trouble when changing domain or moving around files in the server. The only thing left is the dynamicness of the context path. You probably already know that this value is not controllable from inside the webapp. You'd really like to avoid hardcoding it. You can however easily let JSF print it programmatically with a little help of EL. It's namely just available by HttpServletRequest#getContextPath() and the HttpServletRequest is in EL available as implicit object #{request}.

<a href="#{request.contextPath}/index.xhtml">link</a>
<a href="#{request.contextPath}/calculate/calculate.xhtml">link</a>

It only gets tedious to repeat this everytime. Fortunately, JSF offers the <h:link> component for the very purpose of generating a HTML <a> element with the current context path automatically inlined.

<h:link value="link" outcome="index.xhtml" />
<h:link value="link" outcome="calculate/calculate.xhtml" />

Note that the outcome must represent a JSF view ID, which is not necessarily the same as the URL path (it will be when you map FacesServlet on *.xhtml). You can even omit the file extension here, JSF will automatically detect it as part of "implicit navigation" mechanism.

<h:link value="link" outcome="index" />
<h:link value="link" outcome="calculate/calculate" />

See also:

  • Is it recommended to use the <base> html tag?
  • What are those URL's that are starting with // - that you can see within Google+ html source?
  • JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?
  • Implicit objects in EL
  • How to navigate in JSF? How to make URL reflect current page (and not previous one)
like image 173
BalusC Avatar answered Sep 22 '22 19:09

BalusC