Я создал реактивное приложение Spring, пытающееся подключиться к Cassandra. Мои фрагменты кода выглядят следующим образом:
Решение 1. Реактивная Кассандра [не работает]
Мейвен:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra-reactive</artifactId>
<version>3.0</version>
</dependency>
файл application.yml:
spring.data.cassandra.contact-points=<my connection points>
spring.data.cassandra.username=abc
spring.data.cassandra.password=xyz
spring.data.cassandra.local-datacenter=datacenter1
spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.port=9042
Конфигурация:
@Configuration
@EnableReactiveCassandraRepositories
public class LocalBeanConfig extends AbstractReactiveCassandraConfiguration {
@Override
protected String getKeyspaceName() {
return "mykeyspace";
}
Класс таблицы:
@AllArgsConstructor
@Table("test_table")
public class TableClass {
@Getter
@PrimaryKey
@Column("id")
private String id;
@Column("value")
@Getter
private String value;
}
Класс репозитория:
@Repository
public interface TestAppRepository extends ReactiveCassandraRepository<TableClass, String> {
}
Наконец, я получаю доступ к Cassandra следующим образом:
public class MyService {
private final TestAppRepository testRepository;
public void get(CrawlTask crawlTask) {
testRepository.findById("id_1").map(testAppConfig -> test1(testAppConfig)).switchIfEmpty(Mono.just(test2()));
}
}
Независимо от этого, я не могу подключиться к реактивной Cassandra и получаю следующее исключение при запуске:
Caused by: com.datastax.oss.driver.api.core.AllNodesFailedException
Напротив, если я использую Spring Cassandra вместо Reactive Cassandra, я могу подключиться. Мои фрагменты кода для рабочего решения выглядят следующим образом:
Решение 2: нереактивная Cassandra [работает]
Мейвен:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
приложение.yml
spring.cassandra.contact-points=<my connection points>
spring.cassandra.username=abc
spring.cassandra.password=xyz
spring.cassandra.local-datacenter=datacenter1
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.port=9042
Класс таблицы:
@AllArgsConstructor
@Table("test_table")
public class TableClass {
@Getter
@PrimaryKey
@Column("id")
private String id;
@Column("value")
@Getter
private String value;
}
Репозиторий:
public interface TestAppRepository extends CassandraRepository<TableClass, String> {
}
Наконец, я получаю доступ к Cassandra следующим образом:
public class MyService {
private final TestAppRepository testRepository;
public void get(CrawlTask crawlTask) {
Mono.just(testRepository.findById("id_1").map(testAppConfig -> test1(testAppConfig)).orElse(test2()));
}
}
Таким образом, я могу без проблем получить доступ к таблице Cassandra.
Теперь основное различие, которое я вижу между двумя решениями, решением 1 [не работает] и решением 2 [работает], заключается в том, как определяются конфигурации Cassandra.
В нереактивном случае мы используем spring.cassandra
, а в реактивном случае используем spring.data.cassandra
.
Я также пробовал писать конфиги, используя spring.cassandra
с реактивным регистром. Здесь служба запускается, но при получении данных из таблицы не получает никаких данных. [внутри MyService]
Я не уверен, почему нереактивное решение работает, а реактивное - нет. Что мне здесь не хватает? Может ли кто-нибудь помочь мне?
Редактировать 1:
В соответствии с запросом, совместное использование полной трассировки стека Cassandra + журнала ошибок:
s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Cassandra repositories in DEFAULT mode.
.s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 65 ms. Found 1 Reactive Cassandra repository interfaces.
.s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Cassandra repositories in DEFAULT mode.
.s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 4 ms. Found 0 Cassandra repository interfaces.
c.d.o.d.i.core.DefaultMavenCoordinates : DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.15.0
c.d.oss.driver.internal.core.time.Clock : Using native clock for microsecond precision
c.d.o.d.i.c.control.ControlConnection : [s0] Error connecting to Node(endPoint=/127.0.0.1:9042, hostId=null, hashCode=3f2701f1), trying next node (ConnectionInitException: [s0|control|connecting...] Protocol initialization request, step 1 (OPTIONS): failed to send request
@ErickRamirez Я опубликовал трассировку стека Cassandra + журнал ошибок в качестве редактирования в описании выше. Пожалуйста, дайте мне знать, если есть что-то еще, что вы ищете.
@ErickRamirez, как передать имя пользователя и пароль Cassandra в класс, расширенный AbstractReactiveCassandraConfiguration в Spring 3.*? Как я вижу, getAuthProvider() устарела в этой версии. Я предполагаю, что это может быть причиной ошибки. Я нашел Authentication error (AuthenticationException: Authentication error on node
исключение.
Удалось решить эту проблему. Решение выглядит следующим образом:
Поскольку я использую реактивную версию 3.0, детали Cassandra должны быть упомянуты следующим образом:
spring.cassandra.contact-points=<my connection points>
spring.cassandra.username=abc
spring.cassandra.password=xyz
spring.cassandra.local-datacenter=datacenter1
spring.cassandra.keyspace-name=mykeyspace
spring.cassandra.port=9042
spring.cassandra.schema-action=NONE
Что еще более важно, нам нужен класс @Configuration, определенный следующим образом:
@Configuration
@EnableReactiveCassandraRepositories
public class CassandraConfig extends AbstractReactiveCassandraConfiguration {
@Value("${spring.cassandra.contact-points}")
private String contactPoints;
@Value("${spring.cassandra.local-datacenter}")
private String localDatacenter;
@Value("${spring.cassandra.port}")
private int port;
@Value("${spring.cassandra.keyspace-name}")
private String keySpace;
@Value("${spring.cassandra.username}")
private String username;
@Value("${spring.cassandra.password}")
private String password;
@Value("${spring.cassandra.schema-action}")
private SchemaAction schemaAction;
@Override
protected String getContactPoints() {
return contactPoints;
}
@Override
protected int getPort() {
return port;
}
@Override
public SchemaAction getSchemaAction() {
return schemaAction;
}
@Override
protected String getKeyspaceName() {
return keySpace;
}
@Bean
@Override
public CqlSessionFactoryBean cassandraSession() {
CqlSessionFactoryBean cqlSessionFactoryBean = new CqlSessionFactoryBean();
cqlSessionFactoryBean.setUsername(username);
cqlSessionFactoryBean.setPassword(password);
cqlSessionFactoryBean.setKeyspaceName(keySpace);
cqlSessionFactoryBean.setLocalDatacenter(localDatacenter);
cqlSessionFactoryBean.setPort(port);
cqlSessionFactoryBean.setContactPoints(contactPoints);
return cqlSessionFactoryBean;
}
}
Хороший! Рад, что ты это понял!
Не могли бы вы опубликовать полное сообщение об ошибке + полную трассировку стека? Ваше здоровье!