2
votes

In our infrastructure, we are using Redis with Dynomite to have a replication over datacenter and high availability. One of our app is in Java and we are mainly using spring ecosystem.

In this app, we manage session using spring-session and we use the Redis cluster to store the sessions.

Spring session is using pub/sub commands which are not allowed in a Dynomite context so we need to to a custom repository.

I tried to do so but I have an issue with spring-boot and autoconfiguration class.

please find below some part of our code.

dependencies in a build.gradle

val springBootVersion = "2.1.4.RELEASE"
val springSessionDataRedisVersion = "2.1.5.RELEASE"

implementation("org.springframework.boot:spring-boot-starter-security:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-data-redis:$springBootVersion")
implementation("org.springframework.session:spring-session-data-redis:$springSessionDataRedisVersion")

Our configuration class to override the sessionRepository with our custom one

@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer     {

@Bean
public SessionRepository sessionRepository() {
    return new RedisDynoSessionRepository();
    }
}

The sessionRepository custom class

public class RedisDynoSessionRepository implements SessionRepository {
...
}

When we run our app, we a collision in the bean because the app finds that the bean session repository is already known.

org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'sessionRepository' defined in class path resource [com/orange/ccmd/spring/redis/SessionConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=sessionConfig; factoryMethodName=sessionRepository; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/orange/ccmd/spring/redis/SessionConfig.class]] for bean 'sessionRepository': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration; factoryMethodName=sessionRepository; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]] bound.

I am looking for a way to bypass this problem may be with unregistring the bean ?

Thanks for you help.


[EDIT]

I tried the @Primary on the bean and it doesn't work. If I named my bean differently, Spring uses the standard bean not my custom new one. If I named it the same way, I have a conflict error. If I put the override bean configuration (spring.main.allow-bean-definition-overriding=true), I have an error because the 2 beans don't have the same type. Which is what I intend to do because I don't want the messaging stuff in my repo.

1
@DarrenForsythe No I don't think it is related. In my case, I try to register my bean instead of the standard redis repository bean. I don't want to allow overriding beans because I think it can be dangerous. - Hervé Darritchon
Have you tried renaming the bean? Overriding exception occurs because of name conflicts not types. - Darren Forsythe
I think I can't change the name of the bean because Spring-Data-Redis use this bean as a repository and I want to provide my own version of the repository. So I think it has to have the same name. - Hervé Darritchon
sure, but I dont think its depending on autowiring by name? e.g. if you change the method name to redisDynoSessionRepository does it work? If you have to name them the same you have no real option but to enable bean overriding. - Darren Forsythe

1 Answers

2
votes

I have opened an issue on the github Spring-sesssion repo (https://github.com/spring-projects/spring-session/issues/1406).

I had my answer. In fact, I did it the wrong way. As it is stated in the documentation. I have to use the @EnableSpringHttpSessionannotation to register my custom bean instead of the @EnableRedisHttpSession.

And it works, I don't have any issue during the app initialization.