This article covers a Hippo CMS version 11. There's an updated version available that covers our most recent release.

HST Binary Content Resource Serving (BinariesServlet)

1. Introduction

BinariesServlet serves binary resources from the repository. Binary resources can be stored in nodes. BinariesServlet has many features to control HTTP headers and cache controls.

With the default configuration, if the request URI is like ' /site/binaries/content/gallery/images/screenshot_cms_small.jpg' (where the context path is ' /site', the servlet path for BinariesServlet is ' /binaries', and the remaining is the path info), then BinariesServlet will read binary content from nodes under ' /content/gallery/images/screenshot_cms_small.jpg' in the repository and write a stream output to the client. In preview context, the binaries are fetched from the repository by the preview siteuser (more precisely in CMS preview a security delegate between site preview user and the logged in cms user). For the live website, the binaries are fetched by the live site user, and in case of subject-based rendering, by the user that is authenticated. The userID is part of the cache key that is used to cache the fetched binaries internally.

2. Configuration

BinariesServlet is configured in web.xml like the following example:

  <servlet>
    <servlet-name>BinariesServlet</servlet-name>
    <servlet-class>org.hippoecm.hst.servlet.BinariesServlet</servlet-class>
  </servlet>

  <!-- SNIP -->

  <servlet-mapping>
    <servlet-name>BinariesServlet</servlet-name>
    <url-pattern>/binaries/*</url-pattern>
  </servlet-mapping>

BinariesServlet can have the following init parameters.

Init parameter name

Example value

Default value

Description

Since

baseBinariesContentPath

/binarycontents

 

 

When this is set, the node path will be prefixed by this parameter to find the binary content.

 

binaryDataPropName

 

jcr:data

The name of the JCR node property containing binary contents.

 

binaryMimeTypePropName

 

jcr:mimeType

The name of the JCR node property containing content type of the binary contents.

 

binaryLastModifiedPropName

 

jcr:lastModified

The name of the JCR node property containing the last modified date.

 

binaryResourceNodeType

 

hippo:resource

The name of the primary node type after which the binary content node should be typed.

 

contentDispositionContentTypes

application/pdf, application/rtf, application/excel

or

application/*

 

Set this parameter when you want to configure which mime types are able to do content dispositioning. If a binary content has a mime type in this configured mime type set, then BinariesServlet will add content disposition header (" Content-Disposition") to specify attachment and file name attribute. You can also use '*' to configure multiple mime types.

 

contentDispositionFilenameProperty

demosite:filename

 

The name of the JCR node property containing the file name attribute for the binary content node. By default, file name attribute is not added when content dispositioning is used for the content. If you want to set file name attribute, then you should define a JCR property, configure the property name with this parameter and set the property values for each binary contents.

 

contentDispositionFilenameEncoding

user-agent-specific

user-agent-agnostic

When content dispositioning is used for the content with a file name attribute, you can specify which encoding strategy should be used. With " user-agent-specific", the file name attribute for the content will be encoded properly based on the user agent. With " user-agent-agnostic", the file name attribute for the content will be encoded with US-ASCII codes only.

 

cache-name

 

defaultBinariesCache

BinariesServlet uses a cache internally. This parameter specifies the bean component name of the internal cache. The default cache component named " defaultBinariesCache" can be found in SpringComponentManager-cache.xml which is packaged in hst-core library.

 

cache-max-object-size-bytes

 

262144

When this parameter is set to a positive value, a binary content containing data not more than this configured size can be cached. If a binary content contains data more than this size, it will not be cached. The default value is 262144 bytes (256 KB).

 

validity-check-interval-seconds

 

180

Basically, each cache item is validated against the last modified property of the content node. However, it is not efficient to try to validate on every request. So, this parameter enables to configure the validation checking interval. For optimization, the default validation checking interval is set to 180 seconds.

 

set-expires-headers

 

true

Flag whether to set expires HTTP headers.
When this parameter is true, BinariesServlet sets proper cache control HTTP headers such as " Expires" and " Cache-Control".

 

set-content-length-header

 

true

Flag whether to set the Content-Length HTTP header.
When this parameter is true, BinariesServlet sets the Content-Length HTTP header.

2.20.04+ and 2.21.01+

.

3. Cache component configuration

By default, the " defaultBinariesCache" component bean is defined as follows:

  <!-- The ehcache manager component -->

  <!-- By default, this component will try to read ehcache.xml from
       the classpath. -->
  <bean id="ehCacheManager"
       class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  </bean>


  <!-- abstract base cache component bean definition with default property
       configuration -->
  <bean id="abstractEhCacheBase" abstract="true">
    <property name="cacheManager" ref="ehCacheManager" />
    <property name="maxEntriesLocalHeap" value="256" />
    <property name="maxElementsOnDisk" value="0" />
    <property name="eternal" value="false" />
    <property name="overflowToDisk" value="false" />
    <!-- time to live in seconds. default 1 day -->
    <property name="timeToLive" value="86400" />
    <!-- time to idle in seconds. default 1 day -->
    <property name="timeToIdle" value="86400" />
    <property name="diskPersistent" value="false" />
    <property name="diskExpiryThreadIntervalSeconds" value="120" />
  </bean>


  <!-- abstract non-blocking cache component bean definition -->
  <bean id="abstractEhCache" abstract="true" parent="abstractEhCacheBase"
        class="org.springframework.cache.ehcache.EhCacheFactoryBean">
  </bean>


  <!-- abstract blocking cache component bean definition -->
  <bean id="abstractBlockingEhCache" abstract="true"
        parent="abstractEhCacheBase"
        class="org.hippoecm.hst.site.container.BlockingEhCacheFactoryBean">
  </bean>

  <!-- the default cache component bean definition for BinariesServlet -->
  <bean id="defaultBinariesCache"
        class="org.hippoecm.hst.cache.CompositeHstCache">
    <constructor-arg>
      <bean parent="abstractBlockingEhCache">
        <property name="cacheName" value="binariesCache" />
        <!-- time to idle in seconds. default 1 day -->
        <property name="timeToLive" value="86400" />
        <!-- To avoid concurrency issues, use blocking cache -->
        <property name="blocking" value="true" />
      </bean>
    </constructor-arg>
  </bean>
Before CMS 11.2.0, the class org.hippoecm.hst.cache.CompositeHstCache did not exist and should be org.hippoecm.hst.cache.ehcache.HstCacheEhCacheImpl. This HstCacheEhCacheImpl class is still present in 11.2.0, but has been deprecated in favor of CompositeHstCache

Customize the default cache configuration

In most cases, the default bean configuration above would be good enough, but you can also override the default bean definitions by adding bean definition configuration XML files into classpath:/META-INF/hst-assembly/overrides/.

Depending on the requirements there are different ways of creating custom configuration for the cache.

 

Option 1: Creating a custom cache from Spring

Create a file called binaries-cache.xml (you can choose any name) in your local project folder: site/src/main/resources/META-INF/hst-assembly/overrides.

As an example the content of the file could look like:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <import resource=
"classpath:/org/hippoecm/hst/site/container/SpringComponentManager-cache.xml"
             />

  <bean id="customBinariesCache"
        class="org.hippoecm.hst.cache.CompositeHstCache">
    <constructor-arg>
      <bean parent="abstractBlockingEhCache">
        <property name="cacheName" value="customBinariesCache" />
        <property name="maxEntriesLocalHeap" value="1024"/>
        <property name="overflowToDisk" value="true"/>
        <!-- time to idle in seconds. default 1 day -->
        <property name="timeToLive" value="86400" />
        <property name="blocking" value="true" />
      </bean>
    </constructor-arg>
    <property name="statisticsEnabled"
              value="${default.binaries.cache.statistics.enabled}"/>
  </bean>

</beans>

 

Now you only need to instruct the BinariesServlet to use the new cache called customBinariesCache.

<servlet>
  <servlet-name>BinariesServlet</servlet-name>
  <servlet-class>org.hippoecm.hst.servlet.BinariesServlet</servlet-class>
  <init-param>
    <param-name>cache-name</param-name>
    <param-value>customBinariesCache</param-value>
  </init-param>
</servlet>

Option 2: Externalizing the cache configuration

By default the cache configuration is packaged in the deployed war file. Sometimes you might want to externalize the cache configuration so that you can tweak the configuration without having to modify the Spring configuration inside the war (which might require a new deployment).

It's quite easy to do this by changing the configLocation of the ehCacheManagerbean.

You can use the same file as mentioned above ( binaries-cache.xml) to redefine the ehCacheManager.

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <import resource=
          "classpath:/org/hippoecm/hst/site/container
                           /SpringComponentManager-cache.xml" />

  <bean id="ehCacheManager"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="configLocation"
              value="file:${catalina.base}/conf/ehcache.xml"/>
  </bean>
</beans>

In the example configuration above we use the ehcache.xml file stored in the conf directory of the application container.

 

Here is an example ehcache.xml file which reflects the default Spring configured binariesCache:

<ehcache updateCheck="false">

  <diskStore path="java.io.tmpdir"/>

  <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="true"
    maxElementsOnDisk="10000000"
    diskPersistent="false"
    diskExpiryThreadIntervalSeconds="120"
    memoryStoreEvictionPolicy="LRU"
    />

  <!-- default settings copied from abstractEhCacheBase -->
  <!-- time to live in seconds. default 1 day -->
  <cache name="binariesCache"
    maxElementsInMemory="256"
    maxElementsOnDisk="0"
    eternal="false"
    overflowToDisk="false"
    timeToIdleSeconds="86400"
    timeToLiveSeconds="86400"
    diskPersistent="false"
    diskExpiryThreadIntervalSeconds="120">
  </cache>

</ehcache>

 

 

If the named Cache instance is found in the ehcache.xml file, the properties set by Spring will be ignored and the Cache instance will be retrieved from the CacheManager.