Michael Burbidge
Michael Burbidge

Reputation: 203

Connecting dynamically to Cassandra using Spring Data Cassandra

I need to connect dynamically to new Cassandra clusters without restarting the application. I'm using Spring Data Cassandra.

The following code does this, but since it's not done via beans and the IoC, it does not use the ExceptionTranslator implementation that translates Cassandra exceptions to exceptions in Spring’s portable DataAccessException hierarchy.

  CqlSession session = CqlSession.builder()
                         .withKeyspace("composite")
                         .build();
  template = new CassandraTemplate(session);

Is there a way to connect to Cassandra using Spring Data dynamically, by creating beans, in the middle of a running application so that we get the advantages of the standard exception translator? i.e. Not using annotations or XML which only work at startup.

Can you point me at some sample code?


I'm building a service and so what I really want are for these new beans to be part of the ApplicationContext. The above code I believe creates a separate context. The following creates these beans in the ApplicationContext.

        var factory = context.getAutowireCapableBeanFactory();
        var registry = (BeanDefinitionRegistry) factory;
        
        var beanDef = new GenericBeanDefinition();
        beanDef.setBeanClass(Config.class);
        registry.registerBeanDefinition("config", beanDef);

        beanDef = new GenericBeanDefinition();
        beanDef.setBeanClass(CqlSessionFactoryBean.class);
        beanDef.setParentName("config");
        var properties = new MutablePropertyValues();
        properties.add("contactPoints", contactPoints);
        properties.add("keyspaceName", keyspaceName);
        properties.add("localDatacenter", datacenter);
        beanDef.setPropertyValues(properties);
        registry.registerBeanDefinition("session", beanDef);

        beanDef = new GenericBeanDefinition();
        beanDef.setBeanClass(CassandraMappingContext.class);
        beanDef.setParentName("config");
        properties = new MutablePropertyValues();
        var session = factory.getBean("session");
        properties.add("userTypeResolver", new SimpleUserTypeResolver((CqlSession) factory.getBean("session")));
        beanDef.setPropertyValues(properties);
        registry.registerBeanDefinition("mappingContext", beanDef);

        beanDef = new GenericBeanDefinition();
        beanDef.setBeanClass(MappingCassandraConverter.class);
        beanDef.setParentName("config");
        var args = new ConstructorArgumentValues();
        args.addGenericArgumentValue(factory.getBean("mappingContext"));
        beanDef.setConstructorArgumentValues(args);
        registry.registerBeanDefinition("converter", beanDef);

        beanDef = new GenericBeanDefinition();
        beanDef.setBeanClass(SessionFactoryFactoryBean.class);
        beanDef.setParentName("config");
        properties = new MutablePropertyValues();
        properties.add("session", factory.getBean("session"));
        properties.add("converter", factory.getBean("converter"));
        properties.add("schemaAction", SchemaAction.NONE);
        beanDef.setPropertyValues(properties);
        registry.registerBeanDefinition("sessionFactory", beanDef);

        beanDef = new GenericBeanDefinition();
        beanDef.setBeanClass(CassandraTemplate.class);
        beanDef.setParentName("config");
        args = new ConstructorArgumentValues();
        args.addIndexedArgumentValue(0, factory.getBean("sessionFactory"));
        args.addIndexedArgumentValue(1, factory.getBean("converter"));
        beanDef.setConstructorArgumentValues(args);
        registry.registerBeanDefinition("cassandraTemplate", beanDef);
        
        template = (CassandraTemplate) factory.getBean("cassandraTemplate");

Upvotes: 1

Views: 345

Answers (0)

Related Questions