当前位置: 首页 > 知识库问答 >
问题:

Quarkus Gradle插件:覆盖来自依赖库的重复文件条目

荆修明
2023-03-14

我能告诉Quarkus Gradle插件(Gradle quarkusDevgradlew quarkusBuild-Dquarkus.package.uber jar=true)使用我自己提供的资源,而不是在重复时从依赖项jar中选择资源吗?

我在构建uber-jar时收到这些消息:

Duplicate entry META-INF/org.apache.uima.fit/types.txt entry from de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.segmentation-asl::jar:1.10.0(runtime) will be ignored. Existing file was provided by de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.syntax-asl::jar:1.10.0(runtime)
Duplicate entry META-INF/org.apache.uima.fit/types.txt entry from de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.lexmorph-asl::jar:1.10.0(runtime) will be ignored. Existing file was provided by de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.syntax-asl::jar:1.10.0(runtime)
Duplicate entry META-INF/org.apache.uima.fit/types.txt entry from de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.metadata-asl::jar:1.10.0(runtime) will be ignored. Existing file was provided by de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.syntax-asl::jar:1.10.0(runtime)
Duplicate entry META-INF/org.apache.uima.fit/types.txt entry from de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.ner-asl::jar:1.10.0(runtime) will be ignored. Existing file was provided by de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.syntax-asl::jar:1.10.0(runtime)

这些DKPro/uimaFIT库是NLP库,它们自带了自己的META-INF/org。阿帕奇。尤玛。适合/类型。txt文件。你应该自己合并这些文件并添加自己的类型,然后只在uber jar中包含这个新合并的文件,或者作为类路径中的第一个文件。

application.properties中有一个选项quarkus.package.user-配置-忽略-条目,但它也删除了我自己提供的文件。所以这不是我想要的(另请参阅https://github.com/quarkusio/quarkus/blob/master/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java#L186)。我还没有检查gradle qukusDev的来源,但它会导致相同的运行时异常。

对于其他使用uimaFIT的人来说,这是不正确的META-INF/org。阿帕奇。尤玛。适合/类型。txt文件会导致类似于org的错误。阿帕奇。尤玛。分析引擎。AnalysisEngineProcessException:JCas类型“org.apache.uima.conceptMapper.support.tokenizer.TokenAnnotation”在Java代码中使用,但未在XML类型描述符中声明

所以我的问题是,我如何告诉Gradle或Quarkus使用我自己提供的这个文件,而不是从依赖项jar中随机选择一个文件?

用Kotlin DSL编写的Gradle脚本示例。任务generateNlpFiles和函数joinResources根据uimaFIT的要求,自动将src/main/typesystem中的XML文件生成Java源文件,并加入重复的资源,如META-INF/org。阿帕奇。尤玛。适合/类型。txt转换为/generated/resources/uimafit/。你不需要太仔细地看它们。

import java.io.FileOutputStream
import java.net.URLClassLoader
import org.apache.commons.io.IOUtils

plugins {
    id("java")
    id("io.quarkus")
    id("eclipse")
}

repositories {
    jcenter()
    // required for downloading OpenNLP models
    maven("https://zoidberg.ukp.informatik.tu-darmstadt.de/artifactory/public-releases/")
}

group = "com.example"
version = "0.0.0-SNAPSHOT"

java.sourceCompatibility = JavaVersion.VERSION_11
java.targetCompatibility = JavaVersion.VERSION_11

dependencies {
    val quarkusPlatformGroupId: String by project
    val quarkusPlatformArtifactId: String by project
    val quarkusPlatformVersion: String by project
    // Quarkus dependencies
    implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
    implementation("io.quarkus:quarkus-jaxb")
    implementation("io.quarkus:quarkus-jackson")
    implementation("io.quarkus:quarkus-resteasy")
    implementation("io.quarkus:quarkus-jdbc-mariadb")
    implementation("io.quarkus:quarkus-resteasy-jsonb")
    implementation("io.quarkus:quarkus-smallrye-openapi")
    implementation("io.quarkus:quarkus-container-image-docker")
    // UIMA
    implementation("org.apache.uima:uimaj-core:2.10.3")
    implementation("org.apache.uima:ConceptMapper:2.10.2")
    implementation("org.apache.uima:uimafit-core:2.4.0")
    // DKPro
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.io.xmi-asl:1.10.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.api.metadata-asl:1.10.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.langdetect-asl:1.10.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.icu-asl:1.10.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-asl:1.10.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-model-tagger-de-maxent:20120616.1")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-model-tagger-en-maxent:20120616.1")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-asl:1.10.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-model-ner-de-nemgp:20141024.1")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-model-ner-en-location:20100907.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-model-ner-en-organization:20100907.0")
    implementation("de.tudarmstadt.ukp.dkpro.core:de.tudarmstadt.ukp.dkpro.core.opennlp-model-ner-en-person:20130624.1")
    // tests
    testImplementation("io.quarkus:quarkus-junit5")
    testImplementation("io.rest-assured:rest-assured")
    // for generating NLP type system during compile time
    compileOnly("org.apache.uima:uimaj-tools:2.10.4")
}

// joins resource files from classpath into single file
fun joinResources(classLoader: URLClassLoader, inputResourceName: String, outputFile: File) {
    val outputStream = FileOutputStream(outputFile)
    val resources = classLoader.findResources(inputResourceName).toList()
    resources.forEach {
        val inputStream = it.openStream()
        IOUtils.copy(inputStream, outputStream)
        outputStream.write('\n'.toInt());
        inputStream.close()
    }
    outputStream.close()
}

// generate NLP type system from XML files and join uimaFIT files
val generateNlpFiles = task("generateNlpFiles") {
    inputs.files(fileTree("src/main/typesystem"))
    inputs.files(fileTree("src/main/resources"))
    outputs.dir("${buildDir}/generated/sources/jcasgen/main/")
    outputs.dir("${buildDir}/generated/resources/uimafit/")

    val compileClasspath = project.sourceSets.main.get().compileClasspath
    val runtimeClasspath = project.sourceSets.main.get().runtimeClasspath
    val compileClassLoader = URLClassLoader(compileClasspath.map{ it.toURI().toURL() }.toTypedArray())
    val runtimeClassLoader = URLClassLoader(runtimeClasspath.map{ it.toURI().toURL() }.toTypedArray())

    // from XML files in src/main/typesystem/ generate Java sources into build/generated/sources/jcasgen/main/
    val jCasGen = compileClassLoader.loadClass("org.apache.uima.tools.jcasgen.Jg").newInstance()
    fileTree("src/main/typesystem").forEach() { typeSystemFile ->
        doFirst {
            // see https://github.com/Dictanova/gradle-jcasgen-plugin/blob/master/src/main/groovy/com/dictanova/jcasgen/gradle/JCasGenTask.groovy#L45
            val jcasgeninput = "${typeSystemFile}"
            val jcasgenoutput = "${buildDir}/generated/sources/jcasgen/main/"
            val jcasgenclasspath = "${runtimeClasspath.asPath}"
            val arguments: Array<String> = arrayOf("-jcasgeninput", jcasgeninput, "-jcasgenoutput", jcasgenoutput, "-jcasgenclasspath", jcasgenclasspath)
            val main1 = jCasGen.javaClass.getMethod("main1", arguments.javaClass)
            main1.invoke(jCasGen, arguments)
        }
    }

    // collect types.txt and components.txt from classpath and join them in build/generated/resources/uimafit/META-INF/org.apache.uima.fit/
    val uimafitDir = "${buildDir}/generated/resources/uimafit/META-INF/org.apache.uima.fit"
    mkdir(uimafitDir)
    joinResources(runtimeClassLoader, "META-INF/org.apache.uima.fit/types.txt", File("${uimafitDir}/types.txt"))
    joinResources(runtimeClassLoader, "META-INF/org.apache.uima.fit/components.txt", File("${uimafitDir}/components.txt"))
}

eclipse {
    project {
        natures(
                "org.eclipse.wst.common.project.facet.core.nature",
                "org.eclipse.buildship.core.gradleprojectnature"
        )
    }
    classpath {
        file.withXml {
            val attributes = mapOf("kind" to "src", "path" to "build/generated/sources/jcasgen/main")
            this.asNode().appendNode("classpathentry", attributes)
        }
    }
}

tasks {
    compileJava {
        options.encoding = "UTF-8"
        options.compilerArgs.add("-parameters") // was in original Quarkus Gradle file, not sure what this does
        dependsOn(generateNlpFiles)
        // add generated sources to source sets
        sourceSets["main"].java.srcDir(file("${buildDir}/generated/sources/jcasgen/main/"))
        sourceSets["main"].resources.srcDir(file("${buildDir}/generated/resources/uimafit/"))
    }
    compileTestJava {
        options.encoding = "UTF-8"
    }
    "eclipse" {
        dependsOn(generateNlpFiles)
    }
}

一种解决方法是使用gradlew quarkusBuild-Dquarkus。包裹uber jar=true,条目位于quarkus中。包裹用户配置了忽略条目并将我自己的文件手动添加到结果jar中,但这对gradle quarkusDev不起作用。

我正在使用Quarkus 1.3.2,因为Quarkus 1.4.1无法处理多个资源目录(另请参阅https://github.com/quarkusio/quarkus/blob/master/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusDev.java#L391),这是我的项目所需要的。

我还尝试排除带有Gradle JarJar插件的文件,比如https://github.com/shevek/jarjar,但无法让它们运行。


共有1个答案

马星阑
2023-03-14

现在,你不能,它只是从提供它的罐子里拿一个。

您能否在我们的跟踪器中创建一个功能请求:https://github.com/quarkusio/quarkus/issues/new?assignees=

听起来像是有用的东西。

谢谢

 类似资料:
  • 我有一个Maven插件,它在POM文件中配置为 现在我想从命令行覆盖那个,所以我运行 我可以看到的值仍然是,而不是。可以从命令行覆盖配置参数吗?

  • 我正在使用Azure Blob存储来上传/下载文件。问题是,如果我上传到azure blob中的任何新文件与已经上传的文件同名,那么它会自动覆盖以前上传的文件的内容。 null 因此,如果我上传一个名为“file1.docx”的新文件,它们有不同的内容。那么blob存储将替换以前上传的file1.docx。所以在这种情况下,我丢失了以前上传的文件。 blob存储有什么方法可以自动检测到有重复,这样

  • 依赖 AdminLTE 依赖两个主要的框架。下载的软件包中已经包含这两个库,因此你不必手动下载它们。 Bootstrap 4 jQuery 3.3.1+ Popper.js 1.14.7+ 下面列出了所有其他插件 插件 AdminLTE 使用以下插件。相关文档,更新或许可证信息,请访问提供的链接。 你需要手动加载插件的 js/css 文件。 AdminLTE 不会自动加载所有插件,这会造成页面加载

  • BFA插件似乎仍然使用jackson2-api插件中的jackson类,而不是直接依赖maven。导致https://issues.jenkins-ci.org/browse/jenkins-62214在MongoJack内部的导入中使用了错误的jackson版本,导致缺少方法: Jenkins的类路径中Jackson2-api插件的依赖性是否更高?

  • 我试图使用一个目录文件来覆盖XML文件中的DTD位置。我尝试按照这里的所有提示使用saxon内置目录功能,但一直无法让它工作。我简化为这个简单的例子: 撒克逊语的确认版本: 我的目录文件。我试图简化为最简单的(uriSuffix): 已确认的解析器位于类路径中,并且在目录中的行为符合预期: 简单的test.xml文件: 简单test.xql: 结果: 我尝试了几种不同的编目技术来覆盖DTD URI

  • 问题内容: 我有具有main.c main.h和CMakeLists.txt的示例程序目录 main.h的内容是 main.c的内容是 和CMakeLists.txt 但是cmake不会在修改头文件时重建main.c。我希望它自动生成头文件依赖项。有可能使用cmake吗? 如果没有,还有其他工具可以做到吗? 问题答案: 如我的评论中所述,我已经尝试了您的示例,并且一切正常:如果进行了修改,则将重新