解决maven 父工程依赖传递导致的 java.lang.NoClassDefFoundError: org/elasticsearch/xcontent/ToXContentObject

前言

因为项目需要,最近在学习elasticsearch,在使用elasticsearch Java 客户端时,出现了写问题,主要就是报各种的 NoClassDefFoundError

如:java.lang.NoClassDefFoundError: org/elasticsearch/xcontent/ToXContentObject,出现这种 NoClassDefFoundError 的问题基本上就是maven 依赖错误或者版本不对,于是顺着这个思路排查,摸到了问题所在。

案例描述

在尝试使用 elasticsearch-rest-high-level-client 客户端 7.17.4版本。

项目的依赖: elasticsearch-demo -> demo -> spring-boot-starter-parent :2.2.10.RELEASE

父工程demo的pom

<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>
	<packaging>pom</packaging>
   
    <modules>
		<module>elasticsearch-demo</module>
	</modules>
    
    <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.10.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
    <groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
		<!-- <elasticsearch.version>7.17.4</elasticsearch.version> -->
	</properties>
    
    <dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.elasticsearch.client</groupId>
				<artifactId>elasticsearch-rest-high-level-client</artifactId>
				<version>7.17.4</version>
				<!-- <version>${elasticsearch.version}</version> -->
			</dependency>
		</dependencies>
	</dependencyManagement>
    ........ 省略 ......
</project>
    

子工程elasticsearch-demo 的 pom

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>elasticsearch-demo</artifactId>
    <groupId>com.example</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <name>elasticsearch-demo</name>
    
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
        </dependency>
    </dependencies>
       ........ 省略 ......
</project>

使用案例

本以为按照如上配置,就能安心使用java客户端进行对elasticsearch的操作了,但是如下执行会直接报错 : java.lang.NoClassDefFoundError: org/elasticsearch/xcontent/ToXContentObject

/**
 * @author lvzb
 * @date 2022/12/05  13:53
 **/
@Slf4j
public class ElasticSearchTest {

    @Test
    void connectEs() throws IOException {

        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http")
        ));

        GetIndexRequest request = new GetIndexRequest("index");
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        // 索引是否存在
        System.out.println(exists);
        client.close();
    }
}
java.lang.NoClassDefFoundError: org/elasticsearch/xcontent/ToXContentObject

	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at com.example.redis.demo.config.ElasticSearchTest.connectEs(ElasticSearchTest.java:70)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
       ........ 省略 ......
Caused by: java.lang.ClassNotFoundException: org.elasticsearch.xcontent.ToXContentObject
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 73 more

顺着异常的类,在elasticsearch-demo的Dependencies中发现了问题所在 [idea右侧菜单栏的Maven Dependencies ] 发现我的 org.elasticsearch.client:elasticsearch-rest-high-level-client:7.17.4下竟然存在一个 org.elasticsearch:elasticsearch:6.8.12

而且IDEA没有任何报错和依赖冲突的提示,这是为何?原来是demo 依赖的 父工程 spring-boot-starter-parent :2.2.10.RELEASE 他里面含有 org.elasticsearch:elasticsearch:6.8.12 被带过来了,而且竟然直接将我们在 demo 显示声明的 7.17.4中含有的给替换了。

解决:在 demo 工程的 pom 中 声明 elasticsearch.version,也就是上述案例代码中的 注释给打开,然后依赖里引用该版本号即可。注意:这里声明版本的用词要和 spring-boot-starter-parent 含有的依赖声明的版本用词要一致

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值