sbt-assembly and Lucene“类型为org.apache.lucene.codecs.Codec且名为'Lucene 94'的SPI类不存在,

fcipmucu  于 2022-12-23  发布在  Lucene
关注(0)|答案(1)|浏览(228)

操作系统:Ubuntu 22.10 openjdk版本"19.0.1" 2022年10月18日scala:2.13.10ApacheLucene:9.4.2
我以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()

  // Now search the index:
  val ireader: DirectoryReader = DirectoryReader.open(directory)
  val isearcher: IndexSearcher = new IndexSearcher(ireader)

  // Parse a simple query that searches for "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)

  // Iterate through the results:
  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文件:

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文件中包括:

assembly / assemblyMergeStrategy  := {
  case PathList("META-INF", xs @ _*) => MergeStrategy.discard
  case _ => MergeStrategy.first
}

之后,程序的编译和执行正常:

sbt "runMain test.Test"

但是如果我想创建一个fat jar文件并执行它,我得到了下面的异常:
插件.科技咨询机构:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.0")
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

我做错什么了?谢谢。

x8diyxa7

x8diyxa71#

case PathList("META-INF", xs @ _*) => MergeStrategy.discard意味着忽略所有META-INF目录(其全部内容)。这是危险的。依赖项lucene-corelucene-sandbox在其META-INF中具有服务文件。您应该更有选择性地忽略哪些内容。尝试仅忽略Java 9+文件module-info.class

assembly / assemblyMergeStrategy := {
  case x if x.endsWith("module-info.class") => MergeStrategy.discard
  case x =>
    val oldStrategy = (assembly / assemblyMergeStrategy).value
    oldStrategy(x)
}

或至少取消忽略META-INF/services子目录

assembly / assemblyMergeStrategy  := {
  case PathList("META-INF", "services", xs @ _*) => MergeStrategy.concat
  case PathList("META-INF", xs @ _*) => MergeStrategy.discard
  case _ => MergeStrategy.first
}

Drools fat jar nullpointer KieServices
Run Drools Kie project from fat jar

相关问题