Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Actually, all of those examples on the web wherein the common content/file type like "js", "css", "img", etc is been used as library name are <strong>misleading</strong>.</p> <h3>Real world examples</h3> <p>To start, let's look at how existing JSF implementations like <a href="http://javaserverfaces.java.net" rel="noreferrer">Mojarra</a> and <a href="http://myfaces.apache.org" rel="noreferrer">MyFaces</a> and JSF component libraries like <a href="http://primefaces.org" rel="noreferrer">PrimeFaces</a> and <a href="http://omnifaces.org" rel="noreferrer">OmniFaces</a> use it. No one of them use resource libraries this way. They use it (under the covers, by <a href="http://docs.oracle.com/javaee/7/api/javax/faces/application/ResourceDependency.html" rel="noreferrer"><code>@ResourceDependency</code></a> or <a href="https://docs.oracle.com/javaee/7/api/javax/faces/component/UIViewRoot.html#addComponentResource(javax.faces.context.FacesContext,%20javax.faces.component.UIComponent)" rel="noreferrer"><code>UIViewRoot#addComponentResource()</code></a>) the following way:</p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputScript library="javax.faces" name="jsf.js" /&gt; &lt;h:outputScript library="primefaces" name="jquery/jquery.js" /&gt; &lt;h:outputScript library="omnifaces" name="omnifaces.js" /&gt; &lt;h:outputScript library="omnifaces" name="fixviewstate.js" /&gt; &lt;h:outputScript library="omnifaces.combined" name="[dynamicname].js" /&gt; &lt;h:outputStylesheet library="primefaces" name="primefaces.css" /&gt; &lt;h:outputStylesheet library="primefaces-aristo" name="theme.css" /&gt; &lt;h:outputStylesheet library="primefaces-vader" name="theme.css" /&gt; </code></pre> <p>It should become clear that it basically represents the <strong>common library/module/theme name</strong> where all of those resources commonly belong to.</p> <h3>Easier identifying</h3> <p>This way it's so much easier to specify and distinguish where those resources belong to and/or are coming from. Imagine that you happen to have a <code>primefaces.css</code> resource in your own webapp wherein you're overriding/finetuning some default CSS of PrimeFaces; if PrimeFaces didn't use a library name for its own <code>primefaces.css</code>, then the PrimeFaces own one wouldn't be loaded, but instead the webapp-supplied one, which would break the look'n'feel.</p> <p>Also, when you're using a custom <a href="http://docs.oracle.com/javaee/7/api/javax/faces/application/ResourceHandler.html" rel="noreferrer"><code>ResourceHandler</code></a>, you can also apply more finer grained control over resources coming from a specific library when <code>library</code> is used the right way. If all component libraries would have used "js" for all their JS files, how would the <code>ResourceHandler</code> ever distinguish if it's coming from a specific component library? Examples are OmniFaces <a href="https://github.com/omnifaces/omnifaces/blob/2.0/src/main/java/org/omnifaces/resourcehandler/CombinedResourceHandler.java#L280" rel="noreferrer"><code>CombinedResourceHandler</code></a> and <a href="https://github.com/omnifaces/omnifaces/blob/2.0/src/main/java/org/omnifaces/resourcehandler/GraphicResourceHandler.java#L48" rel="noreferrer"><code>GraphicResourceHandler</code></a>; check the <code>createResource()</code> method wherein the library is checked before delegating to next resource handler in chain. This way they know when to create <code>CombinedResource</code> or <code>GraphicResource</code> for the purpose.</p> <p>Noted should be that RichFaces did it wrong. It didn't use any <code>library</code> at all and homebrewed another resource handling layer over it and it's therefore impossible to programmatically identify RichFaces resources. That's exactly the reason why <a href="http://omnifaces.org" rel="noreferrer">OmniFaces</a> <a href="http://showcase.omnifaces.org/resourcehandlers/CombinedResourceHandler" rel="noreferrer"><code>CombinedResourceHander</code></a> had to introduce <a href="https://github.com/omnifaces/omnifaces/blob/2.0/src/main/java/org/omnifaces/util/Hacks.java#L228" rel="noreferrer">a reflection-based hack</a> in order to get it to work anyway with RichFaces resources.</p> <h3>Your own webapp</h3> <p>Your own webapp does not necessarily need a resource library. You'd best just omit it. </p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputStylesheet name="css/style.css" /&gt; &lt;h:outputScript name="js/script.js" /&gt; &lt;h:graphicImage name="img/logo.png" /&gt; </code></pre> <p>Or, if you really need to have one, you can just give it a more sensible common name, like "default" or some company name.</p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputStylesheet library="default" name="css/style.css" /&gt; &lt;h:outputScript library="default" name="js/script.js" /&gt; &lt;h:graphicImage library="default" name="img/logo.png" /&gt; </code></pre> <p>Or, when the resources are specific to some master Facelets template, you could also give it the name of the template, so that it's easier to relate each other. In other words, it's more for self-documentary purposes. E.g. in a <code>/WEB-INF/templates/layout.xhtml</code> template file:</p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputStylesheet library="layout" name="css/style.css" /&gt; &lt;h:outputScript library="layout" name="js/script.js" /&gt; </code></pre> <p>And a <code>/WEB-INF/templates/admin.xhtml</code> template file:</p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputStylesheet library="admin" name="css/style.css" /&gt; &lt;h:outputScript library="admin" name="js/script.js" /&gt; </code></pre> <p>For a real world example, check the <a href="https://github.com/omnifaces/showcase" rel="noreferrer">OmniFaces showcase source code</a>.</p> <p>Or, when you'd like to share the same resources over multiple webapps and have created a "common" project for that based on the same example as in <a href="https://stackoverflow.com/questions/8320486/structure-for-multiple-jsf-projects-with-shared-code/8320738#8320738">this answer</a> which is in turn embedded as JAR in webapp's <code>/WEB-INF/lib</code>, then also reference it as library (name is free to your choice; component libraries like OmniFaces and PrimeFaces also work that way):</p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputStylesheet library="common" name="css/style.css" /&gt; &lt;h:outputScript library="common" name="js/script.js" /&gt; &lt;h:graphicImage library="common" name="img/logo.png" /&gt; </code></pre> <h3>Library versioning</h3> <p>Another main advantage is that you can apply resource library versioning the right way on resources provided by your own webapp (this doesn't work for resources embedded in a JAR). You can create a direct child subfolder in the library folder with a name in the <code>\d+(_\d+)*</code> pattern to denote the resource library version.</p> <pre class="lang-none prettyprint-override"><code>WebContent |-- resources | `-- default | `-- 1_0 | |-- css | | `-- style.css | |-- img | | `-- logo.png | `-- js | `-- script.js : </code></pre> <p>When using this markup:</p> <pre class="lang-html prettyprint-override"><code>&lt;h:outputStylesheet library="default" name="css/style.css" /&gt; &lt;h:outputScript library="default" name="js/script.js" /&gt; &lt;h:graphicImage library="default" name="img/logo.png" /&gt; </code></pre> <p>This will generate the following HTML with the library version as <code>v</code> parameter:</p> <pre class="lang-html prettyprint-override"><code>&lt;link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml?ln=default&amp;amp;v=1_0" /&gt; &lt;script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&amp;amp;v=1_0"&gt;&lt;/script&gt; &lt;img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&amp;amp;v=1_0" alt="" /&gt; </code></pre> <p>So, if you have edited/updated some resource, then all you need to do is to copy or rename the version folder into a new value. If you have multiple version folders, then the JSF <code>ResourceHandler</code> will automatically serve the resource from the highest version number, according to numerical ordering rules. </p> <p>So, when copying/renaming <code>resources/default/1_0/*</code> folder into <code>resources/default/1_1/*</code> like follows:</p> <pre class="lang-none prettyprint-override"><code>WebContent |-- resources | `-- default | |-- 1_0 | | : | | | `-- 1_1 | |-- css | | `-- style.css | |-- img | | `-- logo.png | `-- js | `-- script.js : </code></pre> <p>Then the last markup example would generate the following HTML:</p> <pre class="lang-html prettyprint-override"><code>&lt;link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml?ln=default&amp;amp;v=1_1" /&gt; &lt;script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&amp;amp;v=1_1"&gt;&lt;/script&gt; &lt;img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&amp;amp;v=1_1" alt="" /&gt; </code></pre> <p>This will force the webbrowser to request the resource straight from the server instead of showing the one with the same name from the cache, when the URL with the changed parameter is been requested for the first time. This way the endusers aren't required to do a hard refresh (Ctrl+F5 and so on) when they need to retrieve the updated CSS/JS resource.</p> <p>Please note that library versioning is not possible for resources enclosed in a JAR file. You'd need a custom <code>ResourceHandler</code>. See also <a href="https://stackoverflow.com/questions/18143383/how-to-use-jsf-versioning-for-resources-in-jar">How to use JSF versioning for resources in jar</a>.</p> <h3>See also:</h3> <ul> <li><a href="https://stackoverflow.com/questions/9929417/jsf-resource-versioning">JSF resource versioning</a></li> <li><a href="https://stackoverflow.com/questions/10362942/jsf2-static-resource-caching">JSF2 Static resource caching</a></li> <li><a href="https://stackoverflow.com/questions/8320486/structure-for-multiple-jsf-projects-with-shared-code">Structure for multiple JSF projects with shared code</a></li> <li><a href="http://jcp.org/aboutJava/communityprocess/final/jsr314/index.html" rel="noreferrer">JSF 2.0 specification</a> - Chapter 2.6 Resource Handling</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload