I was going through custom resource handlers in JSF 2 when I came across the UnmappedResourceHandler of omnifaces. This was added in Omnifaces after this post.
I noticed that unlike the other two ResourceHandlers that Omnifaces provides viz. CDNResourceHandler and CombinedResourceHandler, this one requires and additional mapping for the JSF resource URL prefix pattern:
<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
<url-pattern>/javax.faces.resource/*</url-pattern>
</servlet-mapping>
I am no expert on JSF but I am curious to know why this is needed only for this type and not for the other two?
JSF resources also need to be served by the
FacesServlet. It's the one responsible for locating the right file in/resourcesfolder and returing it along with proper caching headers. If you remove the.xhtmlextension (or/facespath) from the resource URL, then the URL won't match the URL pattern ofFacesServletanymore and thus theFacesServletwouldn't be invoked and wouldn't be able to do its job of serving the resource. You would only get a 404 Not Found error back, because the "raw" resource URLs do not match the public webcontent folder structure.UnmappedResourceHandlermakes use of the fact that JSF resource URLs have a common prefix path/javax.faces.resource, as identified byResourceHandler.RESOURCE_IDENTIFIER. So, in order to invoke theFacesServletanyway, even without the.xhtmlextension (or/facespath), you just need to add the/javax.faces.resource/*URL pattern to the mapping.The
CDNResourceHandlerdoesn't need a change in the mapping as it doesn't produce JSF resource URLs anyway, but true CDN URLs like ones pointing to jQuery or Google CDN hosts. Those URLs wouldn't (need to) hit theFacesServletanyway.The
CombinedResourceHandlerjust produces default JSF resource URLs, with.xhtmlextension (or/facespath). It only uses a speciallibraryname ofomnifaces.combined, so that theCombinedResourceHandlercan identify them.