In my JSF 2.0 Facelets application I have one glorious template that I want all the pages to use. It is in the root directory of the web-app disguised with the name template.xhtml. So it is referenced as you would expect:
<ui:composition template="./template.xhtml">
However I do navigate now and then to client files in sub-directories. It is useful to organize them this way because of different privilege levels. The facelets in those subdirectories would have a reference to the same template like this:
<ui:composition template="../template.xhtml">
So far so good. However in the header of the template I pull in the css like this:
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/tableLayout.css" rel="stylesheet" type="text/css" />
<link href="../resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="../resources/css/tableLayout.css" rel="stylesheet" type="text/css" />
The reason for the redundant references is that I haven't found any other way to get the template to work from the context of the root directory or the sub-directory. A pathname that starts with a / doesn't work unless you put the application name in it like this
/TheApp-Ver1_0/resources/css/default.css
The problem with this is that the absolute pathname starts with a variable, not a constant. The variable is dependent on how the app is deployed in the container. Is there any clean way of resolving this?
I did some searches to find this question. Honest. However I suspect this is another one of those where BalusC swoops in an provides a link to the blindingly obvious solution extensively discussed somewhere I missed.
An absolute path always contains the root element and the complete directory list required to locate the file. For example, /home/sally/statusReport is an absolute path. All of the information needed to locate the file is contained in the path string.
If all three components are present, the path is absolute. If no volume or drive letter is specified and the directory name begins with the directory separator character, the path is relative from the root of the current drive. Otherwise, the path is relative to the current directory.
The template
path in <ui:composition>
is relative to the webapp's own folder structure, not to the domain root (because it does not represent an URL!). So if you start it with /
, it's just resolved relative to the context root.
<ui:composition template="/WEB-INF/inc/template.xhtml">
(putting in /WEB-INF
has the advantage that the enduser cannot open it directly by guessing the URL)
The name
path of <h:outputStylesheet>
, <h:outputScript>
and <h:graphicImage>
is always relative to /resources
root folder, regardless of if you start it with /
or not.
<h:outputStylesheet name="css/default.css" />
<h:outputScript name="js/default.js" />
<h:graphicImage name="img/logo.png" />
If you want to use plain HTML instead of JSF components to include CSS/JS/images for some reason, then best is to prepend the path with #{request.contextPath}
yourself, so that you can make it a domain-relative URL, so that you don't need to fiddle with context-relative URLs. See also: How get the base URL?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With