2

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
    Possible duplicate of [SpringBoot - BeanDefinitionOverrideException: Invalid bean definition](https://stackoverflow.com/questions/53723303/springboot-beandefinitionoverrideexception-invalid-bean-definition) – Darren Forsythe Apr 23 '19 at 19:35
  • @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 Apr 24 '19 at 09:35
  • Have you tried renaming the bean? Overriding exception occurs because of name conflicts not types. – Darren Forsythe Apr 24 '19 at 09:38
  • 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 Apr 24 '19 at 11:09
  • 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 Apr 24 '19 at 12:06
  • I tried and it doesn't work, Spring uses the standard bean and not the new one. But I can't see how spring knows which bean to use if I create a new one with a different name. – Hervé Darritchon Apr 24 '19 at 12:35
  • fyi you can get around this with not naming the bean `sessionRepository` and tagging it as `@Primary`, without primary it will error on two session repositories being available. Looking at the session autoconfig it looks like there is a small handful of support spring session repositories which your custom impl. obviously won't be supported by default – Darren Forsythe Apr 24 '19 at 22:00

1 Answers1

2

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.