Ошибка конфигурации FindByIndexNameSessionRepository "RedisConnectionFactory is required"
Реализовывая логику лимитирования активных сессий для каждого пользователя (кол-во сессий хранится в бд, а сами сессии в Redis), наткнулся на проблему конфигурирования FindByIndexNameSessionRepository.
Из-за того, что я инжекчу FindByIndexNameSessionRepository spring начинает конфигурировать бин в классе RedisHttpSessionConfiguration, при этом не заинжектив в себя поля через сеттеры.
По итогу получаю ошибку:
Caused by: java.lang.IllegalStateException: RedisConnectionFactory is required
at org.springframework.util.Assert.state(Assert.java:73) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.data.redis.core.RedisAccessor.afterPropertiesSet(RedisAccessor.java:38) ~[spring-data-redis-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.data.redis.core.RedisTemplate.afterPropertiesSet(RedisTemplate.java:127) ~[spring-data-redis-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration.createRedisTemplate(RedisHttpSessionConfiguration.java:291) ~[spring-session-data-redis-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration.sessionRepository(RedisHttpSessionConfiguration.java:120) ~[spring-session-data-redis-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
Код конфига:
@EnableRedisHttpSession
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
public class CustomConfiguration extends WebSecurityConfigurerAdapter {
private final FindByIndexNameSessionRepository sessionRepository;
// ....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.formLogin()
.and()
// ....
.sessionManagement()
.sessionAuthenticationStrategy(new CustomAuthenticationStrategy(sessionRegistry(), sessionsLimitRepository));
}
@Bean
public SpringSessionBackedSessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry(sessionRepository);
}
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration("server", 6379));
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
}
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<!-- .... -->
</dependencies>
Если убрать\закомментировать места где используется FindByIndexNameSessionRepository, то сеттеры RedisHttpSessionConfiguration, вызываются "кишками" спринга в момент создания бина springSessionRepositoryFilter.
Если я правильно понял, то я, случайно, сломал порядок конфигурирования бинов. В попытках это починить, пробовал @DependsOn, @Lazy и различные махинации с перемещением бинов в разные классы конфигов, сменой порядка загрузки конфигов и прочее.
UPD 1: Добавил бин httpSessionEventPublisher
UPD 2: Добавил pom.xml
Ответы (1 шт):
Основная проблема была в том, что spring-boot конфигурировал уже большую часть бинов за меня.
Для решения данной проблемы необходимо удалить @EnableRedisHttpSession (@EnableWebSecurity тоже можно удалить), бины redisConnectionFactory и httpSessionEventPublisher, и по желанию можно удалить ненужную зависимость spring-session-core
Актуальный код конфига:
@Configuration
@RequiredArgsConstructor
public class CustomConfiguration extends WebSecurityConfigurerAdapter {
private final FindByIndexNameSessionRepository<? extends Session> sessionRepository;
// ....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.formLogin()
.and()
// ....
.sessionManagement()
.sessionAuthenticationStrategy(new CustomAuthenticationStrategy(sessionRegistry(), sessionsLimitRepository));
}
@Bean
public SessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry<>(sessionRepository);
}
}
Актуальный pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- .... -->
</dependencies>