Thursday, 11 February 2010

Using RichFaces to give versioned URL's

RichFaces has some nice components that can load scripts and styles when placed anywhere in the xhtml page and automatically inserts them into the header at render time. For example a footer could say it requires stylesheet, after you've already defined a header.

The tags are pretty simple there is the style loader, loadStyle:
<afj:loadstyle src="/css/test.css"></afj:loadstyle>
And the script loader, loadScript:
<afj:loadscript src="/javascript/test.js">

The src can be a path be:
  1. Relative to the current page.
  2. Path relative to the context if starting with a slash.
  3. Or loaded by RichFaces resource framework
    Using "resource:///path/to/file"
Now, the problem most web developers always face is that of caching. If you disable caching then the site is slow for the user and your bandwidth is used up. If you enable caching and release a new version, how do you clear the user's and ISP's cache so they can see your changes?

RichFaces already deals with this by creating virtual URL's for all their resources served (the static javascript files and the generated css files and images). It prepends "afj/g/[version]" to the url's. For example:
<script src="/myapp/jsf/a4j/g/3_3_2.SR1jquery.js" type="text/javascript">
Where myapp is the name of the context and I have a mapping to the faces servlet for /jsf/*. This gets prepended to all resources served through the framework, even ones from your war.

This neat little feature can be used to version your own deployments, so that after each build a new URL is generated.

If your using maven its simple.
First add this to your web.xml:
<!-- 
  not used, but needs to be set
-->
<context-param>
  <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>
  <param-value>a4j/${project.version}-r${buildNumber}</param-value>
</context-param>
<!-- 
  the prefix used by richfaces for global cached resources
-->
<context-param>
  <param-name>org.ajax4jsf.GLOBAL_RESOURCE_URI_PREFIX</param-name>
  <param-value>a4j/g/${project.version}-r${buildNumber}</param-value>
</context-param>
<!-- 
  the prefix used by richfaces for session cached resources
-->
<context-param>
  <param-name>org.ajax4jsf.SESSION_RESOURCE_URI_PREFIX</param-name>
  <param-value>a4j/s/${project.version}-r${buildNumber}</param-value>
</context-param>
Next you'll need to add the buildnumber plugin:
<build>
   <plugins>
      <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>buildnumber-maven-plugin</artifactId>
         <executions>
            <execution>
               <phase>validate</phase>
               <goals>
                  <goal>create</goal>
               </goals>
            </execution>
         </executions>
         <configuration>
            <doCheck>false</doCheck>
            <doUpdate>false</doUpdate>
         </configuration>
      </plugin>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-war-plugin</artifactId>
         <configuration>
            <warSourceDirectory>WebContent</warSourceDirectory>
            <webXml>src/PROD/web.xml</webXml>
            <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
            <archive>
               <manifest>
                  <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
               </manifest>
               <manifestEntries>
                  <Implementation-Build>${buildNumber}</Implementation-Build>
               </manifestEntries>
            </archive>
         </configuration>
      </plugin>
If your using eclipse to do development then you'll probably want to have 2 web.xml files. One that eclipse can read with the filtering (property subsititution turned off) and one for production builds.
In

1 comment:

  1. Check your spelling:

    If your using maven its simple.
    First add this to your web.xml:


    This should be:
    If you're using maven, it's simple.
    First add this to your web.xml:




    Walter

    ReplyDelete