【问题标题】:Having Spring Gradle dependency container before JRE container results in compilation errors在 JRE 容器之前拥有 Spring Gradle 依赖容器会导致编译错误
【发布时间】:2016-06-07 14:34:48
【问题描述】:

我正在将一个 Java 项目从 Ant 转换为 Gradle。我们团队选择的 IDE 是 Eclipse。我已经为 Eclipse 安装了 Spring Gradle 插件,应用了 Gradle 项目性质并启用了依赖项管理。结果是一些编译错误。

出现编译错误是因为 Gradle 依赖容器在 eclipse 类路径中的 JRE 容器之前。类路径中的一些 jar 包含应该来自 rt.jar 的类(它们与我们的代码不兼容,可能是旧版本)。

当依赖管理被禁用时,gradle 依赖出现在 JRE 容器之后并且它编译没有错误。这也与我使用 Eclipse/Maven/m2e 一致,其中 Maven 依赖容器位于 eclipse 中的 JRE 容器之后。

这是插件的默认行为(将 gradle 容器放在 JRE 之前)吗?有办法改吗?

我尝试在我的 build.gradle 中使用 eclipse 钩子(whenMerged 和 withXml)执行此操作,但这些似乎在 gradle 依赖项被容器条目替换之前执行。

【问题讨论】:

  • 听起来顺序是“JRE 之前的 Gradle 依赖项”不正确,可能被视为错误。您可能想在这里提出错误报告:issuetracker.springsource.com/browse/STS。我试图在下面的回答中提供一些关于如何解决它的建议。即使这对你有用,也许它仍然值得一个错误报告?
  • 感谢 Kris,我提出了一个错误。我也会回应你的变通方法。
  • 作为参考,提出的问题是issuetracker.springsource.com/browse/STS-4332

标签: java eclipse gradle sts-springsourcetoolsuite gradle-eclipse


【解决方案1】:

这是我交换容器的代码。由于几个原因,它可能有点冗长。 1. 我是来自 Java 背景的 Groovy 新手。 2. Gradle 对我自己和团队来说都是新手,我想清楚它在做什么。

// Swap the order of the JRE and classpathcontainer
// https://issuetracker.springsource.com/browse/STS-4332
task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
    doLast {
        def cp = new XmlParser().parse(file(".classpath"))
        def container
        def cons = cp.classpathentry.findAll { it.@kind == "con" }
        cons.find {
            if (it.@path.equals("org.springsource.ide.eclipse.gradle.classpathcontainer")) {
                println "found Gradle dependency container"
                container = it
            } else if (it.@path.contains("JRE_CONTAINER")) {
                if (container == null) {
                    println "found JRE container before Gradle dependency container, nothing to do"
                    // Return true to end the loop (return by itself is not enough)
                    return true
                }
                println "found JRE container, swap with Gradle dependency container"
                container.replaceNode(it)
                it.replaceNode(container)
                // Return true to end the loop (return by itself is not enough)
                return true
            }
            return false
        }
        def builder = new StreamingMarkupBuilder()
        builder.encoding = "UTF-8"
        file(".classpath").withWriter {writer ->
             writer << builder.bind { mkp.xmlDeclaration() }
             def printer = new XmlNodePrinter(new PrintWriter(writer))
             // println cp
             printer.print(cp)
        }
    }
}

【讨论】:

    【解决方案2】:

    对订单有一些控制,但对您来说可能不够精确。右键单击项目并选择“属性 >> Gradle”。

    然后选择其中一个排序选项,例如“按路径字母顺序”。更改此选项后,执行“Gradle >> Refresh All”。

    如果您选择“由 BuildScript 返回”,我收集的内容一定是您所拥有的。顺序将被颠倒(JRE 之前的 Gradle)。这里有一个难题,即构建脚本实际上并没有返回“gradle依赖”容器(仅返回其内容),因此构建脚本并没有真正定义顺序。

    不幸的是,您可能有理由选择该选项并对容器内的依赖项进行排序可能实际上不是一个可行的解决方案。

    如果是这样,您可以尝试第二件事。

    当您导入项目时,“导入选项”下的“导入向导”会出现“运行后”。您可以尝试使用此处指定的任务在导入结束时修改 .classpath 文件(它也将在刷新时执行)。

    最后……最后一个建议。你试过BuildShip吗?也许它更适合您的项目。

    【讨论】:

    • 感谢 Kris,我没想过要尝试更改排序选项。将其设置为按路径解析(根据您的建议)有效。我很高兴将其用作解决方法。我也会试试你的第二个建议。对于 BuildShip,它是第一选择。不幸的是,由于 Eclipse 设置文件中硬编码文件位置的问题,我在短期内放弃了它。如果这个问题得到解决,那么我一定会重新审视它。我相信未来这将是最好的解决方案。
    • “我在短期内放弃了它,因为 Eclipse 设置文件中的硬编码文件位置存在问题”我相信你确保有一个 BuildShip 错误报告。如果 BuildShip 开发人员不知道这是一个问题,他们就不可能解决它。
    • 是的,已经被别人提出了。围绕它有一些争论,我不认为 BuildShip 开发人员认为是一个错误。现在我在等着看结果如何。我添加了一个用于交换 JRE 和 Gradle 容器的 afterEclipseImport,我很高兴现在将其作为一种解决方法。感谢您的帮助。
    猜你喜欢
    • 2015-10-03
    • 2019-12-05
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    相关资源
    最近更新 更多