Spring Boot + Cassandra – Issues and remedies.

Hi peeps. Looks like Spring Boot and Apache Cassandra do not mingle as easily as they should. After a lot of trials, I finally figured it and once you figure it out, usually the setup is fairly simple.

First you add this to your pom.

 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-cassandra</artifactId>
 </dependency>


Second you create a POJO.

import org.springframework.data.cassandra.mapping.Table;

@Table("Users")
public class UsersPOJO {

    private String userId;
    private String name;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

Next, you create a DAO.

import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.stereotype.Repository;

import UsersPOJO;

@Repository
public interface UsersDAO extends CassandraRepository{
    
}

Finally, ofcourse you add a service to add/get data.

import java.sql.Timestamp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserService {

    @Autowired
    private UsersDAO usersDAO;
    
    @RequestMapping(value="/create", method= RequestMethod.POST)
    public String createProfile(){
        
        UsersPOJO usersPOJO = new UsersPOJO();
        usersPOJO.setUserId("abc123");            
        usersPOJO.setName("Alphanumeric");        
        usersDAO.save(usersPOJO);
    
        return usersDAO.toString();
    }
       
}

Now, you should be able to fire up your Spring boot app and insert the data and everything should be fine and dandy until you hit this roadblock!

com.datastax.driver.core.exceptions.InvalidQueryException: 
No keyspace has been specified. USE a keyspace, or explicitly specify 
keyspace.tablename

After much pain and time, I found the solution to this problem. Add the following to your application. properties.

spring.data.cassandra.port=9042
spring.data.cassandra.keyspace-name=Test
spring.data.cassandra.contact-points=localhost

I also added a Configuration file below just to make sure I have enough control over the cluster. However, this step is optional.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;

@Configuration
@EnableCassandraRepositories(basePackages = {"com.test"})
public class CassandraConfig {
    @Autowired
    private Environment environment;
    private static final Logger LOGGER = LoggerFactory.getLogger(CassandraConfig.class);
    @Bean
    public CassandraClusterFactoryBean cluster() {
        CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
        cluster.setContactPoints(environment.getProperty("spring.data.cassandra.contact-points"));
        cluster.setPort(Integer.parseInt(environment.getProperty("spring.data.cassandra.port")));
        return cluster;
    }
    @Bean
    public CassandraMappingContext mappingContext() {
        return new BasicCassandraMappingContext();
    }
    @Bean
    public CassandraConverter converter() {
        return new MappingCassandraConverter(mappingContext());
    }
    @Bean
    public CassandraSessionFactoryBean session() throws Exception {
        CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
        session.setCluster(cluster().getObject());
        session.setKeyspaceName(environment.getProperty("spring.data.cassandra.keyspace-name"));
        session.setConverter(converter());
        session.setSchemaAction(SchemaAction.NONE);
        return session;
    }
    @Bean
    public CassandraOperations cassandraTemplate() throws Exception {
        return new CassandraTemplate(session().getObject());
    }
}