javaspringspring-bootcassandraspring-data-cassandra

How to manage two Cassandra sessions using spring data cassandra with spring boot 2.7.x


In My Application, Using the below technologies

Spring boot 2.7.x
spring-boot-starter-data-cassandra 2.7.x
spring batch 5. x
java 11
Configuration
@EnableCassandraRepositories(
    basePackages = {"com.package1"},
    cassandraTemplateRef = "cassandraTemplate1",
    repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class
)
public class CassandraConfigurationCluster1 extends CassandraConfiguration {
Configuration
@EnableCassandraRepositories(
    basePackages = {"com.package2"},
    cassandraTemplateRef = "cassandraTemplate2",
    repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class
)
public class CassandraConfigurationCluster2 extends CassandraConfiguration {

and with that I have created two beans for CassandraAdminTemplate ( not sure I was using CassandraTemplate from spring boot 2.2.x but its changed to something else in 2.7.x

   @Bean("session1")
  public CqlSessionFactoryBean session() {
    return new CqlSessionFactoryBean();
  }

  @Bean("cassandraTemplate1")
  public CassandraAdminOperations cassandraTemplate(
          @Qualifier("session1")  final CqlSessionFactoryBean session) {
    return new CassandraAdminTemplate(session.getObject(), cassandraConverter());
  }
@Bean("session2")
  public CqlSessionFactoryBean session() {
    return new CqlSessionFactoryBean();
  }

  @Bean("cassandraTemplate2")
  public CassandraAdminOperations cassandraTemplate(
          @Qualifier("session2")  final CqlSessionFactoryBean session) {
    return new CassandraAdminTemplate(session.getObject(), cassandraConverter());
  }

But I am getting error

Unsatisfied dependency expressed through field 'cassandraTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cassandraTemplate' defined in class path resource [/config/CassandraConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.cassandra.core.CassandraAdminTemplate]: Factory method 'cassandraTemplate' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cassandraSessionFactory' defined in class path resource [/config/CassandraConfiguration.class]: Unsatisfied dependency expressed through method 'cassandraSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.datastax.oss.driver.api.core.CqlSession' available: expected single matching bean but found 3: session1,session2","thread":"main","logger":"org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"}

I know this error but I don't know what else should I use it instead to managed two separate Cassandra connections

Thanks


Solution

  • I managed to create two unique sessions to connect to two different keyspaces by adding below code

    @Configuration
    @EnableCassandraRepositories(
    basePackages = {"com.package1"},
    cassandraTemplateRef = "cassandraTemplate1",
    repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class
    )
    public class CassandraConfigurationCluster1 extends CassandraConfiguration {
    
    @Primary
    @Bean("session1")
    public SessionFactoryFactoryBean cassandraSessionFactory(CqlSession cqlSession) {
    SessionFactoryFactoryBean bean = new SessionFactoryFactoryBean();
    bean.setSession(cqlSession);
      bean.setConverter((CassandraConverter)this.requireBeanOfType(CassandraConverter.class));
    bean.setKeyspaceCleaner(this.keyspaceCleaner());
    bean.setKeyspacePopulator(this.keyspacePopulator());
    bean.setSchemaAction(this.getSchemaAction());
    return bean;
    }
    
    @Bean("cassandraTemplate1")
    public CassandraAdminOperations cassandraTemplate(
          @Qualifier("session1")  final SessionFactoryFactoryBean session) throws Exception {
    return new CassandraAdminTemplate(session.getObject(), cassandraConverter());
    }
    

    For second session

    @Configuration
    @EnableCassandraRepositories(
    basePackages = {"com.package2"},
    cassandraTemplateRef = "cassandraTemplate2",
    repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class
    )
    public class CassandraConfigurationCluster2 extends CassandraConfiguration {    
    
    @Bean("session2")
    public SessionFactoryFactoryBean cassandraSessionFactory(CqlSession cqlSession) {
    SessionFactoryFactoryBean bean = new SessionFactoryFactoryBean();
    bean.setSession(cqlSession);
      bean.setConverter((CassandraConverter)this.requireBeanOfType(CassandraConverter.class));
    bean.setKeyspaceCleaner(this.keyspaceCleaner());
    bean.setKeyspacePopulator(this.keyspacePopulator());
    bean.setSchemaAction(this.getSchemaAction());
    return bean;
    }
    
    @Bean("cassandraTemplate2")
    public CassandraAdminOperations cassandraTemplate(
          @Qualifier("session2")  final SessionFactoryFactoryBean session) throws Exception {
    return new CassandraAdminTemplate(session.getObject(), cassandraConverter());
    }
    

    with this I could connect to two clusters without any issues