Add property to disable redisson in spring boot
See original GitHub issueHi!
Is your feature request related to a problem? Please describe. We use redisson with spring-boot-starter in our project. Unfortunately, sometimes we need to disable caching (f.e. on some environments we don’t have redis). When it comes to a spring-data-redis we can just set property:
spring.cache.type: NONE
and caching is disabled, but if we use Redisson then his auto-configuration doesn’t let us run the application without a worked Redis connection.
Describe the solution you’d like
Disable the whole auto-configuration when
spring.cache.type: NONE
Describe alternatives you’ve considered We can add a new maven profile and exclude the redisson dependency but it doesn’t sound well because we get a new profile to maintain.
My current solution
- I excluded autoconfigurations:
@EnableAutoConfiguration(exclude = { RedissonAutoConfiguration.class, RedisAutoConfiguration.class })
- I made my own auto configuration (based on redisson’s autoconfiguration) where I’ve added
@ConditionalOnExpression("'${spring.cache.type}' == 'redis'")
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties({RedisProperties.class, RedissonProperties.class})
@ConditionalOnExpression("'${spring.cache.type}' == 'redis'")
public class RedisConfiguration {
private static final String REDIS_PROTOCOL_PREFIX = "redis://";
private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
@Bean
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
return new RedissonConnectionFactory(redisson);
}
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(RedissonClient.class)
public RedissonClient redisson(RedissonProperties redissonProperties, ApplicationContext ctx,
RedisProperties redisProperties) throws IOException {
Config config = null;
Method clusterMethod = ReflectionUtils.findMethod(RedisProperties.class, "getCluster");
Method timeoutMethod = ReflectionUtils.findMethod(RedisProperties.class, "getTimeout");
Object timeoutValue = ReflectionUtils.invokeMethod(timeoutMethod, redisProperties);
int timeout;
if (null == timeoutValue) {
timeout = 10000;
} else if (!(timeoutValue instanceof Integer)) {
Method millisMethod = ReflectionUtils.findMethod(timeoutValue.getClass(), "toMillis");
timeout = ((Long) ReflectionUtils.invokeMethod(millisMethod, timeoutValue)).intValue();
} else {
timeout = (Integer) timeoutValue;
}
if (redissonProperties.getFile() != null) {
InputStream is = getConfigStream(redissonProperties, ctx);
config = Config.fromYAML(is);
} else if (redisProperties.getSentinel() != null) {
Method nodesMethod = ReflectionUtils.findMethod(Sentinel.class, "getNodes");
Object nodesValue = ReflectionUtils.invokeMethod(nodesMethod, redisProperties.getSentinel());
String[] nodes;
if (nodesValue instanceof String) {
nodes = convert(Arrays.asList(((String) nodesValue).split(",")));
} else {
nodes = convert((List<String>) nodesValue);
}
config = new Config();
config.useSentinelServers()
.setMasterName(redisProperties.getSentinel().getMaster())
.addSentinelAddress(nodes)
.setDatabase(redisProperties.getDatabase())
.setConnectTimeout(timeout)
.setPassword(redisProperties.getPassword());
} else if (clusterMethod != null
&& ReflectionUtils.invokeMethod(clusterMethod, redisProperties) != null) {
Object clusterObject = ReflectionUtils.invokeMethod(clusterMethod, redisProperties);
Method nodesMethod = ReflectionUtils.findMethod(clusterObject.getClass(), "getNodes");
List<String> nodesObject = (List) ReflectionUtils.invokeMethod(nodesMethod, clusterObject);
String[] nodes = convert(nodesObject);
config = new Config();
config.useClusterServers()
.addNodeAddress(nodes)
.setConnectTimeout(timeout)
.setPassword(redisProperties.getPassword());
} else {
config = new Config();
String prefix = REDIS_PROTOCOL_PREFIX;
Method method = ReflectionUtils.findMethod(RedisProperties.class, "isSsl");
if (method != null && (Boolean) ReflectionUtils.invokeMethod(method, redisProperties)) {
prefix = REDISS_PROTOCOL_PREFIX;
}
config.useSingleServer()
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
.setConnectTimeout(timeout)
.setDatabase(redisProperties.getDatabase())
.setPassword(redisProperties.getPassword());
}
return Redisson.create(config);
}
private String[] convert(List<String> nodesObject) {
List<String> nodes = new ArrayList<>(nodesObject.size());
for (String node : nodesObject) {
if (!node.startsWith(REDIS_PROTOCOL_PREFIX) && !node.startsWith(REDISS_PROTOCOL_PREFIX)) {
nodes.add(REDIS_PROTOCOL_PREFIX + node);
} else {
nodes.add(node);
}
}
return nodes.toArray(new String[nodes.size()]);
}
private InputStream getConfigStream(RedissonProperties redissonProperties, ApplicationContext ctx)
throws IOException {
Resource resource = ctx.getResource(redissonProperties.getFile());
return resource.getInputStream();
}
}
If you agree then I will push a pull request with changes.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:8 (3 by maintainers)
Hi, To improve the workaround…
If you don’t want to duplicate all the logic in the
RedissonAutoConfiguration
just extend it with@ConditionalOnProperty
or@ConditionalOnExpression
.I have my own implementation of Redisson Bean, which is @Conditional on an external Spring property. So excluding the jar is not an option. Now the phenomenon is if I “turn on” the property, my own bean is created, otherwise the autoconfiguration is triggered. Is there any workout?