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());
    }
}

Removing elements from Arrays in java.

As far as I know removing elements from arrays is not trivial. Instead of multiple iterative loops, the best way to actually do it is to covert it to ArrayList, add all the elements to the collection and remove the unneccesary elements. This method is particularly useful when the element removed is known and occurs multiple times, like “null” in a string array.

example.

I had an array of strings, which was result of a regex pattern match. it is named as “sentArray2”. To remove the null elements from it, I successfully implemented this following code.

The implementation is like this:

String array —–> ArrayList —-> Update(remove elements) Array list –> Convert back into string array ( I converted back into a new one but its not necessary).

// Create an ArrayList to remove null elements easily

ArrayList sentenceFinal = new ArrayList();

// Step to add all the elements into the ArrayList

for (int e=0;e<sentArray2.length;e++)

{

Collections.addAll(sentenceFinal, sentArray2[e]);

}

// Step to remove all the null elements in a single shot.

sentenceFinal.removeAll(Collections.singleton(null));

// Converting the ArrayList back to String array

String[] sentFinal = new String[sentenceFinal.size()];

sentenceFinal.toArray(sentFinal);