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).
Add the following to an
applicationContext
(eithersite
oradmin
):<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;
}
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:
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:
If you click on a specific MBean you can hit the
removeAll
button to clear the cache:
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.
In
server.xml
, add this line anywhere in the<Server>
tag, replacing the placeholder ports. ThermiRegistryPortPlatfor
is the JMX remote port to connect to while thermiServerPortPlatform
is internally used by Tomcat.<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="30000" rmiServerPortPlatform="30001"/>
Create a
jmxremote.access
if one does not already existcontrolRole readwrite \ create javax.management.monitor.*,javax.management.timer.* \ unregister
Create a
jmxremote.access
if one does not already exist with a chmod of 0600controlRole somepassword
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 certificateIn VisualVM right click on "Remote" and hit "Add Remote Host..."
Select the host that you just added and go to "Add JMX Connection"
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