Technical Articles
How to Use Redis with SAP Cloud SDK
Note: For a complete overview of our blog post series visit the SAP Cloud SDK Overview.
For an overview of new features of the SAP Cloud SDK, please look at our recent announcement post.
Introduction
With the new version 3 of SAP Cloud SDK, it’s possible to integrate custom caching frameworks. The application developer can now take the library of their choice, as long as it supports JCache (JSR-107). By loading dependencies into the Maven project, the caching framework is enabled automatically due to the Service Provider Interface (SPI).
By default the Caffeine library is recommended for easy to use, efficient caching. But certain use cases require a distributed caching setup, which allows the storing of data far beyond the application container scope.
Redis
One of the most popular tools to store in-memory data is Redis. The open source tool can be used as database, message broker and cache. It features built-in functionality for data replication, transactions and high availability. Even using on-disk persistence is possible. And there is much more to discover with this software.
Run locally
There are multiple ways to start a Redis instance. Probably the easiest way is by running a local docker container:
// for running a instance as daemon service
docker run --name my-redis -d -p 6379:6379 redis
// for temporarily running the instance in the current terminal
docker run --name my-redis -it --rm -p 6379:6379 redis
The default port for Redis is 6379 but it can be changed to any open port number.
Caching with the SAP Cloud SDK
To use caching with SAP Cloud SDK it’s recommended to use the ResilienceDecorator. This utility class allows to decorate a given lambda (e.g. external service call) with resilient mechanisms:
- timeout
- circuit breaker
- bulkhead
- fallback
- caching
Add Maven Dependency
By default the resilience strategy featuring Resilience4j is chosen for Cloud SDK. But for caching there is no default dependency provided, the application developer is required to decide on a module for caching.
Usually the following dependency would be recommended for Caffeine:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>jcache</artifactId>
<version>2.8.0</version>
</dependency>
But for enabling Redis you should choose the following dependency instead:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.2</version>
</dependency>
Note: Please take a (new) version of your choice.
The Redisson library is a Java client for connecting and using Redis. It also includes a JCache implementation for the SPI.
Add Redisson Configuration
At runtime Redisson requires a configuration file, from which it reads the current configuration. Please consider other configuration mechanisms as well. The following file features the most basic setup:
./application/src/main/resources/redisson-jcache.yaml
singleServerConfig:
address: "redis://127.0.0.1:6379"
By having the file in the “resource” folder we make sure it will be available at runtime. Please change the configuration with regards to your application setup.
Usage with SAP Cloud SDK
Now consider you have the following computation heavy operation, for which you want to apply a resilience and caching strategy:
Supplier<T> busyLambda;
Now when using the ResilienceDecorator you can enable caching to the lambda with the following code:
import com.sap.cloud.sdk.cloudplatform.resilience.ResilienceDecorator;
import com.sap.cloud.sdk.cloudplatform.resilience.ResilienceConfiguration;
ResilienceConfiguration.CacheConfiguration cacheConfiguration =
ResilienceConfiguration.CacheConfiguration.of(Duration.ofSeconds(10)).withoutParameters();
ResilienceConfiguration resilienceConfiguration =
ResilienceConfiguration.of(YourServiceClass.class).cacheConfiguration(cacheConfiguration);
T result = ResilienceDecorator.executeSupplier(busyLambda, resilienceConfiguration);
The ResilienceDecorator is instantiated with the reference of your service class. You can use any other type of identifier heres as well. Also the decorator utility class features many other methods to decorate (and execute) a lambda. Please find the JavaDoc for more information.
Here the resilience configuration only features a dedicated cache configuration. Settings for timeout, circuit breaker and bulkhead are implicitly taken from default values.
The configuration for cache declares a lifetime of ten seconds after which the next lambda invocation triggers a cache miss and the underlying method will be called – and it’s response persisted in the cache again. Additional a set of parameters could be provided in order to differentiate between requests depending on arguments which may have been used to define the busySupplier. But to keep to keep the example simple, we declare “withoutParameters”.
That’s it.
Now Redis is being used by default in your application with the SAP Cloud SDK.
If you are not able to provide a
yaml
file for configuring Redisson, for e.g. in case you are using an SCP service like for e.g. Redis on hyperscaler, you can configure Redisson programmatically by following the below steps:Decorator
that extends theDefaultCachingDecorator
Decorator
For our example, we are populating redisson's configuration object with values read from
VCAP_SERVICES
in Cloud Foundry.(Assumption is that we have an app deployed in CF and bound to the Redis on hyperscaler SCP service)Do you confirm cached object must implement Serializable?
It's not mentioned in the blog.
But default Redisson Serializers require classes to implement the Serializable interface which makes a caffeine to redis transition tricky
Correct, as of today by default Redisson requires T to be Serializable.
Unfortunately we cannot just add the interface to all of our (internal) classes because it results in additional, permanent API contract that we would need to respect and maintain indefinitely.
Hence your current options is to either choose a different Redisson codec, e.g. Jackson...
... or alternatively find a custom transformation in your application from T to Serializable.
Thank you very much !! Very valuable blog.
I have some doubts
Where do we use this logic in our application , and How do we start using it .
Do we have some more sample/example on its usage?
Thank you in advance!!
Hi Gaurav,
thanks for reaching out to us with your question.
For this integration to work in your application, all you have to do is to include the org.redisson:redisson dependency instead of the usual com.github.ben-manes.caffeine:jcache dependency - the entire rest, such as loading the correct classes, will be handled automatically under the hood without any input required from your side.
(Of course, you also have to supply the configuration file for Redis as described in the post)
Regarding the question about how to use our resilience APIs, please take a look at our documentation.
Best regards,
Johannes