JCache
The JCache add-on integrates the JCache API (a.k.a. JSR 107) which allows to interact with compliant caching providers in a declarative or a programmatic way.
Dependencies
The add-on dependency is:
<dependency>
<groupId>org.seedstack.addons.jcache</groupId>
<artifactId>jcache</artifactId>
</dependency>
Show version
dependencies {
compile("org.seedstack.addons.jcache:jcache:3.0.0")
}
An JCache-compliant implementation is also required, such as the popular EhCache:
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>LATEST_VERSION_HERE</version>
</dependency>
dependencies {
compile("org.ehcache:ehcache:LATEST_VERSION_HERE")
}
Configuration
Configuration is done by declaring one or more caches:
jcache:
# Configured caches with the name of the cache as key
caches:
cache1:
# The JCache provider to use (fallback to global default if not specified)
provider: (Class<? extends CachingProvider>)
# The built-in expiry policy to use
expiryPolicy: (TOUCHED|ACCESSED|CREATED|MODIFIED|ETERNAL)
# Expiry duration in seconds for built-in expiry policies (defaults to 900)
expiryDuration: (int)
# The factory of the custom expiry policy to use instead of the built-in expiry policy
expiryPolicyFactory: (Class<? extends Factory<? extends javax.cache.expiry.ExpiryPolicy>>)
# The default JCache provider to use if not specified on a cache (auto-detected if not specified at all)
defaultProvider: (Class<? extends CachingProvider>)
To dump the jcache
configuration options:
mvn -q -Dargs="jcache" seedstack:config
Declarative usage
The declarative API is annotation-based and can be used on methods. When the method will be invoked, the corresponding cache operation will take place.
Cache a return value
The following code caches the return value of the method, using its arguments as a key:
public class SomeClass {
@CacheResult(cacheName = "things")
public Thing getThing(String scope, String name) {
// do something
}
}
Keys generation can be customized using the CacheKeyGenerator
interface. If no specific implementation is specified,
the default implementation, per spec, takes all parameters unless one or more parameters are annotated with the
@CacheKey
annotation, in which case only those are used:
public class SomeClass {
@CacheResult(cacheName = "things")
public Thing getThing(@CacheKey String scope, @CacheKey String name, Date timestamp) {
// do something
}
}
@CacheResult
brings the concept of exception cache: whenever a method execution failed,
it is possible to cache the exception that was raised to prevent calling the method again.
JCache has the notion of CacheResolver
which permits to resolve the cache to use at runtime.
public class SomeClass {
@CacheResult(cacheName = "things", cacheResolverFactory = MyCacheResolverFactory.class)
public Thing getThing(@CacheKey String scope, @CacheKey String name, Date timestamp) {
// do something
}
}
Finally, @CacheResult
has a skipGet attribute that can be enabled to always invoke the method regardless of the status
of the cache. This is useful for create or update methods that should always be executed and have their returned value
placed in the cache.
Put a value
The following code add updatedThing
to the things
cache with the scope
and name
arguments as the key:
public class SomeClass {
@CachePut(cacheName = "things")
public void updateThing(String scope, String name, @CacheValue updatedThing) {
// do something
}
}
@CacheValue
annotated parameters are automatically excluded from key generation.
Same as @CacheResult
, @CachePut
allows
to manage any exception that is thrown while executing the method, preventing the put operation to happen if the thrown
exception matches the filter specified on the annotation.
Finally, it is possible to control if the cache is updated before or after the invocation of the annotated method. Of course, if it is updated before, no exception handling takes place.
Remove a value
The @CacheRemove
annotation removes the entry with the scope
and name
arguments as the key from the things
cache:
public class SomeClass {
@CacheRemove(cacheName = "things")
public void deleteThing(String scope, String name) {
// do something
}
}
This annotation has a special exception handling to prevent the eviction if the annotated method throws an exception that matches the filter specified on the annotation.
Remove all values
The @CacheRemoveAll
annotation removes all entries from the things
cache:
public class SomeClass {
@CacheRemoveAll(cacheName = "things")
public void clearAllThings() {
// do something
}
}
Cache defaults
@CacheDefaults
is a class-level annotation that allows you to share common
settings on any caching operation defined on the class. These are:
- The name of the cache
- The custom CacheResolverFactory
- The custom CacheKeyGenerator
Programmatic usage
If you need a more fine-grained control of your caches, you can also use the programmatic API. You just need to inject
the needed Cache
object(s):
public class SomeClass {
@Inject
@Named("things")
private Cache thingsCache;
}
Please check the JavaDoc of the Cache
interface for more information.