I am not able to establish a connection with the datastax cassandra instance with spring boot version 2.3.0.RELEASE. The same code works fine with spring boot 2.6 version.
Error while running the spring boot app
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration': \
Unsatisfied dependency expressed through constructor parameter 0; \
nested exception is org.springframework.beans.factory.BeanCreationException: \
Error creating bean with name 'cassandraSession' defined in class path resource [org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.class]: \
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: \
Failed to instantiate [com.datastax.oss.driver.api.core.CqlSession]: \
Factory method 'cassandraSession' threw exception; \
nested exception is java.lang.IllegalStateException: \
Can't use withCloudSecureConnectBundle and explicitly specify ssl configuration. They are mutually exclusive.
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
...
@Configuration
public class CassandraConfig {
@Value("${spring.data.cassandra.contact-points}")
private String contactPoints;
@Value("${astra.secure-connect-bundle:none}")
private String astraSecureConnectBundle;
@Value("${spring.data.cassandra.username}")
private String cassandraUsername;
@Value("${spring.data.cassandra.password}")
private String cassandraPassword;
@Value("${spring.data.cassandra.port}")
private int port;
@Value("${spring.data.cassandra.keyspace-name}")
private String keySpace;
@Value("${spring.data.cassandra.local-datacenter}")
private String dataCenter;
@Bean
public CqlSessionBuilderCustomizer sessionBuilderCustomizer() {
/*
* When using DataStax Astra, we must pass the secure connect bundle to the
* CqlSession
* See documentation:
* https://docs.datastax.com/en/astra/aws/doc/dscloud/astra/dscloudUsingDrivers.
* html
*/
if (!astraSecureConnectBundle.equals("none")) {
return builder -> builder
.withCloudSecureConnectBundle(Paths
.get("C:/projects/****/****/**/secure-connect-###.zip"))//zip file provided by datastax
.withAuthCredentials(this.cassandraUsername, this.cassandraPassword);
} else {
return builder -> builder
.addContactPoint(new InetSocketAddress(this.contactPoints, this.port))
.withLocalDatacenter(this.dataCenter)
.withAuthCredentials(this.cassandraUsername, this.cassandraUsername);
}
}
@Bean
public DriverConfigLoaderBuilderCustomizer driverConfigLoaderBuilderCustomizer() {
/*
* When using DataStax Astra, we do not have to pass contact points like we
* normally would because
* this metadata is contained in the secure connect bundle.
*/
if (!astraSecureConnectBundle.equals("none")) {
return builder -> builder.without(DefaultDriverOption.CONTACT_POINTS);
}
return builder -> builder
.withString(DefaultDriverOption.SESSION_NAME, "spring-boot-service");
}
}
application.properties
spring.data.cassandra.keyspace-name="KeySpaceSpace"
spring.data.cassandra.contact-points=#########.db.astra.datastax.com
spring.data.cassandra.port=32392
spring.data.cassandra.local-datacenter=dc-1
spring.data.cassandra.username=###########
spring.data.cassandra.password=###########
spring.data.cassandra.ssl=true
astra.secure-connect-bundle=${ASTRA_SECURE_CONNECT_BUNDLE:/app/astra/creds}
spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS
spring.main.allow-circular-references=true
pom.xml
<?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.6.0</version> -->
<version>2.3.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.sample</groupId>
<artifactId>sample-one-poc-svc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sample-one-poc-svc</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1 </version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1 </version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-query-builder</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-processor</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-runtime</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-core</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-mapping</artifactId>
<version>3.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.17.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
I am not sure if it is the same issue as this https://github.com/spring-projects/spring-boot/issues/21487 The issue says its fixedin 2.3.1 version of spring boot, but I aget same exception if I use 2.3.1 version.
CodePudding user response:
Andrew is on the right track with his comment. The problem is that the secure connect bundle contains connection metadata plus SSL (TLS) credentials so the driver already expects that encryption is enabled which is the reason the resolver throws this exception:
nested exception is java.lang.IllegalStateException: \
Can't use withCloudSecureConnectBundle and explicitly specify ssl configuration. \
They are mutually exclusive.
You can resolve the conflict by removing this line from application.properties
:
spring.data.cassandra.ssl=true
I'm not familiar with the Spring code base so I'm not able verify why it works in 2.6 but not 2.3.
Credit to Cédric Lunven for pointers on the issue. Cheers!