ASC
ASC

Reputation: 33

How to set Spring Data Cassandra keyspace dynamically?

We're using Spring Boot 1.5.10 with Spring Data for Apache Cassandra and that's all working well.

We've had a new requirement coming along where we need to connect to a different keyspace while the service is up and running.

Through the use of Spring Cloud Config Server, we can easily set the value of spring.data.cassandra.keyspace-name, however, we're not certain if there's a way that we can dynamically switch (force) the service to use this new keyspace without having to restart if first?

Any ideas or suggestions?

Upvotes: 3

Views: 2301

Answers (2)

mp911de
mp911de

Reputation: 18129

Using @RefreshScope with properties/repositories doesn't work as the keyspace is bound to the Cassandra Session bean.

Using Spring Data Cassandra 1.5 with Spring Boot 1.5 you have at least two options:

  1. Declare a @RefreshScope CassandraSessionFactoryBean, see also CassandraDataAutoConfiguration. This will interrupt all Cassandra operations upon refresh and re-create all dependant beans.
  2. Listen to RefreshScopeRefreshedEvent and change the keyspace via USE my-new-keyspace;. This approach is less invasive and doesn't interrupt running queries. You'd basically use an event listener.

    @Component
    class MySessionRefresh {
    
      private final Session session;
      private final Environment environment;
    
      // omitted constructors for brevity
    
      @EventListener
      @Order(Ordered.LOWEST_PRECEDENCE)
      public void handle(RefreshScopeRefreshedEvent event) {
    
        String keyspace = environment.getProperty("spring.data.cassandra.keyspace-name");
        session.execute("USE " + keyspace + ";");
      }
    }
    

With Spring Data Cassandra 2, we introduced the SessionFactory abstraction providing AbstractRoutingSessionFactory for code-controlled routing of CQL/session calls.

Upvotes: 1

Ortomala Lokni
Ortomala Lokni

Reputation: 62635

Yes, you can use the @RefreshScope annotation on a the bean(s) holding the spring.data.cassandra.keyspace-name value.

After changing the config value through Spring Cloud Config Server, you have to issue a POST on the /refresh endpoint of your application.

From the Spring cloud documentation:

A Spring @Bean that is marked as @RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.

From the RefreshScope class javadoc:

A Scope implementation that allows for beans to be refreshed dynamically at runtime (see refresh(String) and refreshAll()). If a bean is refreshed then the next time the bean is accessed (i.e. a method is executed) a new instance is created. All lifecycle methods are applied to the bean instances, so any destruction callbacks that were registered in the bean factory are called when it is refreshed, and then the initialization callbacks are invoked as normal when the new instance is created. A new bean instance is created from the original bean definition, so any externalized content (property placeholders or expressions in string literals) is re-evaluated when it is created.

Upvotes: 1

Related Questions