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.
The
templatepath 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.(putting in
/WEB-INFhas the advantage that the enduser cannot open it directly by guessing the URL)The
namepath of<h:outputStylesheet>,<h:outputScript>and<h:graphicImage>is always relative to/resourcesroot folder, regardless of if you start it with/or not.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?