Documentation Home

Caching Configuration

With the 6.1 release of Broadleaf, the cache approach has changed to use the standard Java caching API - JCache. This does allow for different implementations to by used but the initial out-of-the-box implementation continues to by EHCache (upgraded to EHCache version 3).

The configuration for EHCache 3.0 has changed slightly (details below) but the ability to define an initial configuration on the core framework and the allow aN INDIVIDUAL cache configuration override in the project implementation is still supported.

To override an individual cache setting, you will want to define a bean in your applicationContext.xml file that specifies additional config locations for Broadleaf to merge. This bean will look similar to this:

<bean id="blMergedCacheConfigLocations" class="org.springframework.beans.factory.config.ListFactoryBean">
    <property name="sourceList">
        <list>
            <value>classpath:bl-override-ehcache.xml</value>
        </list>
    </property>
</bean>

Or as a Java COnfiguration

    @Merge("blMergedCacheConfigLocations")
    public List<String> adminOverrideCache() {
        return Arrays.asList("classpath:bl-override-ehcache.xml");
    }

Broadleaf will then pick up this definition and merge it with the default configuration, overriding any regions that Broadleaf has defined while creating new ones.

Note: if you have started using Broadleaf with the DemoSite "Heat Clinic" project then this is already configured for you

Caching with Enterprise

With the Broadleaf Enterprise license caches are expired whenever you make edits in the admin panel. This allows you to set caches extremely

Default Cache Configurations

Broadleaf provides a number of ehcache regions out of the box with sensible defaults. These are defined in the following locations:

These default settings were determined empirically using load testing results from our scalability white paper.

Additional Cache Regions with Enterprise

Beyond the above default cache configurations, various modules that are included with the Enterprise license define new regions. These are notated below.

Enterprise:

<!-- 1 day cache -->
<cache alias="defaultSandboxableCollectionQueryCache">
    <expiry>
        <ttl>86400</ttl>
    </expiry>
    <heap>50000</heap>
</cache>

This is a special cache that acts as the default cache for queries executed as a result of intercepting a collection fetch on an entity class and converting it from many individual select queries to a single select query. This isn't stored in the original cache region as query caches behave differently than entities using the @Cache annotation.

Since a significant number of collections will be cached in this region, it must be sized properly for your application. The best way to determine how large this cache should be is proper profiling and load testing. However, as a rule of thumb you should start with setting it to 5 times the number of products in the catalog. For example, the default setting of 50k assumes a catalog containing 10k products.

The cache region converter, blCollectionQueryCacheRegionConverter, can be customized to provide different enterprise collection query caches other than the default for different original cache regions by merging into the blEnterpriseCollectionCacheRegionConversion bean map. For example:

<bean class="org.broadleafcommerce.common.extensibility.context.merge.LateStageMergeBeanPostProcessor">
    <property name="collectionRef" value="myCollectionCacheRegions" />
    <property name="targetRef" value="blEnterpriseCollectionCacheRegionConversion" />
</bean>

<bean id="myCollectionCacheRegions" class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="sourceMap">
        <map>
            <entry key="blCategories" value="myCategoriesCache"/>
        </map>
    </property>
</bean>

Theme:

<!-- 1 hour cache -->
<cache alias="blThemeConfigurationUpdated">
    <expiry>
        <ttl>3600</ttl>
    </expiry>
    <heap>100</heap>
</cache>

<!-- 1 hour cache -->
<cache alias="blThemeFiles">
    <expiry>
        <ttl>3600</ttl>
    </expiry>
    <heap>10000</heap>
</cache>

<cache alias="blThemeFileNullCheckCache">
    <expiry>
        <ttl>3600</ttl>
    </expiry>
    <heap>1000</heap>
</cache>

i18nEnterprise

<!-- 10 minute cache -->
<cache alias="blInternationalMessageElements">
    <expiry>
        <ttl>600</ttl>
    </expiry>
    <heap>1000</heap>
</cache>

<cache alias="blInternationalMessageNullCheckCache">
    <expiry>
        <ttl>600</ttl>
    </expiry>
    <heap>1000</heap>
</cache>

Price Lists

<!-- 1 hour cache -->
<cache alias="blPriceListCache">
   <expiry>
       <ttl>3600</ttl>
   </expiry>
   <heap>100</heap>
</cache>

<cache alias="blPriceDataCache">
   <expiry>
       <ttl>3600</ttl>
   </expiry>
   <heap>10000</heap>
</cache>

Subscription

<!-- 1 hour cache -->
<cache alias="blSubscriptionCache">
    <expiry>
        <ttl>30</ttl>
    </expiry>
    <heap>100</heap>
</cache>

Manually Expiring Caches in a Running Application

The below methodology exposes the EHCache regions over JMX as MBeans for control. You can then connect to the Java process via a JMX console like VisualVM.

One drawback with this is that you will get duplicate MBean exceptions if you are running the site and admin on the same JVM (deploying to the same Tomcat instance).

  1. Add the following to an applicationContext (either site or admin):

    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
        <!-- indicate to first look for a server -->
        <property name="locateExistingServerIfPossible" value="true"/>
    </bean>
    
    <bean id="managementService"
        class="net.sf.ehcache.management.ManagementService"
        init-method="init"
        destroy-method="dispose">
        <constructor-arg ref="blCacheManager"/>
        <constructor-arg ref="mbeanServer"/>
        <constructor-arg index="2" value="true"/>
        <constructor-arg index="3" value="true"/>
        <constructor-arg index="4" value="true"/>
        <constructor-arg index="5" value="true"/>
    </bean>
    

    or in Java Config:

    @Bean
    public MBeanServerFactoryBean mbeanServer() {
        MBeanServerFactoryBean mBeanServerFactoryBean = new MBeanServerFactoryBean();
        mBeanServerFactoryBean.setLocateExistingServerIfPossible(true);
        return mBeanServerFactoryBean;
    }

    @Bean(initMethod = "init", destroyMethod = "dispose")
    public ManagementService managementService(@Qualifier("blCacheManager") CacheManager cacheManager, @Qualifier("mbeanServer") MBeanServerFactoryBean mbeanServer) {
        ManagementService managementService = new ManagementService(cacheManager, mbeanServer.getObject(), true, true, true, true);
        return managementService;
    }
  1. Start up the server, and connect to it via a JMX listener like VisualVM. If you are running locally, VisualVM will display all local Java processes on the lefthand side that you can easily attach to. In this screenshot, I have attached to my locally running Broadleaf instance that I started via Ant/Maven on the command line:

    visualvm-local

    If you go over to the MBeans tab, you will see the exports from the server. We are interested in the net.sf.ehcache folder and the Cache -> DEFAULT MBean:

    visual-vm-ehcache

    If you click on a specific MBean you can hit the removeAll button to clear the cache:

    visual-vm-cmscache

Simple Remote JMX Connections

Add the following arguments to your JVM (if you are using Tomcat, this is CATALINA_OPTS):

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=4446
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

This opens port 4446 for remote connection

Remote JMX Connections Securely behind a Firewall

The above configuration assigns a random external port for RMI which makes it impossible to securely connect to the running application and only whitelist a specific port. The below instructions assume Tomcat, but there are likely equivalents on other application servers.

  1. In server.xml, add this line anywhere in the <Server> tag, replacing the placeholder ports. The rmiRegistryPortPlatfor is the JMX remote port to connect to while the rmiServerPortPlatform is internally used by Tomcat.

    <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="30000" rmiServerPortPlatform="30001"/>
    
  2. Create a jmxremote.access if one does not already exist

    controlRole   readwrite \
                  create javax.management.monitor.*,javax.management.timer.* \
                  unregister
    
  3. Create a jmxremote.access if one does not already exist with a chmod of 0600

    controlRole  somepassword
    
  4. Change the system properties above to authenticate and specify the password and access file.

    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=true
    -Dcom.sun.management.jmxremote.password.file=/etc/java-7-openjdk/management/jmxremote.password
    -Dcom.sun.management.jmxremote.access.file=/etc/java-7-openjdk/management/jmxremote.access
    -Djava.rmi.server.hostname=1.2.3.4
    

    Note: you could also use com.sun.management.jmxremote.ssl=true and use the domain name for the hostname if you have a valid SSL certificate

  5. In VisualVM right click on "Remote" and hit "Add Remote Host..."

    remote host

  6. Select the host that you just added and go to "Add JMX Connection"

    add JMX remote

Disabling the Cache

You can also set property jcache.disable.cache=true to completely disable all caching in Broadleaf.

Other cache settings

Broadleaf also uses various other caching configured by system properties. Add this to your environment-specific properties files to change the behavior.

cache.page.templates
cache.page.templates.ttl