This document explains how optional dependencies work in the Firefly Common Cache Library and how to use the library with or without Redis.
The Firefly Common Cache Library is designed with optional dependencies to give you flexibility in choosing which cache implementations to use:
- Caffeine (In-Memory Cache) - Always Available ✅
- Redis (Distributed Cache) - Optional
⚠️
Redis dependencies are marked as <optional>true</optional> in the library's pom.xml. This means:
- ✅ You can use the library WITHOUT Redis - Only Caffeine cache will be available
- ✅ No Redis classes are loaded if Redis is not on your classpath
- ✅ No errors or warnings if Redis dependencies are missing
- ✅ Smaller dependency footprint if you only need in-memory caching
The library uses separate auto-configuration classes to ensure Redis is truly optional:
-
CacheAutoConfiguration- Core configuration (always loaded)- Configures Caffeine cache adapter
- Sets up cache manager
- Provides serialization support
-
RedisCacheAutoConfiguration- Redis-specific configuration (conditionally loaded)- Only loaded when Redis classes are on the classpath
- Configures Redis connection factory
- Sets up Redis cache adapter
This separation ensures that:
- Redis classes are never imported in the core configuration
- No
ClassNotFoundExceptionoccurs when Redis is not available - The library works seamlessly with or without Redis
Maven Dependencies:
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-cache</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>Application Properties:
firefly:
cache:
default-cache-name: default
default-cache-type: caffeine
caffeine:
default:
maximum-size: 1000
expire-after-write: PT1HResult:
- ✅ Only Caffeine cache adapter is created
- ✅ No Redis dependencies required
- ✅ Smaller application footprint
Maven Dependencies:
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-cache</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Add Redis dependencies explicitly -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>Application Properties:
firefly:
cache:
default-cache-name: default
default-cache-type: auto # or 'redis'
caffeine:
default:
maximum-size: 1000
expire-after-write: PT1H
redis:
default:
enabled: true
host: localhost
port: 6379
database: 0Result:
- ✅ Both Caffeine and Redis cache adapters are created
- ✅ Auto-selection strategy chooses the best cache for each operation
- ✅ Full distributed caching capabilities
If you have Redis dependencies on your classpath but want to disable Redis caching:
Application Properties:
firefly:
cache:
redis:
default:
enabled: false # Explicitly disable RedisResult:
- ✅ Only Caffeine cache adapter is created
- ✅ Redis beans are not instantiated
- ✅ No Redis connections are made
The library uses Spring Boot's conditional annotations to ensure beans are only created when appropriate:
@Bean
@ConditionalOnClass(name = "com.github.benmanes.caffeine.cache.Caffeine")
@ConditionalOnProperty(prefix = "firefly.cache.caffeine.default",
name = "enabled",
havingValue = "true",
matchIfMissing = true)
public CacheAdapter caffeineCacheAdapter(CacheProperties properties)Created when:
- ✅ Caffeine is on the classpath
- ✅ Not explicitly disabled via properties
@Bean
@ConditionalOnProperty(prefix = "firefly.cache.redis.default",
name = "enabled",
havingValue = "true",
matchIfMissing = true)
@ConditionalOnBean({ReactiveRedisTemplate.class, ReactiveRedisConnectionFactory.class})
public CacheAdapter redisCacheAdapter(...)Created when:
- ✅ Redis classes are on the classpath
- ✅ Redis host is configured
- ✅ Not explicitly disabled via properties
- ✅ Redis connection factory and template beans exist
The library includes comprehensive tests to verify it works without Redis:
@Test
void shouldStartWithoutRedis() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
CacheAutoConfiguration.class,
RedisCacheAutoConfiguration.class
))
.withClassLoader(new FilteredClassLoader(
ReactiveRedisTemplate.class,
ReactiveRedisConnectionFactory.class
));
contextRunner.run(context -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(FireflyCacheManager.class);
assertThat(context).hasSingleBean(CacheAdapter.class);
});
}See CacheAutoConfigurationWithoutRedisTest for complete test suite.
If you're migrating from a version where Redis was required:
- Remove explicit Redis dependencies from your
pom.xmlif you don't need Redis - Update application properties to disable Redis if needed:
firefly: cache: redis: default: enabled: false
- Test your application to ensure it works with Caffeine-only caching
If you want to add Redis to an existing Caffeine-only setup:
-
Add Redis dependencies to your
pom.xml:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
Configure Redis in your application properties:
firefly: cache: redis: default: enabled: true host: localhost port: 6379
-
Restart your application - Redis cache adapter will be auto-configured
Cause: Redis dependencies are not on the classpath
Solution: This is expected if you're using Caffeine-only mode. No action needed.
Possible causes:
- Redis host not configured in properties
- Redis explicitly disabled:
firefly.cache.redis.default.enabled=false - Another
ReactiveRedisConnectionFactorybean already exists
Solution: Check your application properties and bean configuration
Cause: Default cache type is set to caffeine or auto is selecting Caffeine
Solution: Set the default cache type explicitly:
firefly:
cache:
default-cache-type: redis- Start with Caffeine-only for development and testing
- Add Redis when you need distributed caching or persistence
- Use
autocache type to let the library choose the best cache - Monitor cache metrics to understand which cache is being used
- Test both scenarios (with and without Redis) in your CI/CD pipeline
✅ Redis is truly optional - The library works perfectly without it
✅ No class loading issues - Redis classes are never loaded if not available
✅ Flexible configuration - Enable/disable Redis via properties
✅ Seamless integration - Add Redis anytime without code changes
✅ Well-tested - Comprehensive test suite verifies both scenarios
For more information, see: