We will write a custom JSF resource handler CustomResourceHandler which will accomplish the URL modifying. The resource handler can be registered in faces-config.xml as follows:
<application> <resource-handler>packagename.CustomResourceHandler</resource-handler> </application>Writing of any resource handler is straightforward. We need to extend javax.faces.application.ResourceHandlerWrapper
public class CustomResourceHandler extends javax.faces.application.ResourceHandlerWrapper { private ResourceHandler wrapped; public CustomResourceHandler(ResourceHandler wrapped) { this.wrapped = wrapped; } @Override public ResourceHandler getWrapped() { return this.wrapped; } @Override public Resource createResource(String resourceName, String libraryName) { Resource resource = super.createResource(resourceName, libraryName); // here a check of library name could be necessary, etc. ... return new CustomResource(resource); } }We need now a class CustomResource. CustomResource should extend javax.faces.application.ResourceWrapper and delegate all calls to this wrapper class except one call getRequestPath(). Method getRequestPath() needs to be overwritten.
public class CustomResource extends javax.faces.application.ResourceWrapper { private javax.faces.application.Resource resource; public CustomResource(Resource resource) { this.resource = resource; } @Override public Resource getWrapped() { return this.resource; } @Override public String getRequestPath() { String requestPath = resource.getRequestPath(); // get current revision String revision = ... if(requestPath.contains("?")) requestPath = requestPath + "&rv=" + revision; else requestPath = requestPath + "?rv=" + revision; return requestPath; } @Override public String getContentType() { return getWrapped().getContentType(); } ... }That's all. For more control in Mojarra JSF implementation there are two handy config parameters for web.xml.
com.sun.faces. resourceUpdateCheckPeriod gives frequency in minutes to check for changes to webapp artifacts that contain resources.
An interesting situation arises with a custom resource handler and richfaces when using the packed/compressed resources available in RF4.1. In the place where it says // here a check of library name could be necessary, etc. you need to check if the libraryName is "org.richfaces" and just "return resource;".
ReplyDeleteIf you use the jquery distribution from within the richfaces libraries then just using h:outputScript name="jquery.js" will cause the richfaces packed.js to load, and it doesn't like having a query string appended to it. So you also need to check in this same place if the resourceName is "jquery.js" and "return resource;" - not return new CustomResource(resource);.
Regards,
healeyb
Nice solution! Exactly what I was looking for. Thanks!
ReplyDeleteUnfortunately the tags were truncated. The tags I tried to mention are:
ReplyDelete<h:outputStylesheet />, <h:outputScript /> and <h:graphicImage />
I'm using a code like this. But raise NullPointerException when I try to open a facelets page that contains a composite component.
ReplyDeleteSo, in my project, I had to undo the changes.
Great post, RE the NullPointerException raised for composite components, adding
ReplyDelete@Override
public String getLibraryName() {
return resource.getLibraryName();
}
@Override
public String getResourceName() {
return resource.getResourceName();
}
will fix this in Majorra. It looks like an over-site in the ResourceWrapper implementation that it does not provide these.
You made some decent points there. I looked on the internet for the issue and found most individuals will go along with with your website.
ReplyDeleteBespoke Software Development.
Nice solution! Big up!
ReplyDeleteThanks, it worked perfectly for me
ReplyDelete