Итак, сегодня столкнулся с интересной проблемой, связанной с spring-boot-starter-data-rest. Мой вариант использования — хранить некоторые данные в Redis с некоторым сроком действия, чтобы они были удалены, как только это время истечет. У меня все настроено и работает на моем локальном Redis без каких-либо проблем. Это становится проблемой при попытке работать с ним на AWS с использованием защищенного соединения (SSL) и является примером ошибки:
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180)
at com.springbootapp.config.Application.main(Application.java:16)
... 6 more
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: ERR Unsupported CONFIG parameter: notify-keyspace-events; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR Unsupported CONFIG parameter: notify-keyspace-events
at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:44)
at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:36)
at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:37)
at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:37)
at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:210)
at org.springframework.data.redis.connection.jedis.JedisConnection.setConfig(JedisConnection.java:633)
at org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction.configure(ConfigureNotifyKeyspaceEventsAction.java:63)
at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration$EnableRedisKeyspaceNotificationsInitializer.afterPropertiesSet(RedisHttpSessionConfiguration.java:167)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 22 more
Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR Unsupported CONFIG parameter: notify-keyspace-events
at redis.clients.jedis.Protocol.processError(Protocol.java:117)
at redis.clients.jedis.Protocol.process(Protocol.java:151)
at redis.clients.jedis.Protocol.read(Protocol.java:205)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:297)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:196)
at redis.clients.jedis.Jedis.configSet(Jedis.java:2575)
at org.springframework.data.redis.connection.jedis.JedisConnection.setConfig(JedisConnection.java:631)
... 26 more
Я не использую @EnabledRedisSession
и это зависит, так как мне это не нужно.
Оказывается, большинство примеров ориентировано на это.
Я добавил зависимость весеннего сеанса Redis и попробовал
@Bean
public static ConfigureRedisAction configureRedisAction() {
return ConfigureRedisAction.NO_OP;
}
@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_DEMAND)
изменил это на on_demand, и я получаю следующую ошибку.
Мой redisContainer, показанный ниже, не работает.
@EnableAsync
@Configuration
@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_DEMAND)
public class RedisConfiguration {
private DeloreanProperties deloreanProperties;
private ApplicationEventPublisher applicationEventPublisher;
private RedisConfigProperties redisConfigProperies;
private Environment environment;
@Autowired
public void setDeloreanProperties(DeloreanProperties deloreanProperties) {
this.deloreanProperties = deloreanProperties;
}
@Autowired
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@Autowired
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Autowired
public void setRedisConfigProperies(RedisConfigProperties redisConfigProperies) {
this.redisConfigProperies = redisConfigProperies;
}
@Bean
public JedisConnectionFactory redisConnectionFactory() {
JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
jedisClientConfiguration.connectTimeout(Duration.ofSeconds(60));
jedisClientConfiguration.usePooling();
if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("deployed")))) {
jedisClientConfiguration.useSsl();
}
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(redisConfigProperies.getHost());
configuration.setPort(redisConfigProperies.getPort());
configuration.setPassword(redisConfigProperies.getPassword());
return new JedisConnectionFactory(configuration, jedisClientConfiguration.build());
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
return template;
}
@Bean
public RedisMessageListenerContainer redisContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory());
container.setTaskExecutor(Executors.newFixedThreadPool(deloreanProperties.getListenExecutorFixedThreadPool()));
return container;
}
@Bean
public MessageListener messageListener() {
KeyExpirationEventMessageListener messageListener = new KeyExpirationEventMessageListener(redisContainer());
messageListener.setApplicationEventPublisher(applicationEventPublisher);
return messageListener;
}
}