【问题标题】:Liquibase scripts not being executed in Spring boot multi module project fat jar在 Spring Boot 多模块项目 fat jar 中未执行 Liquibase 脚本
【发布时间】:2019-01-10 18:24:44
【问题描述】:

我有一个与 Liquibase 集成的多模块 Spring Boot 应用程序。从 IDE 运行它时,liquibase 脚本工作得很好。但是,当从 jar 中运行它时,它们不会。经过一番调查,似乎 liquibase 本身在尝试从嵌入式 jar 中读取时存在重大问题。 liquibase 脚本本身存在于 fat jar 内的嵌入式 jar 中,主 xml 文件如下所示:

<includeAll path="classpath*:config/liquibase/changelog/"/>

经过进一步调查,我将所有问题缩小到 liquibase 本身的问题。我使用的版本是 liquibase-3.6.2。我怀疑 liquibase 中存在的错误属于以下类: liquibase.resource.ClassLoaderResourceAccessor 我把它缩小到的方法是

public Set<String> list(String relativeTo, String path, boolean includeFiles, boolean includeDirectories, boolean recursive) throws IOException

此方法的输入如下:

relativeTo = null
path = jar:file:/C:/#{SOME_PATH}/xxx-1.0.0.0-SNAPSHOT.jar!/BOOT-INF/lib/yyy-1.0.0.0-SNAPSHOT.jar!/config/liquibase/changelog/
includeFiles = true
includeDirectories = false
recursive = true

当然,您需要将#{SOME_PATH} 替换为磁盘上的有效路径。出于安全目的,我将其编辑了。我们已经可以注意到,liquibase 发现在 fat jar xxx 内的嵌入式 yyy jar 中可能有一些脚本。

这个方法的问题是它不是返回 jar 中的 XML 脚本,而是返回 yyy jar 本身。这只会在稍后的代码中导致错误,因此我假设此方法负责查找 XML 文件(因为如果我直接从 IDE 而不是从 jar 运行我的项目,它会成功)。

我注意到主要问题的行是第 134 行:

String returnPath = SpringBootFatJar.getSimplePathForResources(entry.getName(), path);

此时path变量被破坏,SpringBootFatJar返回一个被破坏的返回路径。在下面的部分中,我将描述会发生什么:

  • 在第 105 行,路径变量被拆分并变为“config/liquibase/changelog/”。根据第 134 行的使用方式和 SpringBootFatJar 类中的 javadoc,这可能非常糟糕。
  • 快进到第 134 行,entry.getName() 返回“BOOT-INF/lib/yyy-1.0.0.0-SNAPSHOT.jar”,路径同上。基于 SpringBootFatJar 中的 javadoc,这是非常糟糕的。
  • 在第 134 行之后,returnPath 变为“BOOT-INF/lib/yyy-1.0.0.0-SNAPSHOT.jar”,其余为历史记录,因为第 143 行的nestedEntries 永远不会以该路径开头。

不幸的是,我本周没有时间进一步调查这个问题,我想在 stackoverflow 上发布这个问题,看看是否有其他人有这个问题,是否是一个已知的 liquibase 错误,以及是否有一个简单的解决方法它。下周我将尝试自己进一步调查,并检查是否所有这些问题都来自第 105 行看似糟糕的分割路径参数,因为输入的路径参数中有两个“!/”实例。

谢谢

【问题讨论】:

    标签: spring spring-boot liquibase


    【解决方案1】:

    万一其他人偶然发现了这个问题,他们在 master 上修复了它,但还没有发布。我们所做的是从 github 获取他们的 master 并从中编译一个 SNAPSHOT。撰写此评论时的结果是 3.7.0-SNAPSHOT。我们将使用官方的 3.7.0 版本。

    【讨论】:

      【解决方案2】:

      显然它仍然不适用于当前的 liquibase 版本 (3.8.5)。更改日志不会从 spring boot fat jar 中的其他 jar 中提取。 一种解决方法可能是覆盖 SpringLiquibase.java 文件并手动更新 jar 列表。可以在这里找到详细信息:http://www.it-surmann.com/spring-boot/fix-liquibase-includeall-in-a-spring-boot-project_1002.html

      【讨论】:

        猜你喜欢
        • 2017-08-16
        • 2014-11-27
        • 1970-01-01
        • 1970-01-01
        • 2018-10-30
        • 2020-12-24
        • 2018-10-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多