使用spring数据将spring Boot 应用程序与elasticsearch8.6连接的问题

isr3a4wc  于 2023-06-04  发布在  Spring
关注(0)|答案(3)|浏览(553)

我是ElasticSearch的新手,我希望有一个连接到数据库ElasticSearch 8.6的Sping Boot 应用程序,以便对索引进行CRUD操作。我试图使用Sping Boot 和ElasticSearch数据库做一个CRUD应用程序。
实体:

@Document(createIndex = true, indexName = "client")
public class ClientEntity {

  public ClientEntity() {
    super();
  }

  @Id
  private String id;

  @Field(type = FieldType.Text, name = "name")
  private String name;

  @Field(type = FieldType.Long, name = "phoneNumber")
  private Long phone;

来自spring数据的存储库接口是:

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    import org.springframework.stereotype.Repository;

    @Repository
    public interface ClientRepository extends ElasticsearchRepository<ClientEntity, String> {
    
    }

ElasticSearch配置:

import org.apache.http.HttpHost;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.UsernamePasswordCredentials;
    import org.apache.http.client.CredentialsProvider;
    import org.apache.http.impl.client.BasicCredentialsProvider;
    import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.elasticsearch.client.ClientConfiguration;
    import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;
    import     org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
    
    import co.elastic.clients.elasticsearch.ElasticsearchClient;
    import co.elastic.clients.json.jackson.JacksonJsonpMapper;
    import co.elastic.clients.transport.ElasticsearchTransport;
    import co.elastic.clients.transport.rest_client.RestClientTransport;
    
    @Configuration
    public class ConfigElasticSearch extends ElasticsearchConfiguration {
      @Bean
      public ElasticsearchTransport getElasticsearchTransport() {
        return new RestClientTransport(getRestClient(), new JacksonJsonpMapper());
      }

      @Bean
      public ElasticsearchClient getElasticsearchClient() {
        ElasticsearchClient client = new ElasticsearchClient(getElasticsearchTransport());
        return client;
      }

      @Override
      public ClientConfiguration clientConfiguration() {
        return ClientConfiguration.builder().connectedTo("localhost:9200")
         .withBasicAuth("user", "my-password").build();
      }

pom.xml:

<parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.7.12</version>
    </parent>

    <properties>
      <java.version>17</java.version>
      <spring-cloud.version>2021.0.5</spring-cloud.version>
      <json-web-token.version>0.9.1</json-web-token.version>   
      <org-modelmapper.version>3.1.1</org-modelmapper.version>
    </properties>
    <dependencies>
          <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>${org-modelmapper.version}</version>
          </dependency>
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
    
    <!-- ES -->
           <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
          </dependency>
         <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
         </dependency>
        <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-databind</artifactId>
        </dependency>

使用Spring Data存储库的服务如下:

@Service("clientPersistence")
    public class ClientPersistenceElasticSearchDb {

      @Autowired
      private ClientRepository clientRepository;

      public Stream\<ClientEntity\> findAll() {
       return StreamSupport.stream(this.clientRepository.findAll().spliterator(), false);
      }

      public Optional\<ClientEntity\> findById(String id) {
        return clientRepository.findById(id);
      }
    }

我的微服务的主要配置是:

@SpringBootApplication
    public class ClientMicroserviceApplication {

      public static void main(String[] args) {
        SpringApplication.run(EmpleadosMicroservicioApplication.class, args);
      }

    }

如果我启动我的微服务,我在启动时会得到以下内容(然后,微服务挂起):
org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“clientPersistencia”的Bean时出错:通过字段“clientRepository”表示的未满足依赖;嵌套异常为org.springframework.beans.factory.BeanCreationException:在ConfigElasticSearch上声明的@EnableElasticsearchRepositories中定义的es.clientmicroservice.dao.clientRepository中定义的名为“clientRepository”的Bean创建时出错:设置Bean属性“elasticsearchOperations”时无法解析对Bean“elasticsearchTemplate”的引用;嵌套异常为org.springframework.beans.factory.UnsatisfiedDependencyException:创建在类路径资源[es/clientmicroservice/config/ConfigElasticSearch.class]中定义的名为“elasticsearchOperations”的bean时出错:通过方法'elasticsearchOperations'参数1表示的未满足依赖;嵌套异常为org.springframework.beans.factory.BeanCreationException:创建在类路径资源[es/clientmicroservice/config/ConfigElasticSearch.class]中定义的名为“elasticsearchClient”的bean时出错:通过工厂方法示例化Bean失败;嵌套异常为org.springframework.beans.BeanInstantiationException:示例化[co.elastic.clients.elasticsearch.ElasticsearchClient]失败:工厂方法'elasticsearchClient'抛出异常;嵌套异常为java.lang.NoClassDefFoundError:jakarta/json/spi/JsonProvider
我不知道为什么我的类clientPersistence没有构建,因为缺少JsonProvider依赖项。
有人能帮我吗?
感谢您的评分!

to94eoyn

to94eoyn1#

查看Sping Boot 版本,您正在使用Spring Data Elasticsearch 4.4.x(现在已停止维护)。您正在使用新的Elasticsearch客户端(org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration)的配置。在4.4中引入了当时的新客户端,作为一个新的和潜在的不稳定特性。
我没有看到您设置了jakarta-json.version(请参阅有关新客户端配置的文档)。
您是否有特殊的原因,为什么你覆盖并提供getElasticsearchTransport()getElasticsearchClient()?这些bean是由基类提供的,您需要提供的唯一方法是提供配置的方法。
请记住,当使用该版本并连接到Elasticsearch 8时,您需要在每个请求上设置兼容性头,请参阅相关文档。
我建议您使用最新版本的Spring Data Elasticsearch。

qvtsj1bj

qvtsj1bj2#

您正在使用spring-boot-starter-parent:2.7.12,这意味着您正在使用spring-boot-starter-data-elasticsearch:2.7.12。如果查看依赖项,最后一个依赖于spring-data-elasticsearch:4.4.12。4.4.x的迁移指南说你需要手动添加一些依赖项。我在问题中显示的pom.xml中没有看到任何依赖项。

zbwhf8kr

zbwhf8kr3#

谢谢你的帮助。
我已经更改了我的依赖项,以便使用已弃用的类连接到ElasticSearch:pom.xml:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.7.12</version>
</parent>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

在配置类中,我配置了以下bean(在应用程序属性中,我为url和user/pwd创建了elasticSearch的属性):

@Value("${elasticsearch.url}")
  private String urlElasticsearch;

  @Value("${elasticsearch.user}")
  private String userElasticsearch;

  @Value("${elasticsearch.pwd}")
  private String pwdElasticsearch;

  @Bean
  public RestHighLevelClient client() {
    ClientConfiguration clientConfiguration = ClientConfiguration.builder()
    .connectedTo(urlElasticsearch)
    .withBasicAuth(userElasticsearch, pwdElasticsearch)
    .build();
  return RestClients.create(clientConfiguration).rest();
}

@Bean
public ElasticsearchOperations elasticsearchTemplate() {
  return new ElasticsearchRestTemplate(client());
}

有了这个配置,它就可以连接到Elasticsearch,并可以在elasticsearch上进行查询。例如:repository.findAll()正在工作,它返回存储在elasticsearch索引中的数据。
我遇到的唯一问题是在添加新文档时,使用repository.save(client)。它返回一个异常(但数据被添加到elasticsearch,实际上,如果我列出所有文档,它会返回正常)。
我在保存文档时遇到的异常是:

org.springframework.dao.DataAccessResourceFailureException: Unable to parse response body for Response{requestLine=POST /clientindex/_doc?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}; nested exception is java.lang.RuntimeException: Unable to parse response body for Response{requestLine=POST /clientindex/_doc?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}
  at org.springframework.data.elasticsearch.core.ElasticsearchExceptionTranslator.translateExceptionIfPossible(ElasticsearchExceptionTranslator.java:94)
  at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.translateException(ElasticsearchRestTemplate.java:601)
  at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.execute(ElasticsearchRestTemplate.java:584)
  at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.doIndex(ElasticsearchRestTemplate.java:187)
  at org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate.save(AbstractElasticsearchTemplate.java:201)
  at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.lambda$save$6(SimpleElasticsearchRepository.java:188)
  at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.executeAndRefresh(SimpleElasticsearchRepository.java:360)
  at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.save(SimpleElasticsearchRepository.java:188)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)
  at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
  at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
  at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:530)
  at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:286)
  at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:640)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
  at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
  at jdk.proxy2/jdk.proxy2.$Proxy124.save(Unknown Source)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
  at jdk.proxy2/jdk.proxy2.$Proxy124.save(Unknown Source)
  at es.clientmicroservice.persistence.ClientPersistenceElasticSearchDb.save(ClientPersistenceElasticSearchDb.java:53)
  ...
Caused by: java.lang.RuntimeException: Unable to parse response body for Response{requestLine=POST /clientindex/_doc?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}
  at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.translateException(ElasticsearchRestTemplate.java:599)
  ... 149 more
Caused by: java.io.IOException: Unable to parse response body for Response{requestLine=POST /clientindex/_doc?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}
  at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:2190)
  at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:2137)
  at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:2105)
  at org.elasticsearch.client.RestHighLevelClient.index(RestHighLevelClient.java:1241)
  at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.lambda$doIndex$0(ElasticsearchRestTemplate.java:187)
  at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.execute(ElasticsearchRestTemplate.java:582)
  ... 148 more
Caused by: java.lang.NullPointerException
  at java.base/java.util.Objects.requireNonNull(Objects.java:208)
  at org.elasticsearch.action.DocWriteResponse.<init>(DocWriteResponse.java:116)
  at org.elasticsearch.action.index.IndexResponse.<init>(IndexResponse.java:43)
  at org.elasticsearch.action.index.IndexResponse.<init>(IndexResponse.java:28)
  at org.elasticsearch.action.index.IndexResponse$Builder.build(IndexResponse.java:96)
  at org.elasticsearch.action.index.IndexResponse.fromXContent(IndexResponse.java:78)
  at org.elasticsearch.client.RestHighLevelClient.parseEntity(RestHighLevelClient.java:2484)
  at org.elasticsearch.client.RestHighLevelClient.lambda$performRequestAndParseEntity$8(RestHighLevelClient.java:2105)
  at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:2188)
  ... 153 more

谁能帮我一下,如何避免这种情况?奇怪的是,文档被添加了,但是处理来自elasticsearch的响应失败了。
先谢谢你了!
最好的问候

相关问题