Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring data with cassandra giving IllegalStateException

I'm completly new to cassandra, so my error might be obvious.

I'm trying to create an application with spring boot (version 2.3.0.M2) that contacts a cassandra (version 3.11.6) installed in localhost.

I've got an java.lang.IllegalStateException with the message: Since you provided explicit contact points, the local DC must be explicitly set (see basic.load-balancing-policy.local-datacenter in the config, or set it programmatically with SessionBuilder.withLocalDatacenter). Current contact points are: Node(endPoint=localhost:9042, hostId=16a785a4-eaf3-4a4d-a216-5244d75206aa, hashCode=7b0b99d7)=datacenter1. Current DCs in this cluster are: datacenter1

My pom is the following one:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.M2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.test</groupId>
    <artifactId>cassandra</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cassandra</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-cassandra</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </pluginRepository>
    </pluginRepositories>
</project>

In the application code, I've got a the following configuration class:

public class CassandraConfig extends AbstractCassandraConfiguration {

    public static final String KEYSPACE = "test_keyspace";


    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }

    @Override
    protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
        CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(KEYSPACE);

        return Arrays.asList(specification);
    }

    @Override
    protected List<DropKeyspaceSpecification> getKeyspaceDrops() {
        return Arrays.asList(DropKeyspaceSpecification.dropKeyspace(KEYSPACE));
    }

    @Override
    protected String getKeyspaceName() {
        return KEYSPACE;
    }

    @Override
    public String[] getEntityBasePackages() {
        return new String[]{"com.test.cassandra.entity"};
    }
}

My properties file contains the following configuration:

spring.data.cassandara.keyspace-name=test_keyspace
spring.data.cassandra.contact-points=localhost
spring.data.cassanda.port=9042
spring.data.cassandra.schema-act=create_if_not_exists

I also have tried with

spring.data.cassandra.contact-points=dc1

When I execute the application, I got see from the logs that I'm using the following version DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.4.0

In the cassandra-rackdc.properties I've set the name to

dc=dc1

I've done several test adding configuration parameters, even adding an application.conf to the classpath as described datastax documentation, but didn't have any success. Any clue where should I do it?

like image 301
Elena Avatar asked Mar 13 '20 10:03

Elena


People also ask

Can we use JPA with Cassandra?

Use JPA libraries to communicate with Apache Cassandra comparing Achilles, Datastax and Kundera. The last one presents the better processing speeds with lower computational resources consumption. Source code is available on Github with detailed documentation on how to build and run the tests using Docker.

What is Spring Data Cassandra?

GitHub - spring-projects/spring-data-cassandra: Provides support to increase developer productivity in Java when using Apache Cassandra. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.

What is local data center in Cassandra?

An Apache Cassandra Datacenter is a group of nodes, related and configured within a cluster for replication purposes. Setting up a specific set of related nodes into a datacenter helps to reduce latency, prevent transactions from impact by other workloads, and related effects.


2 Answers

There's actually a different config needed for Apache Cassandra to truly work with the new spring versions. It took me about 50 hours of searching before finding this out on this documentation - https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.cassandra-java-config

You'll need to create a new config file as specified there. To do this, follow thus:

  1. Create a new package named config

  2. Create a .java class file in the package named - CassandraConfig

  3. Copy and paste the below code into it.

    @Configuration public class CassandraConfig { public @Bean CqlSession session() { return CqlSession.builder().withKeyspace("mykeyspacename").build(); } }

Note, change the Keyspace name to your Keyspace name defined in your property file. If you have not created a Keyspace, start Cassandra server on your system, login to the cqlsh on the terminal or cmd by issuing cqlsh, and issue this command -

CREATE KEYSPACE IF NOT EXISTS mykeyspacename WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 } AND DURABLE_WRITES = true ;

By now, when you start the spring boot app, it should run without any error.

like image 50
ken4ward Avatar answered Oct 03 '22 16:10

ken4ward


Simply add

spring.data.cassandra.local-datacenter=DC1

to your application.properties file, where DC1 your local datacenter name (default DC1).

like image 39
Alexander Revkov Avatar answered Oct 03 '22 17:10

Alexander Revkov