关键词:Maven
问题复现
使用Java连接es报错
Exception in thread "main" java.lang.NoSuchFieldError: FAIL_ON_SYMBOL_HASH_OVERFLOW
at org.elasticsearch.common.xcontent.json.JsonXContent.<clinit>(JsonXContent.java:57)
at org.elasticsearch.common.xcontent.XContentType$1.xContent(XContentType.java:56)
at org.elasticsearch.common.xcontent.XContentHelper.toXContent(XContentHelper.java:348)
at org.elasticsearch.client.RequestConverters.createEntity(RequestConverters.java:686)
at org.elasticsearch.client.RequestConverters.createEntity(RequestConverters.java:681)
at org.elasticsearch.client.RequestConverters.search(RequestConverters.java:388)
at org.elasticsearch.client.RestHighLevelClient.lambda$search$4(RestHighLevelClient.java:1094)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1760)
at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1734)
at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1696)
at org.elasticsearch.client.RestHighLevelClient.search(RestHighLevelClient.java:1092)
原因是elasticsearch jar包里面的jackson-core的jar包和其他jar包产生冲突,其他jar也引用了jackson-core,导致有多个jackson-core,程序里面调用的jackson-core没有FAIL_ON_SYMBOL_HASH_OVERFLOW这个字段
Maven jar包冲突原理
假设pom中引入了A和E两个jar包,A和E各自也有需要引入的jar包
A->B->C->D(15.0):A中包含对B的依赖,B中包含对C的依赖,C中包含对D1的依赖,D1的version为15.0
E->F->D(16.0):E中包含对F的依赖,F包含对D2的依赖,假设是D2是同一个日志jar包,version为16.0
由于A,E都引用了D,但是D的版本不同,产生jar包冲突,此时Maven对于同一个jar包只会保留一个,Maven的保留规则为:
1.最短路径优先
如果有多个路径引用到D,就选取其中最短的路径对应的那个D作为最终的D引入项目,这点很容易理解,比如有个jar比如D是直接在pom里面引用的,它的路径长度就是1,它肯定比引其他包导致被D被关联引入的更符合使用的需求。2.最先声明优先
如果路径长度都相同,则以最先声明的为准,就是pom文件哪个写在上面,如果路径长度相同,只能凭借前后声明拼运气了
使用Maven helper分析冲突
下载Maven helper插件
安装好后在工程目录中双击选中pom文件,就可以看到Dependency Analyzer
点击进入分析
左边框内每一个jar包都是冲突项,右边展示了具体该jar如何冲突,把它的来源路径全部展示出来,以jackson-core为例,有6个来源路径,其中5个是红色的代表被Maven冲突规则去除的,有一个白色的是最终被项目引入的,由此也说明Maven会通过简单规则将同一个jar包的仅一个版本引入项目。最终被引入的是hadoop-client这条路径的,原因是该路径最短只有2,spark_hive_2.11太长为3,而同为2的elasticsearch由于在pom中写在了hadoop-client的下面导致也被去除了。
解决方案
很明显应该保留下elasticsearch的jackson-core,由于已经知道了Maven的冲突保留规则,因此本例中可以直接把elasticsearch在pom中写到hadoop-client的上面
更改后在冲突UI中点击Reimport即可重新查看
此时elasticsearch变为白色成为最终保留下来的路径,重新打包FAIL_ON_SYMBOL_HASH_OVERFLOW问题解决。
以上只是搞正确了最后保留下来的胜利者正确,并没有避免冲突,基于冲突UI进一步操作,右键需要移除的jar包点击Exclude即可以避免冲突
点击之后红色的消失,同时在pom里面自动加上了Exclude语句