examples
package: Caching
The examples
package provides an example service that demonstrates how caching can be done
via one-liners from the CacheMethods
class.
The cachingDemo.CachedWeatherResponseDemo.gloop
service caches the current weather forecast provided by a mock
weather service1, then deletes the entry 10
seconds after it has been created. This service has been exposed as a
REST API and can be accessed through the following URL2:
1 | <host>/api/cached/mock-api/getCurrentWeather/{city}/{countryCode}
|
Related articles
Please see the following articles for more information:
Try it!
In the Navigator, expand the examples
package and navigate to the
code
folder, then expand the cachingDemo
package. This package contains the
files and/or directories as shown below:
1 2 3 4 5 6 7 8 | examples ├── ... └── code └── ... └── cachingDemo ├── api │ └── CachedMockedWeatherApi.api └── CachedWeatherResponseDemo.gloop |
Under this package is the CachedWeatherResponseDemo.gloop
service which demonstrates cache usage and the
cachingDemo.api.CachedMockedWeatherApi.api
file, which exposes the CachedWeatherResponseDemo.gloop
service
as a REST endpoint.
By running the service multiple times3 within the cache entry expiry time (10 seconds by default), the response of the service will be the same. When the cache entry expires, it will respond with a new set of data and will be returning that same data for that same specific amount of time again.
The service will also log messages showing whether the cache was used or not. When the cache doesn't have the entry the service is looking for, it will log a message similar to the following:
1 2 | INFO [Martini] No cache entry found. Creating a cache entry... INFO [Martini] The generated mock weather forecast below is now saved in the cache, this service will keep on returning this value until the cache expires (10 seconds from when it was saved. See line 6 of this service) |
If you keep executing the service within the configured expiry time of seeing the previous message, it will log the following:
1 | [Martini] Found a cache entry! Returning a cache entry... |
After the cache entry has expired, the first log messages will appear again, showing that the cache has removed the entry (as configured).
See comments for documentation
You will find a more detailed explanation about this example you if check the Comments tab
(found within the Properties view) of CachedWeatherResponseDemo.gloop
. Each step in the service is
also decorated with comments4 to better explain the implementation.
Explanation
Each Martini package contains its own CacheManager
. The examples
package has one already set up
and its configuration is defined in conf/caches.conf
.
1 2 3 4 5 6 | examples ├── ... ├── code └── conf ├── caches.conf └── ... |
Inside the caches.conf
file, there is a CacheManager
configured called cachedWeatherResponse
that's used to
cache the response from the exposed REST API.
1 2 3 4 5 6 7 8 9 10 | cachedWeatherResponse { provider = "guava" // (required) // Specifies that each entry should be automatically removed from the cache once a fixed duration has elapsed // after the entry's creation, or the most recent replacement of its value. expireAfterWrite = 10s // (optional) <long>ns | us | ms | s | m | h | d default is ms // Each entry should be automatically removed from the cache once a fixed duration has elapsed // after the entry's last access time, the most recent replacement of its value, or its last access. //expireAfterAccess = 5s // (optional) <long>ns | us | ms | s | m | h | d default is ms } |
If you want to set up your own CacheManager
, simply create a caches.conf
file for your package and define your
CacheManager
there. You can define multiple CacheManager
s in the caches.conf
file. Once configured,
restart the package for the caches to be configured and started.
Martini currently supports Ehcache, Guava, and Redis. Below is a sample configuration
you can use to set up your own CacheManager
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | myCache1 { provider = "guava" // Required expireAfterWrite = 1h expireAfterAccess = 15m heap = 3200 } myCache2 { provider = "ehcache" // Required expireAfterWrite = 1h expireAfterAccess = 15m key { type = "java.lang.String" // Required serializer = "" } value { type = "java.io.Serializable" // Default serializer = "" } heap = 3200 // 3200 entries; may append units (e.g. MB) offHeap = 5MB disk = 10MB diskStore = /tmp/ehcache // Required if using disk persistence } myCache3 { provider = "redis" // Required connectionName = "myRedisConnection" // Redis connection name to use expireAfterWrite = 1h expireAfterAccess = 15m asyncWrites = false // Whether to write to Redis asynchronously or not // Optional custom io.lettuce.core.codec.RedisCodec to use to encode and decode keys and values for the cache codecClassName = "com.company.MyRedisCodec" } |
The format above uses HOCON - a superset of JSON. At minimum, a cache is configurable with just:
1 2 3 4 5 6 | cacheName { provider = guava | ehcache | redis heap = `long` expireAfter* = // if not provided, the cache entries won't expire } |
-
based on a city-country combination ↩
-
<host>
must be substituted with the base URL of your Martini instance. This URL will depend on the where your instance is hosted and how you've configured your server. ↩ -
You can do this easily via REST API calls to
/cached/mock-api/getCurrentWeather/{city}/{country}
. ↩ -
Open the Gloop service file to see comments. Make sure comments are also not hidden. ↩