使用sbt-assembly打包Lucene Scala项目遇SPI类缺失异常求助
环境信息
- OS: Ubuntu 22.10
- Java: openjdk version "19.0.1" 2022-10-18
- Scala: 2.13.10
- Apache Lucene: 9.4.2
Scala版Lucene示例代码
我将Lucene官方文档示例转换为Scala程序,代码如下:
package test import org.apache.lucene.analysis.standard.StandardAnalyzer import org.apache.lucene.document.{Document, Field, TextField} import org.apache.lucene.index.{DirectoryReader, IndexWriter, IndexWriterConfig} import org.apache.lucene.queryparser.classic.QueryParser import org.apache.lucene.search.{IndexSearcher, Query, ScoreDoc} import org.apache.lucene.store.FSDirectory import java.nio.file.{Files, Path} object Test extends App { val analyzer: StandardAnalyzer = new StandardAnalyzer() val indexPath: Path = Files.createTempDirectory("tempIndex") val directory: FSDirectory = FSDirectory.open(indexPath) val config: IndexWriterConfig = new IndexWriterConfig(analyzer) val iwriter: IndexWriter = new IndexWriter(directory, config) val doc: Document = new Document() val text: String = "This is the text to be indexed." doc.add(new Field("fieldname", text, TextField.TYPE_STORED)) iwriter.addDocument(doc) iwriter.close() // 搜索索引 val ireader: DirectoryReader = DirectoryReader.open(directory) val isearcher: IndexSearcher = new IndexSearcher(ireader) // 解析搜索"text"的简单查询 val parser: QueryParser = new QueryParser("fieldname", analyzer) val query: Query = parser.parse("text") val hits: Array[ScoreDoc] = isearcher.search(query, 10).scoreDocs assert(hits.length == 1) // 遍历结果 for (i <- hits.indices) { val hitDoc = isearcher.doc(hits(i).doc) assert("This is the text to be indexed.".equals(hitDoc.get("fieldname"))) } ireader.close() directory.close() println("The end!") }
初始sbt配置文件
最初使用的sbt配置如下:
ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "2.13.10" lazy val root = (project in file(".")) .settings( name := "Test" ) val luceneVersion = "9.4.2" libraryDependencies ++= Seq( "org.apache.lucene" % "lucene-core" % luceneVersion, "org.apache.lucene" % "lucene-queryparser" % luceneVersion )
编译阶段错误
编译时出现重复文件错误:
[error] Deduplicate found different file contents in the following: [error] Jar name = lucene-core-9.4.2.jar, jar org = org.apache.lucene, entry target = module-info.class [error] Jar name = lucene-queries-9.4.2.jar, jar org = org.apache.lucene, entry target = module-info.class [error] Jar name = lucene-queryparser-9.4.2.jar, jar org = org.apache.lucene, entry target = module-info.class [error] Jar name = lucene-sandbox-9.4.2.jar, jar org = org.apache.lucene, entry target = module-info.class
修改后的sbt配置(添加合并策略)
于是我在sbt文件中添加了合并策略:
assembly / assemblyMergeStrategy := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case _ => MergeStrategy.first }
运行异常
添加合并策略后,通过sbt "runMain test.Test"命令编译并运行程序一切正常。但当使用sbt-assembly(插件版本2.1.0)生成fat jar,并通过java -cp target/scala-2.13/Test-assembly-0.1.0-SNAPSHOT.jar test.Test命令运行时,出现如下异常:
Exception in thread "main" java.lang.ExceptionInInitializerError at org.apache.lucene.codecs.Codec.getDefault(Codec.java:141) at org.apache.lucene.index.LiveIndexWriterConfig.<init>(LiveIndexWriterConfig.java:128) at org.apache.lucene.index.IndexWriterConfig.<init>(IndexWriterConfig.java:145) at test.Test$.delayedEndpoint$test$Test$1(Test.scala:17) at test.Test$delayedInit$body.apply(Test.scala:12) at scala.Function0.apply$mcV$sp(Function0.scala:42) at scala.Function0.apply$mcV$sp$(Function0.scala:42) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17) at scala.App.$anonfun$main$1(App.scala:98) at scala.App.$anonfun$main$1$adapted(App.scala:98) at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:575) at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:573) at scala.collection.AbstractIterable.foreach(Iterable.scala:933) at scala.App.main(App.scala:98) at scala.App.main$(App.scala:96) at test.Test$.main(Test.scala:12) at test.Test.main(Test.scala) Caused by: java.lang.IllegalArgumentException: An SPI class of type org.apache.lucene.codecs.Codec with name 'Lucene94' does not exist. You need to add the corresponding JAR file supporting this SPI to your classpath. The current classpath supports the following names: [] at org.apache.lucene.util.NamedSPILoader.lookup(NamedSPILoader.java:113) at org.apache.lucene.codecs.Codec$Holder.<clinit>(Codec.java:58) ... 17 more
问题
请问我哪里操作出错了?
内容的提问来源于stack exchange,提问作者Heitor Barbieri
相关产品推荐
相关产品推荐

