Search code examples
javaspring-bootelasticsearchspring-datanosuchfileexception

What is the difference between spring-data-elasticsearch vs spring-boot-starter-data-elasticsearch?


I was facing this issue after migrating to springboot 2.7.15 while saving a doc to es index.

2023-10-04 13:23:01 [pool-2-thread-10] ERROR o.s.s.s.TaskUtils$LoggingErrorHandler -
                Unexpected error occurred in scheduled task
java.lang.NoSuchFieldError: INDEX_CONTENT_TYPE
    at org.springframework.data.elasticsearch.core.RequestFactory.indexRequest(RequestFactory.java:771)
    at org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate.doIndex(ElasticsearchRestTemplate.java:156)
    at org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate.save(AbstractElasticsearchTemplate.java:189)
    at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.lambda$save$6(SimpleElasticsearchRepository.java:185)
    at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.executeAndRefresh(SimpleElasticsearchRepository.java:359)
    at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.save(SimpleElasticsearchRepository.java:185)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    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:241)
    at jdk.proxy2/jdk.proxy2.$Proxy100.save(Unknown Source)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    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:241)
    at jdk.proxy2/jdk.proxy2.$Proxy100.save(Unknown Source)

By changing to spring-boot-starter-data-elasticsearch it fixed the issue. So what is the difference between both dependencies


Solution

  • The library spring-data-elasticsearch is the Elasticsearch support for Spring Data, which is not tied to Spring Boot specifically.

    The library spring-boot-starter-data-elasticsearch is the Spring Boot starter which configures/sets up Spring Boot to use Elasticsearch with Spring Data (and among others, includes spring-data-elasticsearch as one of its dependencies).

    In other words, when you use spring-boot-starter-data-elasticsearch, you also use spring-data-elasticsearch, but the starter makes sure you also have any other dependencies needed for things to work correctly in Spring Boot.

    However, given the error in your question, I rather suspect the main problem was that you depended on the wrong version of spring-data-elasticsearch. A NoSuchFieldError generally indicates that the code was compiled against a different version of another dependency, and if that code changes (e.g. a field getting removed or renamed), it will then fail at runtime. When you switched to spring-boot-starter-data-elasticsearch it imported the right version of the spring-data-elasticsearch dependency, and the problem went away.

    When you use Spring Boot, you should generally not specify versions of dependencies in your Maven or Gradle config, but rather use the versions managed by Spring Boot. Only dependencies which are not managed by Spring Boot should have a version in your build config (see Dependency Versions for a list of dependencies managed by Spring Boot)