org.omnifaces.resourcehandler
Class CombinedResourceHandler

java.lang.Object
  extended by javax.faces.application.ResourceHandler
      extended by javax.faces.application.ResourceHandlerWrapper
          extended by org.omnifaces.resourcehandler.CombinedResourceHandler
All Implemented Interfaces:
java.util.EventListener, javax.faces.event.FacesListener, javax.faces.event.SystemEventListener, javax.faces.FacesWrapper<javax.faces.application.ResourceHandler>

public class CombinedResourceHandler
extends javax.faces.application.ResourceHandlerWrapper
implements javax.faces.event.SystemEventListener

This ResourceHandler implementation will remove all separate script and stylesheet resources which have the target attribute set to "head" from the UIViewRoot and create a combined one for all scripts and another combined one for all stylesheets, when the JSF project stage is not set to Development.

To get it to run, this handler needs be registered as follows in faces-config.xml:

 <application>
   <resource-handler>org.omnifaces.resourcehandler.CombinedResourceHandler</resource-handler>
 </application>
 

Note that the target attribute of <h:outputStylesheet> already defaults to "head" but the one of <h:outputScript> not. So if you have placed this inside the <h:head>, then you would still need to explicitly set its target attribute to "head", otherwise it will be treated as an inline script and not be combined. This is a design limitation.

 <h:head>
   <h:outputStylesheet name="style.css" />
   <h:outputScript name="script.js" target="head" />
 </h:head>
 

If you want them to appear after any auto-included resources, then move the declarations to the <h:body>.

 <h:body>
   <h:outputStylesheet name="style.css" />
   <h:outputScript name="script.js" target="head" />
 </h:body>
 

Configuration

The following context parameters are available:

"org.omnifaces.COMBINED_RESOURCE_HANDLER_EXCLUDED_RESOURCES" Comma separated string of resource identifiers of <h:head> resources which needs to be excluded from combining. For example:
<param-value>primefaces:primefaces.css, javax.faces:jsf.js</param-value>
Any combined resource will be included after any of those excluded resources.
"org.omnifaces.COMBINED_RESOURCE_HANDLER_SUPPRESSED_RESOURCES" Comma separated string of resource identifiers of <h:head> resources which needs to be suppressed and removed. For example:
<param-value>skinning.ecss, primefaces:jquery/jquery.js</param-value>
"org.omnifaces.COMBINED_RESOURCE_HANDLER_INLINE_CSS" Set to true if you want to render the combined CSS resources inline (embedded in HTML) instead of as a resource.
"org.omnifaces.COMBINED_RESOURCE_HANDLER_INLINE_JS" Set to true if you want to render the combined JS resources inline (embedded in HTML) instead of as a resource.

Here, the "resource identifier" is the unique combination of library name and resource name, separated by a colon, exactly the syntax as you would use in #{resource} in EL. If there is no library name, then just omit the colon. Valid examples of resource identifiers are filename.ext, folder/filename.ext, library:filename.ext and library:folder/filename.ext.

Note that this combined resource handler is not able to combine resources which are not been added as a component resource, but are been hardcoded in some renderer (such as theme.css in case of PrimeFaces and several JavaScript files in case of RichFaces), or are been definied using plain HTML <link> or <script> elements. Also, when you're using RichFaces with the context parameter org.richfaces.resourceOptimization.enabled set to true, then the to-be-combined resource cannot be resolved by a classpath URL due to RichFaces design limitations, so this combined resource handler will use an internal workaround to get it to work anyway, but this involves firing a HTTP request for every resource. The impact should however be relatively negligible as this is performed on localhost.

CDNResourceHandler

If you're also using the CDNResourceHandler or, at least, have configured its context parameter "org.omnifaces.CDN_RESOURCE_HANDLER_URLS", then those CDN resources will automatically be added to the set of excluded resources.

Author:
Bauke Scholtz

Field Summary
static java.lang.String LIBRARY_NAME
          The default library name of a combined resource.
static java.lang.String PARAM_NAME_EXCLUDED_RESOURCES
          The context parameter name to specify resource identifiers which needs to be excluded from combining.
static java.lang.String PARAM_NAME_INLINE_CSS
          The context parameter name to enable rendering CSS inline instead of as resource link.
static java.lang.String PARAM_NAME_INLINE_JS
          The context parameter name to enable rendering JS inline instead of as resource link.
static java.lang.String PARAM_NAME_SUPPRESSED_RESOURCES
          The context parameter name to specify resource identifiers which needs to be suppressed and removed.
 
Fields inherited from class javax.faces.application.ResourceHandler
LOCALE_PREFIX, RESOURCE_EXCLUDES_DEFAULT_VALUE, RESOURCE_EXCLUDES_PARAM_NAME, RESOURCE_IDENTIFIER
 
Constructor Summary
CombinedResourceHandler(javax.faces.application.ResourceHandler wrapped)
          Creates a new instance of this combined resource handler which wraps the given resource handler.
 
Method Summary
 javax.faces.application.Resource createResource(java.lang.String resourceName, java.lang.String libraryName)
           
 javax.faces.application.ResourceHandler getWrapped()
           
 void handleResourceRequest(javax.faces.context.FacesContext context)
           
 boolean isListenerForSource(java.lang.Object source)
          Returns true if the source is an instance of UIViewRoot.
 void processEvent(javax.faces.event.SystemEvent event)
          Before rendering of a freshly created view, perform the following actions: Collect all component resources from the head.
 
Methods inherited from class javax.faces.application.ResourceHandlerWrapper
createResource, createResource, getRendererTypeForResourceName, isResourceRequest, libraryExists
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LIBRARY_NAME

public static final java.lang.String LIBRARY_NAME
The default library name of a combined resource. Make sure that this is never used for other libraries.

See Also:
Constant Field Values

PARAM_NAME_EXCLUDED_RESOURCES

public static final java.lang.String PARAM_NAME_EXCLUDED_RESOURCES
The context parameter name to specify resource identifiers which needs to be excluded from combining.

See Also:
Constant Field Values

PARAM_NAME_SUPPRESSED_RESOURCES

public static final java.lang.String PARAM_NAME_SUPPRESSED_RESOURCES
The context parameter name to specify resource identifiers which needs to be suppressed and removed.

See Also:
Constant Field Values

PARAM_NAME_INLINE_CSS

public static final java.lang.String PARAM_NAME_INLINE_CSS
The context parameter name to enable rendering CSS inline instead of as resource link.

See Also:
Constant Field Values

PARAM_NAME_INLINE_JS

public static final java.lang.String PARAM_NAME_INLINE_JS
The context parameter name to enable rendering JS inline instead of as resource link.

See Also:
Constant Field Values
Constructor Detail

CombinedResourceHandler

public CombinedResourceHandler(javax.faces.application.ResourceHandler wrapped)
Creates a new instance of this combined resource handler which wraps the given resource handler. If the current JSF project stage is not set to Development, then the initialization will be performed and this will also register this resource handler as a pre render view event listener, so that it can do the job of removing the CSS/JS resources and adding combined ones.

Parameters:
wrapped - The resource handler to be wrapped.
Method Detail

isListenerForSource

public boolean isListenerForSource(java.lang.Object source)
Returns true if the source is an instance of UIViewRoot.

Specified by:
isListenerForSource in interface javax.faces.event.SystemEventListener

processEvent

public void processEvent(javax.faces.event.SystemEvent event)
                  throws javax.faces.event.AbortProcessingException
Before rendering of a freshly created view, perform the following actions:

Specified by:
processEvent in interface javax.faces.event.SystemEventListener
Throws:
javax.faces.event.AbortProcessingException

createResource

public javax.faces.application.Resource createResource(java.lang.String resourceName,
                                                       java.lang.String libraryName)
Overrides:
createResource in class javax.faces.application.ResourceHandlerWrapper

handleResourceRequest

public void handleResourceRequest(javax.faces.context.FacesContext context)
                           throws java.io.IOException
Overrides:
handleResourceRequest in class javax.faces.application.ResourceHandlerWrapper
Throws:
java.io.IOException

getWrapped

public javax.faces.application.ResourceHandler getWrapped()
Specified by:
getWrapped in interface javax.faces.FacesWrapper<javax.faces.application.ResourceHandler>
Overrides:
getWrapped in class javax.faces.application.ResourceHandlerWrapper