Skip to content

Integration with Spring

Spring Boot Starter

Integrates Redisson with Spring Boot library. Depends on Spring Data Redis module.

Supports Spring Boot 1.3.x - 4.0.x

Usage

  1. Add redisson-spring-boot-starter dependency into your project:

    • Redisson PRO

      Maven

      <dependency>
         <groupId>pro.redisson</groupId>
         <artifactId>redisson-spring-boot-starter</artifactId>
         <version>4.1.0</version>
      </dependency>
      

      Gradle

      compile 'pro.redisson:redisson-spring-boot-starter:4.1.0'
      

      License key configuration

    • Community Edition

      Maven

      <dependency>
         <groupId>org.redisson</groupId>
         <artifactId>redisson-spring-boot-starter</artifactId>
         <version>4.1.0</version>
      </dependency>
      

      Gradle

      compile 'org.redisson:redisson-spring-boot-starter:4.1.0'
      

    Redisson PRO vs. Community Edition ➜

    redisson-spring-boot-starter depends on redisson-spring-data module compatible with the latest version of Spring Boot. Downgrade redisson-spring-data module if necessary to support previous Spring Boot versions:

    redisson-spring-data
    module name
    Spring Boot
    version
    redisson-spring-data-16 1.3.y
    redisson-spring-data-17 1.4.y
    redisson-spring-data-18 1.5.y
    redisson-spring-data-2x 2.x.y
    redisson-spring-data-3x 3.x.y
    redisson-spring-data-4x 4.x.y

    For Gradle, you can downgrade to redisson-spring-data-27 this way:

    implementation ("org.redisson:redisson-spring-boot-starter:4.1.0") {
       exclude group: 'org.redisson', module: 'redisson-spring-data-40'
    }
    implementation "org.redisson:redisson-spring-data-27:4.1.0"
    

    For Maven, you can downgrade to redisson-spring-data-27 this way:

    <dependencies>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>4.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.redisson</groupId>
                    <artifactId>redisson-spring-data-40</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-data-27</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>
    
  2. Add settings into application.settings file:

    Using common Spring Boot 3.x+ settings:

    spring:
      data:
        redis:
          database: 
          host:
          port:
          password:
          ssl: 
          timeout:
          connectTimeout:
          clientName:
          cluster:
            nodes:
          sentinel:
            master:
            nodes:
    

    Using common Spring Boot up to 2.7.x settings:

    spring:
      redis:
        database: 
        host:
        port:
        password:
        ssl: 
        timeout:
        connectTimeout:
        clientName:
        cluster:
          nodes:
        sentinel:
          master:
          nodes:
    

    Using Redisson config file: (single mode, replicated mode, cluster mode, sentinel mode, proxy mode, multi cluster mode, multi sentinel mode)

    spring:
      redis:
       redisson: 
          file: classpath:redisson.yaml
    

    Using Redisson settings: (single mode, replicated mode, cluster mode, sentinel mode, proxy mode, multi cluster mode, multi sentinel mode)

    spring:
      redis:
       redisson: 
          config: |
            clusterServersConfig:
              idleConnectionTimeout: 10000
              connectTimeout: 10000
              timeout: 3000
              retryAttempts: 3
              retryInterval: 1500
              failedSlaveReconnectionInterval: 3000
              failedSlaveCheckInterval: 60000
              password: null
              subscriptionsPerConnection: 5
              clientName: null
              loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
              subscriptionConnectionMinimumIdleSize: 1
              subscriptionConnectionPoolSize: 50
              slaveConnectionMinimumIdleSize: 24
              slaveConnectionPoolSize: 64
              masterConnectionMinimumIdleSize: 24
              masterConnectionPoolSize: 64
              readMode: "SLAVE"
              subscriptionMode: "SLAVE"
              nodeAddresses:
              - "redis://127.0.0.1:7004"
              - "redis://127.0.0.1:7001"
              - "redis://127.0.0.1:7000"
              scanInterval: 1000
              pingConnectionInterval: 0
              keepAlive: false
              tcpNoDelay: false
            threads: 16
            nettyThreads: 32
            codec: !<org.redisson.codec.Kryo5Codec> {}
            transportMode: "NIO"
    
  3. Available Spring Beans:

    • RedissonClient
    • RedissonRxClient
    • RedissonReactiveClient
    • RedisTemplate
    • ReactiveRedisTemplate
    • ReactiveRedisOperations

FAQ

Q: How to replace Netty version brought by Spring Boot?

You need to define netty version in properties section of your Maven project.

    <properties>
          <netty.version>4.2.9.Final</netty.version> 
    </properties>

Q: How to disable Redisson?

You may not have Redis or Valkey in some environments. In this case Redisson can be disabled:

  • Using Annotations
    Spring Boot 4.0+
    @SpringBootApplication
    @EnableAutoConfiguration(exclude = {
        RedissonAutoConfigurationV4.class})
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
    Spring Boot 2.7+
    ```java
    @SpringBootApplication
    @EnableAutoConfiguration(exclude = {
        RedissonAutoConfigurationV2.class})
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
    Spring Boot up to 2.6
    @SpringBootApplication
    @EnableAutoConfiguration(exclude = {
        RedissonAutoConfiguration.class})
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
  • Using application.yml file
    Spring Boot 4.0+
    spring:
      autoconfigure:
        exclude:
          - org.redisson.spring.starter.RedissonAutoConfigurationV4
    
    Spring Boot 2.7+
    spring:
      autoconfigure:
        exclude:
          - org.redisson.spring.starter.RedissonAutoConfigurationV2
    
    Spring Boot up to 2.6
    spring:
      autoconfigure:
        exclude:
          - org.redisson.spring.starter.RedissonAutoConfiguration
    

Spring Cache

Redisson provides various Spring Cache implementations.

Eviction, local cache and data partitioning

Redisson provides various Spring Cache managers with multiple important features:

  1. Local cache

    So called near cache used to speed up read operations and avoid network roundtrips. It caches Map entries on Redisson side and executes read operations up to 45x faster in comparison with common implementation. Local cache instances with the same name connected to the same pub/sub channel. This channel is used for exchanging of update/invalidate events between all instances. Local cache store doesn't use hashCode()/equals() methods of key object, instead it uses hash of serialized state.

  2. Data partitioning

    Although Map object is cluster compatible its content isn't scaled/partitioned across multiple Redis or Valkey master nodes in cluster. Data partitioning allows to scale available memory, read/write operations and entry eviction process for individual Map instance in cluster.

  3. Scripted eviction

    Allows to define time to live or max idle time parameters per map entry. Eviction is done on Redisson side through a custom scheduled task which removes expired entries using Lua script. Eviction task is started once per unique object name at the moment of getting Map instance. If instance isn't used and has expired entries it should be get again to start the eviction process. This leads to extra Redis or Valkey calls and eviction task per unique map object name.

    Entries are cleaned time to time by org.redisson.eviction.EvictionScheduler. By default, it removes 100 expired entries at a time. This can be changed through cleanUpKeysAmount setting. Task launch time tuned automatically and depends on expired entries amount deleted in previous time and varies between 5 second to 30 minutes by default. This time interval can be changed through minCleanUpDelay and maxCleanUpDelay. For example, if clean task deletes 100 entries each time it will be executed every 5 seconds (minimum execution delay). But if current expired entries amount is lower than previous one then execution delay will be increased by 1.5 times and decreased otherwise.

    Available implementations:

    Class name Local
    cache
    Data
    partitioning
    Ultra-fast
    read/write
    RedissonSpringCacheManager
    open-source version
    RedissonSpringCacheManager
    Redisson PRO version
    ✔️
    RedissonSpringLocalCachedCacheManager
    available only in Redisson PRO
    ✔️ ✔️
    RedissonClusteredSpringCacheManager
    available only in Redisson PRO
    ✔️ ✔️
    RedissonClusteredSpringLocalCachedCacheManager
    available only in Redisson PRO
    ✔️ ✔️ ✔️
  4. Advanced eviction

    Allows to define time to live parameter per map entry. Doesn't use an entry eviction task, entries are cleaned on Redis or Valkey side.

    Available implementations:

    Class name Local
    cache
    Data
    partitioning
    Ultra-fast
    read/write
    RedissonSpringCacheV2Manager
    available only in Redisson PRO
    ✔️ ✔️
    RedissonSpringLocalCachedCacheV2Manager
    available only in Redisson PRO
    ✔️ ✔️ ✔️
  5. Native eviction

    Allows to define time to live parameter per map entry. Doesn't use an entry eviction task, entries are cleaned on Redis side.
    Requires Valkey 9.0+ or Redis 7.4+.

    Available implementations:

    Class name Local
    cache
    Data
    partitioning
    Ultra-fast
    read/write
    RedissonSpringCacheNativeManager
    open-source version
    RedissonSpringCacheNativeManager
    Redisson PRO version
    ✔️
    RedissonSpringLocalCachedCacheNativeManager
    available only in Redisson PRO
    ✔️ ✔️
    RedissonClusteredSpringCacheNativeManager
    available only in Redisson PRO
    ✔️ ✔️
    RedissonClusteredSpringLocalCachedCacheNativeManager
    available only in Redisson PRO
    ✔️ ✔️ ✔️

Local cache options

Follow options object can be supplied during local cached managers initialization:

LocalCachedMapOptions options = LocalCachedMapOptions.defaults()

// Defines whether to store a cache miss into the local cache.
// Default value is false.
.storeCacheMiss(false);

// Defines store mode of cache data.
// Follow options are available:
// LOCALCACHE - store data in local cache only.
// LOCALCACHE_REDIS - store data in both Redis or Valkey and local cache.
.storeMode(StoreMode.LOCALCACHE_REDIS)

// Defines Cache provider used as local cache store.
// Follow options are available:
// REDISSON - uses Redisson own implementation
// CAFFEINE - uses Caffeine implementation
.cacheProvider(CacheProvider.REDISSON)

 // Defines local cache eviction policy.
 // Follow options are available:
 // LFU - Counts how often an item was requested. Those that are used least often are discarded first.
 // LRU - Discards the least recently used items first
 // SOFT - Uses weak references, entries are removed by GC
 // WEAK - Uses soft references, entries are removed by GC
 // NONE - No eviction
.evictionPolicy(EvictionPolicy.NONE)

 // If cache size is 0 then local cache is unbounded.
.cacheSize(1000)

 // Used to load missed updates during any connection failures to Redis. 
 // Since, local cache updates can't be get in absence of connection to Redis. 
 // Follow reconnection strategies are available:
 // CLEAR - Clear local cache if map instance has been disconnected for a while.
 // LOAD - Store invalidated entry hash in invalidation log for 10 minutes
 //        Cache keys for stored invalidated entry hashes will be removed 
 //        if LocalCachedMap instance has been disconnected less than 10 minutes
 //        or whole cache will be cleaned otherwise.
 // NONE - Default. No reconnection handling
.reconnectionStrategy(ReconnectionStrategy.NONE)

 // Used to synchronize local cache changes.
 // Follow sync strategies are available:
 // INVALIDATE - Default. Invalidate cache entry across all LocalCachedMap instances on map entry change
 // UPDATE - Insert/update cache entry across all LocalCachedMap instances on map entry change
 // NONE - No synchronizations on map changes
.syncStrategy(SyncStrategy.INVALIDATE)

// time to live for each entry in local cache
.timeToLive(Duration.ofSeconds(10))

// max idle time for each entry in local cache
.maxIdle(Duration.ofSeconds(10));

// Defines how to listen expired event sent by Redis or Valkey upon this instance deletion
//
// Follow expiration policies are available:
// DONT_SUBSCRIBE - Don't subscribe on expire event
// SUBSCRIBE_WITH_KEYEVENT_PATTERN - Subscribe on expire event using `__keyevent@*:expired` pattern
// SUBSCRIBE_WITH_KEYSPACE_CHANNEL - Subscribe on expire event using `__keyspace@N__:name` channel
.expirationEventPolicy(ExpirationEventPolicy.SUBSCRIBE_WITH_KEYEVENT_PATTERN)

Usage

  1. Add redisson-spring-cache dependency into your project:

    • Redisson PRO

      Maven

      <dependency>
          <groupId>pro.redisson</groupId>
          <artifactId>redisson-spring-cache</artifactId>
          <version>xVERSIONx</version>
      </dependency>
      

      Gradle

      compile 'pro.redisson:redisson-spring-cache:xVERSIONx'
      

      License key configuration

    • Community Edition

      Maven

      <dependency>
          <groupId>org.redisson</groupId>
          <artifactId>redisson-spring-cache</artifactId>
          <version>xVERSIONx</version>
      </dependency>
      

      Gradle

      compile 'org.redisson:redisson-spring-cache:xVERSIONx'
      

    Redisson PRO vs. Community Edition ➜

  2. Create Spring Cache Manager instance

    Each Spring Cache Manager instance has two important parameters: ttl and maxIdleTime and stores data infinitely if they are not defined or equal to 0.

    Complete config example:

    @Configuration
    @ComponentScan
    @EnableCaching
    public static class Application {
    
        @Bean(destroyMethod="shutdown")
        RedissonClient redisson() throws IOException {
            Config config = new Config();
            config.useClusterServers()
                  .addNodeAddress("redis://127.0.0.1:7004", "redis://127.0.0.1:7001");
            return Redisson.create(config);
        }
    
        @Bean
        CacheManager cacheManager(RedissonClient redissonClient) {
            Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
    
            // define local cache settings for "testMap" cache.
            // ttl = 48 minutes and maxIdleTime = 24 minutes for local cache entries
            LocalCachedMapOptions options = LocalCachedMapOptions.defaults()
                .evictionPolicy(EvictionPolicy.LFU)
                .timeToLive(48, TimeUnit.MINUTES)
                .maxIdle(24, TimeUnit.MINUTES)
                .cacheSize(1000);
    
            // create "testMap" Redis or Valkey cache with ttl = 24 minutes and maxIdleTime = 12 minutes
            LocalCachedCacheConfig cfg = new LocalCachedCacheConfig(24*60*1000, 12*60*1000, options);
            // Max size of map stored in Redis
            cfg.setMaxSize(2000);
            config.put("testMap", cfg);
    
            // scripted eviction
            return new RedissonSpringCacheManager(redissonClient, config);
    
            // native eviction
            return new RedissonSpringCacheManager(redissonClient, config);
    
            // data partitioning + scripted eviction
            return new RedissonClusteredSpringCacheManager(redissonClient, config);
    
            // data partitioning + advanced eviction
            return new RedissonSpringCacheV2Manager(redissonClient, config);
    
            // data partitioning + native eviction
            return new RedissonClusteredSpringCacheNativeManager(redissonClient, config);
    
            // local cache + scripted eviction
            return new RedissonSpringLocalCachedCacheManager(redissonClient, config);
    
            // local cache + native eviction
            return new RedissonSpringLocalCachedCacheNativeManager(redissonClient, config);
    
            // local cache + data partitioning + native eviction
            return new RedissonClusteredSpringLocalCachedCacheNativeManager(redissonClient, config);
    
            // local cache + data partitioning + advanced eviction
            return new RedissonSpringLocalCachedCacheV2Manager(redissonClient, config);
    
            // local cache + data partitioning + scripted eviction
            return new RedissonClusteredSpringLocalCachedCacheManager(redissonClient, config);
        }
    
    }
    

    Cache configuration could be read from YAML configuration files:

        @Configuration
        @ComponentScan
        @EnableCaching
        public static class Application {
    
            @Bean(destroyMethod="shutdown")
            RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
                Config config = Config.fromYAML(configFile.getInputStream());
                return Redisson.create(config);
            }
    
            @Bean
            CacheManager cacheManager(RedissonClient redissonClient) throws IOException {
                // scripted eviction
                return new RedissonSpringCacheManager(redissonClient, "classpath:/cache-config.yaml");
    
                // native eviction
                return new RedissonSpringCacheManager(redissonClient, "classpath:/cache-config.yaml");
    
                // data partitioning + scripted eviction
                return new RedissonClusteredSpringCacheManager(redissonClient, "classpath:/cache-config.yaml");
    
                // data partitioning + advanced eviction
                return new RedissonSpringCacheV2Manager(redissonClient, "classpath:/cache-config.yaml");
    
                // data partitioning + native eviction
                return new RedissonClusteredSpringCacheNativeManager(redissonClient, "classpath:/cache-config.yaml");
    
                // local cache + scripted eviction
                return new RedissonSpringLocalCachedCacheManager(redissonClient, "classpath:/cache-config.yaml");
    
                // local cache + native eviction
                return new RedissonSpringLocalCachedCacheNativeManager(redissonClient, "classpath:/cache-config.yaml");
    
                // local cache + data partitioning + native eviction
                return new RedissonClusteredSpringLocalCachedCacheNativeManager(redissonClient, "classpath:/cache-config.yaml");
    
                // local cache + data partitioning + advanced eviction
                return new RedissonSpringLocalCachedCacheV2Manager(redissonClient, "classpath:/cache-config.yaml");
    
                // local cache + data partitioning + scripted eviction
                return new RedissonClusteredSpringLocalCachedCacheManager(redissonClient, "classpath:/cache-config.yaml");
            }
    
        }
    

YAML config format

Below is the configuration of Spring Cache with name testMap in YAML format:

---
testMap:
  ttl: 1440000
  maxIdleTime: 720000
  localCacheOptions:
    invalidationPolicy: "ON_CHANGE"
    evictionPolicy: "NONE"
    cacheSize: 0
    timeToLiveInMillis: 0
    maxIdleInMillis: 0

Note

localCacheOptions settings are available for RedissonSpringLocalCachedCacheManager, RedissonClusteredSpringLocalCachedCacheManager, RedissonSpringLocalCachedCacheV2Manager, RedissonSpringLocalCachedCacheNativeManager, RedissonClusteredSpringLocalCachedCacheNativeManager classes only.

Spring Session

Redisson integrates with Spring Session by providing RedissonConnectionFactory, which implements Spring Data Redis's RedisConnectionFactory and ReactiveRedisConnectionFactory interfaces. This allows Spring Session to use Redisson as the underlying Valkey or Redis client for session storage and retrieval.

Dependencies

Ensure you have Spring Session library in your classpath, add it if necessary:

  1. Add Spring Session Data Redis library in classpath:
    Maven:
    <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-data-redis</artifactId>
      <version>4.0.0</version>
    </dependency>
    
    Gradle:
    compile 'org.springframework.session:spring-session-data-redis:4.0.0'  
    
  2. Add Redisson Spring Data Redis library in classpath:

    • Redisson PRO

      Maven

      <dependency>
         <groupId>pro.redisson</groupId>
         <artifactId>redisson-spring-data-40</artifactId>
         <version>4.1.0</version>
      </dependency>
      

      Gradle

      compile 'pro.redisson:redisson-spring-data-40:4.1.0'
      

      License key configuration

    • Community Edition

      Maven

      <dependency>
         <groupId>org.redisson</groupId>
         <artifactId>redisson-spring-data-40</artifactId>
         <version>4.1.0</version>
      </dependency>
      

      Gradle

      compile 'org.redisson:redisson-spring-data-40:4.1.0'
      

    Redisson PRO vs. Community Edition ➜

Note

Valkey or Redis notify-keyspace-events setting should contain Exg letters to make Spring Session integration work.

Spring Http Session configuration

Add configuration class which extends AbstractHttpSessionApplicationInitializer class:

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer { 

     @Bean
     public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
         return new RedissonConnectionFactory(redisson);
     }

     @Bean(destroyMethod = "shutdown")
     public RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
        Config config = Config.fromYAML(configFile.getInputStream());
        return Redisson.create(config);
     }

}

Spring WebFlux’s Session configuration

Add configuration class which extends AbstractReactiveWebInitializer class:

@Configuration
@EnableRedisWebSession
public class SessionConfig extends AbstractReactiveWebInitializer { 

     @Bean
     public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
         return new RedissonConnectionFactory(redisson);
     }

     @Bean(destroyMethod = "shutdown")
     public RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
        Config config = Config.fromYAML(configFile.getInputStream());
        return Redisson.create(config);
     }
}

Spring Boot configuration

  1. Add Redisson Spring Boot Starter module.

  2. Define the following properties in Spring Boot settings:

    spring.session.store-type=redis
    spring.redis.redisson.file=classpath:redisson.yaml
    spring.session.timeout.seconds=900
    

Local Cache

This feature is available only in Redisson PRO edition.

Redisson PRO provides local caching implementation for Spring Session.

local cache - a so-called near cache used to speed up read operations and avoid network roundtrips. It caches the whole Spring Session on the Redisson side and then uses the cached copy instead of loading it on each request.getSession() method access. The cached Session is updated/removed via pub/sub notifications.

To utilize this feature follow the steps below.

  1. Add Redisson Spring Session library in classpath.

    Maven

    <dependency>
       <groupId>pro.redisson</groupId>
       <!-- for Spring Session v2.x.x - v2.1.x -->
       <artifactId>redisson-spring-session-20</artifactId>
       <!-- for Spring Session v2.2.x - v2.7.x -->
       <artifactId>redisson-spring-session-22</artifactId>
       <!-- for Spring Session v3.x.x - v4.x.x -->
       <artifactId>redisson-spring-session-30</artifactId>
       <version>4.1.0</version>
    </dependency>
    

    Gradle

    // for Spring Session v2.x.x - v2.1.x
    compile 'pro.redisson:redisson-spring-session-20:4.1.0'
    // for Spring Session v2.2.x - v2.7.x
    compile 'pro.redisson:redisson-spring-session-22:4.1.0'
    // for Spring Session v3.x.x - v4.x.x
    compile 'pro.redisson:redisson-spring-session-30:4.1.0'
    
  2. Define configuration with @EnableLocalCachedRedisSession annotation

    @Configuration
    @EnableLocalCachedRedisSession
    public class SessionConfig extends AbstractHttpSessionApplicationInitializer { 
    
        @Bean
        public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
            return new RedissonConnectionFactory(redisson);
        }
    
        @Bean(destroyMethod = "shutdown")
        public RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
           Config config = Config.fromYAML(configFile.getInputStream());
           return Redisson.create(config);
        }
    
    }
    

    Configuration Settings

    The @EnableLocalCachedRedisSession annotation provides the following configuration settings:

    • maxInactiveIntervalInSeconds - Specifies the maximum time, in seconds, that a session can remain idle before it expires. Default is 1800.

    • redisNamespace - Specifies a custom namespace for Redis keys to enable session isolation across multiple applications. The namespace changes the Redis key prefix from the default spring:session: to <redisNamespace>:. This allows multiple applications to share the same Redis instance while maintaining separate session storage. Default is "spring:session".

    • redisFlushMode - Specifies when session changes are written to Redis. Default is FlushMode.ON_SAVE. Available modes:

      • FlushMode.ON_SAVE (default) - Session changes are written to Redis only when SessionRepository.save(Session) is explicitly invoked. In web applications, this occurs automatically just before the HTTP response is committed. This mode offers better performance by batching updates.
      • FlushMode.IMMEDIATE - Session changes are written to Redis immediately as they occur. Use this mode when session data must be immediately visible across multiple application instances, though it may impact performance.
    • cleanupCron - Specifies the cron expression for scheduling the expired session cleanup task. Default is "0 * * * * *".

    • broadcastSessionUpdates - Specifies whether session updates should be broadcast to other application instances. When enabled, session attribute changes are published to Redis pub/sub channels, allowing other application instances to update their local caches. This ensures session consistency across a distributed deployment. Disable this feature if you have a single application instance or do not require real-time session synchronization across instances, which can reduce Redis network traffic. Default is true.

Spring Transaction Manager

Redisson provides implementation of both org.springframework.transaction.PlatformTransactionManager and org.springframework.transaction.ReactiveTransactionManager interfaces to participant in Spring transactions. See also Transactions section.

Add redisson-spring-transaction dependency into your project:

  • Redisson PRO

    Maven

    <dependency>
       <groupId>pro.redisson</groupId>
       <artifactId>redisson-spring-transaction</artifactId>
       <version>4.1.0</version>
    </dependency>
    

    Gradle

    compile 'pro.redisson:redisson-spring-transaction:4.1.0'
    
  • Community Edition

    Maven

    <dependency>
       <groupId>org.redisson</groupId>
       <artifactId>redisson-spring-transaction</artifactId>
       <version>4.1.0</version>
    </dependency>
    

    Gradle

    compile 'org.redisson:redisson-spring-transaction:4.1.0'
    

Redisson PRO vs. Community Edition ➜

Spring Transaction Management

@Configuration
@EnableTransactionManagement
public class RedissonTransactionContextConfig {

    @Bean
    public TransactionalBean transactionBean() {
        return new TransactionalBean();
    }

    @Bean
    public RedissonTransactionManager transactionManager(RedissonClient redisson) {
        return new RedissonTransactionManager(redisson);
    }

    @Bean(destroyMethod="shutdown")
    public RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
         Config config = Config.fromYAML(configFile.getInputStream());
        return Redisson.create(config);
    }

}


public class TransactionalBean {

    @Autowired
    private RedissonTransactionManager transactionManager;

    @Transactional
    public void commitData() {
        RTransaction transaction = transactionManager.getCurrentTransaction();
        RMap<String, String> map = transaction.getMap("test1");
        map.put("1", "2");
    }

}

Reactive Spring Transaction Management

@Configuration
@EnableTransactionManagement
public class RedissonReactiveTransactionContextConfig {

    @Bean
    public TransactionalBean transactionBean() {
        return new TransactionalBean();
    }

    @Bean
    public ReactiveRedissonTransactionManager transactionManager(RedissonReactiveClient redisson) {
        return new ReactiveRedissonTransactionManager(redisson);
    }

    @Bean(destroyMethod="shutdown")
    public RedissonReactiveClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
         Config config = Config.fromYAML(configFile.getInputStream());
        return Redisson.createReactive(config);
    }

}

public class TransactionalBean {

    @Autowired
    private ReactiveRedissonTransactionManager transactionManager;

    @Transactional
    public Mono<Void> commitData() {
        Mono<RTransactionReactive> transaction = transactionManager.getCurrentTransaction();
        return transaction.flatMap(t -> {
            RMapReactive<String, String> map = t.getMap("test1");
            return map.put("1", "2");
        }).then();
    }

}

Spring Cloud Stream

This feature is available only in Redisson PRO edition.

Redisson implements Spring Cloud Stream Binder based on Valkey or Redis using the Reliable Queue for messages delivery.

Compatible with Spring versions below.

Spring Cloud Stream Spring Cloud Spring Boot
5.0.x 2025.1.x 4.0.x
4.3.x 2025.0.x 3.5.x
4.2.x 2024.0.x 3.4.x
4.1.x 2023.0.x 3.0.x - 3.3.x
4.0.x 2022.0.x 3.0.x - 3.3.x
3.2.x 2021.0.x 2.6.x, 2.7.x (Starting with 2021.0.3 of Spring Cloud)
3.1.x 2020.0.x 2.4.x, 2.5.x (Starting with 2020.0.3 of Spring Cloud)

To use binder with Redisson you need to add Spring Cloud Stream Binder library in classpath:

Maven:

<dependency>
    <groupId>pro.redisson</groupId>
    <artifactId>spring-cloud-stream-binder-redisson</artifactId>
    <version>4.1.0</version>
</dependency>
Gradle:
compile 'pro.redisson:spring-cloud-stream-binder-redisson:4.1.0'  

Receiving messages

Register the input binder (an event sink) for receiving messages as follows:

@Bean
public Consumer<MyObject> receiveMessage() {
  return obj -> {
     // consume received object ...
  };
}

Define channel id in the configuration file application.properties.

Consumer settings:

  • pollBatchSize - Sets the maximum number of messages to retrieve in a single poll operation. Default value is 10.

  • visibilityTimeout - Sets the visibility timeout for retrieved messages. The time period during which a message is invisible to other consumers after being retrieved. This prevents duplicate processing and allows the message to reappear in the queue if it wasn't acknowledged during that timeout. Default value is 30 seconds.

  • negativeAcknowledgeDelay - Specifies the delay duration before a message handled with an exception is eligible for redelivery. Default value is 15 seconds.

Example for receiveMessage bean defined above connected to my-channel channel:

spring.cloud.stream.bindings.receiveMessage-in-0.destination=my-channel
spring.cloud.stream.redisson.bindings.receiveMessage-in-0.consumer.pollBatchSize=15
spring.cloud.stream.redisson.bindings.receiveMessage-in-0.consumer.visibilityTimeout=60s

YAML configuration:

spring:
  cloud:
    stream:
      bindings:
        receiveMessage-in-0:
          destination: my-channel
      redisson:
        bindings:
          receiveMessage-in-0:
            consumer:
              pollBatchSize: 15
              visibilityTimeout: 60s

Publishing messages

  • Publish messages using an output binder

    Register the output binder (an event source) for publishing messages as follows:

    @Bean
    public Supplier<MyObject> feedSupplier() {
        return () -> {
               // ...
               return new MyObject();
        };
    }
    
  • Publish messages using org.springframework.cloud.stream.function.StreamBridge object

    StreamBridge bridge;
    
    bridge.send("feedSupplier-out-0", new MyObject());
    

Define channel id in the configuration file application.properties. Example for feedSupplier bean defined above connected to my-channel channel:

spring.cloud.stream.bindings.feedSupplier-out-0.destination=my-channel
spring.cloud.stream.bindings.feedSupplier-out-0.producer.useNativeEncoding=true

YAML configuration:

spring:
  cloud:
    stream:
      bindings:
        feedSupplier-out-0:
          destination: my-channel
          producer:
            useNativeEncoding: true

Spring Data Redis

Redisson implements RedisConnectionFactory and ReactiveRedisConnectionFactory interfaces from Spring Data Redis module, allowing usage of RedisTemplate, ReactiveRedisTemplate or ReactiveRedisOperations objects.

Usage

  1. Add redisson-spring-data dependency into your project:

    • Redisson PRO

      Maven

      <dependency>
          <groupId>pro.redisson</groupId>
          <!-- for Spring Data Redis v.1.6.x -->
          <artifactId>redisson-spring-data-16</artifactId>
          <!-- for Spring Data Redis v.1.7.x -->
          <artifactId>redisson-spring-data-17</artifactId>
          <!-- for Spring Data Redis v.1.8.x -->
          <artifactId>redisson-spring-data-18</artifactId>
          <!-- for Spring Data Redis v.2.0.x -->
          <artifactId>redisson-spring-data-20</artifactId>
          <!-- for Spring Data Redis v.2.1.x -->
          <artifactId>redisson-spring-data-21</artifactId>
          <!-- for Spring Data Redis v.2.2.x -->
          <artifactId>redisson-spring-data-22</artifactId>
          <!-- for Spring Data Redis v.2.3.x -->
          <artifactId>redisson-spring-data-23</artifactId>
          <!-- for Spring Data Redis v.2.4.x -->
          <artifactId>redisson-spring-data-24</artifactId>
          <!-- for Spring Data Redis v.2.5.x -->
          <artifactId>redisson-spring-data-25</artifactId>
          <!-- for Spring Data Redis v.2.6.x -->
          <artifactId>redisson-spring-data-26</artifactId>
          <!-- for Spring Data Redis v.2.7.x -->
          <artifactId>redisson-spring-data-27</artifactId>
          <!-- for Spring Data Redis v.3.0.x -->
          <artifactId>redisson-spring-data-30</artifactId>
          <!-- for Spring Data Redis v.3.1.x -->
          <artifactId>redisson-spring-data-31</artifactId>
          <!-- for Spring Data Redis v.3.2.x -->
          <artifactId>redisson-spring-data-32</artifactId>
          <!-- for Spring Data Redis v.3.3.x -->
          <artifactId>redisson-spring-data-33</artifactId>
          <!-- for Spring Data Redis v.3.4.x -->
          <artifactId>redisson-spring-data-34</artifactId>
          <!-- for Spring Data Redis v.3.5.x -->
          <artifactId>redisson-spring-data-35</artifactId>
          <!-- for Spring Data Redis v.4.0.x -->
          <artifactId>redisson-spring-data-40</artifactId>
          <version>4.1.0</version>
      </dependency>
      

      Gradle

      // for Spring Data Redis v.1.6.x
      compile 'pro.redisson:redisson-spring-data-16:4.1.0'
      // for Spring Data Redis v.1.7.x
      compile 'pro.redisson:redisson-spring-data-17:4.1.0'
      // for Spring Data Redis v.1.8.x
      compile 'pro.redisson:redisson-spring-data-18:4.1.0'
      // for Spring Data Redis v.2.0.x
      compile 'pro.redisson:redisson-spring-data-20:4.1.0'
      // for Spring Data Redis v.2.1.x
      compile 'pro.redisson:redisson-spring-data-21:4.1.0'
      // for Spring Data Redis v.2.2.x
      compile 'pro.redisson:redisson-spring-data-22:4.1.0'
      // for Spring Data Redis v.2.3.x
      compile 'pro.redisson:redisson-spring-data-23:4.1.0'
      // for Spring Data Redis v.2.4.x
      compile 'pro.redisson:redisson-spring-data-24:4.1.0'
      // for Spring Data Redis v.2.5.x
      compile 'pro.redisson:redisson-spring-data-25:4.1.0'
      // for Spring Data Redis v.2.6.x
      compile 'pro.redisson:redisson-spring-data-26:4.1.0'
      // for Spring Data Redis v.2.7.x
      compile 'pro.redisson:redisson-spring-data-27:4.1.0'
      // for Spring Data Redis v.3.0.x
      compile 'pro.redisson:redisson-spring-data-30:4.1.0'
      // for Spring Data Redis v.3.1.x
      compile 'pro.redisson:redisson-spring-data-31:4.1.0'
      // for Spring Data Redis v.3.2.x
      compile 'pro.redisson:redisson-spring-data-32:4.1.0'
      // for Spring Data Redis v.3.3.x
      compile 'pro.redisson:redisson-spring-data-33:4.1.0'
      // for Spring Data Redis v.3.4.x
      compile 'pro.redisson:redisson-spring-data-34:4.1.0'
      // for Spring Data Redis v.3.5.x
      compile 'pro.redisson:redisson-spring-data-35:4.1.0'
      // for Spring Data Redis v.4.0.x
      compile 'pro.redisson:redisson-spring-data-40:4.1.0'
      

      License key configuration

    • Community Edition

      Maven

      <dependency>
          <groupId>org.redisson</groupId>
          <!-- for Spring Data Redis v.1.6.x -->
          <artifactId>redisson-spring-data-16</artifactId>
          <!-- for Spring Data Redis v.1.7.x -->
          <artifactId>redisson-spring-data-17</artifactId>
          <!-- for Spring Data Redis v.1.8.x -->
          <artifactId>redisson-spring-data-18</artifactId>
          <!-- for Spring Data Redis v.2.0.x -->
          <artifactId>redisson-spring-data-20</artifactId>
          <!-- for Spring Data Redis v.2.1.x -->
          <artifactId>redisson-spring-data-21</artifactId>
          <!-- for Spring Data Redis v.2.2.x -->
          <artifactId>redisson-spring-data-22</artifactId>
          <!-- for Spring Data Redis v.2.3.x -->
          <artifactId>redisson-spring-data-23</artifactId>
          <!-- for Spring Data Redis v.2.4.x -->
          <artifactId>redisson-spring-data-24</artifactId>
          <!-- for Spring Data Redis v.2.5.x -->
          <artifactId>redisson-spring-data-25</artifactId>
          <!-- for Spring Data Redis v.2.6.x -->
          <artifactId>redisson-spring-data-26</artifactId>
          <!-- for Spring Data Redis v.2.7.x -->
          <artifactId>redisson-spring-data-27</artifactId>
          <!-- for Spring Data Redis v.3.0.x -->
          <artifactId>redisson-spring-data-30</artifactId>
          <!-- for Spring Data Redis v.3.1.x -->
          <artifactId>redisson-spring-data-31</artifactId>
          <!-- for Spring Data Redis v.3.2.x -->
          <artifactId>redisson-spring-data-32</artifactId>
          <!-- for Spring Data Redis v.3.3.x -->
          <artifactId>redisson-spring-data-33</artifactId>
          <!-- for Spring Data Redis v.3.4.x -->
          <artifactId>redisson-spring-data-34</artifactId>
          <!-- for Spring Data Redis v.3.5.x -->
          <artifactId>redisson-spring-data-35</artifactId>
          <!-- for Spring Data Redis v.4.0.x -->
          <artifactId>redisson-spring-data-40</artifactId>
          <version>4.1.0</version>
      </dependency>
      

      Gradle

      // for Spring Data Redis v.1.6.x
      compile 'org.redisson:redisson-spring-data-16:4.1.0'
      // for Spring Data Redis v.1.7.x
      compile 'org.redisson:redisson-spring-data-17:4.1.0'
      // for Spring Data Redis v.1.8.x
      compile 'org.redisson:redisson-spring-data-18:4.1.0'
      // for Spring Data Redis v.2.0.x
      compile 'org.redisson:redisson-spring-data-20:4.1.0'
      // for Spring Data Redis v.2.1.x
      compile 'org.redisson:redisson-spring-data-21:4.1.0'
      // for Spring Data Redis v.2.2.x
      compile 'org.redisson:redisson-spring-data-22:4.1.0'
      // for Spring Data Redis v.2.3.x
      compile 'org.redisson:redisson-spring-data-23:4.1.0'
      // for Spring Data Redis v.2.4.x
      compile 'org.redisson:redisson-spring-data-24:4.1.0'
      // for Spring Data Redis v.2.5.x
      compile 'org.redisson:redisson-spring-data-25:4.1.0'
      // for Spring Data Redis v.2.6.x
      compile 'org.redisson:redisson-spring-data-26:4.1.0'
      // for Spring Data Redis v.2.7.x
      compile 'org.redisson:redisson-spring-data-27:4.1.0'
      // for Spring Data Redis v.3.0.x
      compile 'org.redisson:redisson-spring-data-30:4.1.0'
      // for Spring Data Redis v.3.1.x
      compile 'org.redisson:redisson-spring-data-31:4.1.0'
      // for Spring Data Redis v.3.2.x
      compile 'org.redisson:redisson-spring-data-32:4.1.0'
      // for Spring Data Redis v.3.3.x
      compile 'org.redisson:redisson-spring-data-33:4.1.0'
      // for Spring Data Redis v.3.4.x
      compile 'org.redisson:redisson-spring-data-34:4.1.0'
      // for Spring Data Redis v.3.5.x
      compile 'org.redisson:redisson-spring-data-35:4.1.0'
      // for Spring Data Redis v.4.0.x
      compile 'org.redisson:redisson-spring-data-40:4.1.0'
      

    Redisson PRO vs. Community Edition ➜

  2. Register RedissonConnectionFactory in Spring context:

    @Configuration
    public class RedissonSpringDataConfig {
    
       @Bean
       public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
           return new RedissonConnectionFactory(redisson);
       }
    
       @Bean(destroyMethod = "shutdown")
       public RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
           Config config = Config.fromYAML(configFile.getInputStream());
           return Redisson.create(config);
       }
    
    }
    

Spring AI Vector Store

This feature is available only in Redisson PRO edition.

Redisson provides Spring AI Vector Store implementation for building AI-powered applications with Retrieval Augmented Generation (RAG) capabilities. The implementation leverages Redis Stack with RediSearch and RedisJSON modules to store and query vector embeddings.

The store uses Redis JSON documents to persist vector embeddings along with their associated document content and metadata. It leverages RediSearch for creating and querying vector similarity indexes.

Features:

  • Vector similarity search using KNN (K-Nearest Neighbors)
  • Support for HNSW and FLAT vector indexing algorithms
  • Multiple distance metrics: COSINE, L2 (Euclidean), Inner Product
  • Configurable metadata fields (TEXT, TAG, NUMERIC) for advanced filtering
  • Automatic schema initialization
  • Portable filter expressions
  • Batch processing support

Prerequisites

  1. Redis Stack or Redis 8.4+ instance with RediSearch and RedisJSON modules

  2. EmbeddingModel instance to compute the document embeddings. Several options are available:

Usage

1. Add dependency into your project

Spring Boot Starter (recommended)

For Spring Boot applications with auto-configuration support:

Maven

<dependency>
    <groupId>pro.redisson</groupId>
    <artifactId>redisson-spring-ai-store-starter-10</artifactId>
    <version>xVERSIONx</version>
</dependency>

Gradle

compile 'pro.redisson:redisson-spring-ai-store-starter-10:xVERSIONx'

Store Implementation Only

For manual configuration or non-Spring Boot applications:

Maven

<dependency>
    <groupId>pro.redisson</groupId>
    <artifactId>redisson-spring-ai-store-10</artifactId>
    <version>xVERSIONx</version>
</dependency>

Gradle

compile 'pro.redisson:redisson-spring-ai-store-10:xVERSIONx'

License key configuration

2. Add settings into application.yaml file

spring:
  ai:
    vectorstore:
      redisson:
        index-name: my-index
        prefix: doc:
        initialize-schema: true
        vector-algorithm: HNSW
        distance-metric: COSINE
        hnsw:
          m: 16
          ef-construction: 200
          ef-runtime: 10
        metadata-fields:
          - name: category
            type: TAG
          - name: year
            type: NUMERIC

3. Use VectorStore in your application

@Autowired 
VectorStore vectorStore;

// ...

List<Document> documents = List.of(
    new Document("Spring AI rocks!! Spring AI rocks!!", Map.of("category", "framework", "year", 2024)),
    new Document("The World is Big and Salvation Lurks Around the Corner"),
    new Document("You walk forward facing the past and you turn back toward the future.", Map.of("category", "philosophy", "year", 2023)));

// Add the documents to Redis
vectorStore.add(documents);

// Retrieve documents similar to a query
List<Document> results = vectorStore.similaritySearch(
    SearchRequest.builder()
        .query("Spring")
        .topK(5)
        .build());

Configuration

Properties starting with spring.ai.vectorstore.redisson.* are used to configure the Vector Store:

Property Description Default Value
spring.ai.vectorstore.redisson.index-name Name of the Redis search index spring-ai-index
spring.ai.vectorstore.redisson.prefix Prefix for Redis keys embedding:
spring.ai.vectorstore.redisson.initialize-schema Whether to initialize the required schema false
spring.ai.vectorstore.redisson.vector-algorithm Vector indexing algorithm (HNSW or FLAT) HNSW
spring.ai.vectorstore.redisson.distance-metric Distance metric (COSINE, L2, or IP) COSINE

The initialize-schema property must be set to true for automatic index creation. This is a breaking change from earlier Spring AI versions where schema initialization happened by default.

Vector Algorithms

  • HNSW

    Hierarchical Navigable Small World - default algorithm that provides better search performance with slightly higher memory usage. Recommended for most use cases.

    • m - Controls the number of bi-directional links created for each node. Higher values improve recall but increase memory usage. Recommended range: 12-48.
    • ef-construction - Determines search width during index building. Higher values create higher quality indexes at the cost of longer construction time. Should be at least 2 * m. Recommended range: 100-500.
    • ef-runtime - Controls search precision at query time. Higher values improve recall but increase query latency. Recommended range: 10-100.
  • FLAT

    Brute force algorithm that provides exact results but slower performance for large datasets. Use when exact accuracy is required and dataset size is small.

HNSW Algorithm Parameters:

Property Description Default Value
spring.ai.vectorstore.redisson.hnsw.m Maximum number of connections per node 16
spring.ai.vectorstore.redisson.hnsw.ef-construction Search width during index building 200
spring.ai.vectorstore.redisson.hnsw.ef-runtime Search width during query execution 10

Metadata fields

Metadata fields enable filtering capabilities during similarity searches. You must explicitly define all metadata field names and types for any metadata field used in filter expressions.

Metadata Field Types:

Type Description Use Case
TAG Exact match filtering Categorical data, labels, status values
TEXT Full-text search Descriptions, content fields
NUMERIC Range queries Years, prices, counts, scores

Configuration example:

spring:
  ai:
    vectorstore:
      redisson:
        index-name: "my-index"
        prefix: "doc:"
        initialize-schema: true
        vector-algorithm: HNSW
        distance-metric: COSINE
        hnsw:
          m: 16
          ef-construction: 200
          ef-runtime: 10      
        metadata-fields:
          - name: category
            type: TAG
          - name: description
            type: TEXT
          - name: year
            type: NUMERIC
          - name: price
            type: NUMERIC

Metadata Filtering

You can use the generic metadata filters with Redisson Vector Store.

Using text expression language:

vectorStore.similaritySearch(SearchRequest.builder()
        .query("The World")
        .topK(5)
        .similarityThreshold(0.7)
        .filterExpression("country in ['UK', 'NL'] && year >= 2020")
        .build());

Using programmatic Filter.Expression DSL:

FilterExpressionBuilder b = new FilterExpressionBuilder();

vectorStore.similaritySearch(SearchRequest.builder()
        .query("The World")
        .topK(5)
        .similarityThreshold(0.7)
        .filterExpression(b.and(
                b.in("country", "UK", "NL"),
                b.gte("year", 2020)).build())
        .build());

Filter expressions are automatically converted into Redis search queries. For example, the portable filter expression country in ['UK', 'NL'] && year >= 2020 is converted into the Redis filter format @country:{UK | NL} @year:[2020 inf].

Distance Metrics

The Vector Store supports three distance metrics:

Metric Description Best For
COSINE Cosine similarity (default) Text embeddings, semantic similarity
L2 Euclidean distance Image embeddings, spatial data
IP Inner Product Pre-normalized embeddings

Each metric is automatically normalized to a 0-1 similarity score, where 1 indicates maximum similarity.

Manual Configuration

Instead of using the Spring Boot auto-configuration, you can manually configure the Redisson Vector Store:

@Configuration
public class VectorStoreConfig {

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://127.0.0.1:6379");
        return Redisson.create(config);
    }

    @Bean
    public VectorStore vectorStore(RedissonClient redissonClient, EmbeddingModel embeddingModel) {
        return RedissonVectorStore.builder(redissonClient, embeddingModel)
            .indexName("custom-index")
            .prefix("custom-prefix")
            .vectorAlgorithm(Algorithm.HNSW)
            .distanceMetric(DistanceMetric.COSINE)
            .hnswM(16)
            .hnswEfConstruction(200)
            .hnswEfRuntime(10)
            .metadataFields(
                MetadataField.tag("category"),
                MetadataField.numeric("year"),
                MetadataField.text("description"))
            .initializeSchema(true)
            .build();
    }

    @Bean
    public EmbeddingModel embeddingModel() {
        // Configure your embedding model (OpenAI, Ollama, etc.)
        return new OpenAiEmbeddingModel(new OpenAiApi(System.getenv("OPENAI_API_KEY")));
    }
}

RAG Integration Example

Combine the vector store with Spring AI's ChatClient for Retrieval Augmented Generation:

@Service
public class RagService {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public RagService(ChatClient.Builder chatClientBuilder, VectorStore vectorStore) {
        this.chatClient = chatClientBuilder.build();
        this.vectorStore = vectorStore;
    }

    public String askQuestion(String question) {
        // Retrieve relevant documents
        List<Document> relevantDocs = vectorStore.similaritySearch(
            SearchRequest.builder()
                .query(question)
                .topK(3)
                .similarityThreshold(0.7)
                .build()
        );

        // Build context from retrieved documents
        String context = relevantDocs.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n"));

        // Generate response with context
        return chatClient.prompt()
            .user(u -> u.text("""
                Based on the following context, answer the question.

                Context:
                {context}

                Question: {question}
                """)
                .param("context", context)
                .param("question", question))
            .call()
            .content();
    }
}