Peeper - a simple message board

The demo directory in the Ehcache 3 sources includes a sample applications with two (2) implementations demonstrating Ehcache use. Implemented as a simple browser-based web service, the sample application Peeper displays any messages (peeps) previously entered and accepts new peeps, recording the peeps in a database. The peeps database, shared among implementations of the Peeper application, is located at $HOME/ehcache-demo-peeper.mv.db. This file may be safely erased while the application is not running. While running, information about the operation of the Peeper application (database access, cache access, etc.) is written to the console.

While the sample application may be run, the application is very simplistic — the code implementing the sample is the interesting bit. Running the sample application requires the use of Gradle. This sample may be accessed from GitHub by cloning the Ehcache 3 git repository:

# Create and/or change to a directory to hold the Ehcache git repository clone
git clone https://github.com/ehcache/ehcache3.git

Peeper without Caching — 00-NoCache

The first sample, located in demos/00-NoCache, is a base Peeper application that does not use caching. Each peep is stored in the database and all peeps are read from the database to display the Peeper web page. To run this implementation:

cd ehcache3/demos/00-NoCache
../../gradlew appStart

This builds the necessary components, starts a Jetty web service, and displays the URL of the web server on the console. The URL will be something like http://localhost:8080/ehcache-demos/00-NoCache/.

While running, lines like the following are displayed to the console:

11:23:53.536 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:24:03.226 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Adding peep into DB
11:24:03.234 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:24:13.312 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Adding peep into DB
11:24:13.317 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:24:41.238 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:24:50.896 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Adding peep into DB
11:24:50.901 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:24:56.295 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Adding peep into DB
11:24:56.298 [800523121@qtp-1157162760-2] INFO  o.e.d.p.DataStore - Loading peeps from DB

Note the absence of indications of interactions with a cache.

Peeper with Cache-aside Caching — 01-CacheAside

The second sample, located in demos/01-CacheAside, is a version of the Peeper application that makes use of Ehcache. As each peep is read from the database (for display in the web page), it is written to an Ehcache instance. If the Peeper web page is refreshed (without adding a new peep) or a new Peeper client connects, the peeps are read from the cache (instead of the database) to form the web page. If a new peep is posted, the cache is cleared. To run this implementation:

cd ehcache3/demos/01-CacheAside
../../gradlew appStart

This builds the necessary components, starts a Jetty web service, and displays the URL of the web server on the console. The URL will be something like http://localhost:8080/ehcache-demos/01-CacheAside/.

While running, lines like the following are displayed to the console:

11:26:20.557 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:26:20.572 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Filling cache with peeps
11:26:33.422 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Adding peep into DB
11:26:33.428 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Clearing peeps cache
11:26:33.431 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:26:33.432 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Filling cache with peeps
11:26:50.025 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Adding peep into DB
11:26:50.027 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Clearing peeps cache
11:26:50.030 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Loading peeps from DB
11:26:50.031 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Filling cache with peeps
11:27:10.742 [139688380@qtp-965028604-0] INFO  o.e.d.p.DataStore - Getting peeps from cache

Note the presence of the Filling cache with peeps, Clearing peeps cache, and Getting peeps from cache lines indicating cache interactions.

XML with 107 extension

<ehcache:config
    xmlns:ehcache="http://www.ehcache.org/v3"
    xmlns:jcache="http://www.ehcache.org/v3/jsr107">

  <!--
    OPTIONAL
     services to be managed and lifecycled by the CacheManager
  -->
  <ehcache:service>
    <!--
      One element in another namespace, using our JSR-107 extension as an example here
    -->
    <jcache:defaults>
      <jcache:cache name="invoices" template="myDefaultTemplate"/>
    </jcache:defaults>
  </ehcache:service>

  <!--
    OPTIONAL
      A <cache> element defines a cache, identified by the mandatory 'alias' attribute, to be managed by the CacheManager
  -->
  <ehcache:cache alias="productCache">

    <!--
      OPTIONAL, defaults to java.lang.Object
        The FQCN of the type of keys K we'll use with the Cache<K, V>
    -->
    <ehcache:key-type copier="org.ehcache.impl.copy.SerializingCopier">java.lang.Long</ehcache:key-type>

    <!--
      OPTIONAL, defaults to java.lang.Object
        The FQCN of the type of values V we'll use with the Cache<K, V>
    -->
    <ehcache:value-type copier="org.ehcache.impl.copy.SerializingCopier">com.pany.domain.Product</ehcache:value-type>

    <!--
      OPTIONAL, defaults to no expiry
        Entries to the Cache can be made to expire after a given time
    -->
    <ehcache:expiry>
      <!--
        time to idle, the maximum time for an entry to remain untouched
          Entries to the Cache can be made to expire after a given time
          other options are:
             * <ttl>, time to live;
             * <class>, for a custom Expiry implementation; or
             * <none>, for no expiry
      -->
      <ehcache:tti unit="minutes">2</ehcache:tti>
    </ehcache:expiry>

    <!--
      OPTIONAL, defaults to no advice
        An eviction advisor, which lets you control what entries should only get evicted as last resort
        FQCN of a org.ehcache.config.EvictionAdvisor implementation
    -->
    <ehcache:eviction-advisor>com.pany.ehcache.MyEvictionAdvisor</ehcache:eviction-advisor>

    <!--
      OPTIONAL,
        Let's you configure your cache as a "cache-through",
        i.e. a Cache that uses a CacheLoaderWriter to load on misses, and write on mutative operations.
    -->
    <ehcache:loader-writer>
      <!--
          The FQCN implementing org.ehcache.spi.loaderwriter.CacheLoaderWriter
      -->
      <ehcache:class>com.pany.ehcache.integration.ProductCacheLoaderWriter</ehcache:class>
        <!-- Any further elements in another namespace -->
    </ehcache:loader-writer>

    <!--
        The maximal number of entries to be held in the Cache, prior to eviction starting
    -->
    <ehcache:heap unit="entries">200</ehcache:heap>

    <!--
       OPTIONAL
        Any further elements in another namespace
    -->
  </ehcache:cache>

  <!--
    OPTIONAL
      A <cache-template> defines a named template that can be used be <cache> definitions in this same file
      They have all the same property as the <cache> elements above
  -->
  <ehcache:cache-template name="myDefaultTemplate">
    <ehcache:expiry>
      <ehcache:none/>
    </ehcache:expiry>
    <!--
       OPTIONAL
        Any further elements in another namespace
    -->
  </ehcache:cache-template>

  <!--
    A <cache> that uses the template above by referencing the cache-template's name in the uses-template attribute:
  -->
  <ehcache:cache alias="customerCache" uses-template="myDefaultTemplate">
    <!--
      Adds the key and value type configuration
    -->
    <ehcache:key-type>java.lang.Long</ehcache:key-type>
    <ehcache:value-type>com.pany.domain.Customer</ehcache:value-type>

    <!--
      Overwrites the capacity limit set by the template to a new value
    -->
    <ehcache:heap unit="entries">200</ehcache:heap>
  </ehcache:cache>

</ehcache:config>