Quarkus 和提供的依赖项 (sapjco3.jar)

Posted

技术标签:

【中文标题】Quarkus 和提供的依赖项 (sapjco3.jar)【英文标题】:Quarkus and provided dependencies (sapjco3.jar) 【发布时间】:2021-03-08 05:51:57 【问题描述】:

我目前尝试将通过 RFC 连接到 SAP 系统的旧 Java EE 解决方案迁移到使用 Quarkus 的方法。 由于该项目使用 maven,我再次面临 SAP 的 sapjco3.jar 库的问题,该问题阻止了该库被重命名。 如果我像这样将库添加为依赖项

     <dependency>
          <groupId>com.sap</groupId>
          <artifactId>sapjco3</artifactId>
          <version>3.1</version>
      </dependency>

它将被添加到名为 com.sap.sapjco3-3.1.jar 的 lib 目录中。 不幸的是,这最终导致了异常

java.lang.ExceptionInInitializerError:JCo 初始化失败,出现 java.lang.ExceptionInInitializerError:非法 JCo 存档“com.sap.sapjco3-3.1.jar”。不允许重命名或重新打包原始存档“sapjco3.jar”。

*** 上已经有一些文章描述了该问题,并且还有一个 SAP 说明:https://apps.support.sap.com/sap/support/knowledge/en/2182414

所以我用“旧”方法解决了这个问题,将依赖项设置为提供并使用 maven-dependency-plugin 复制它。

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <includeArtifactIds>sapjco3</includeArtifactIds>
                        <outputDirectory>$project.build.directory/lib</outputDirectory>
                        <stripVersion>true</stripVersion>
                    </configuration>
                </execution>
            </executions>
        </plugin>

不幸的是,这不适用于 quarkus。 如果我使用,正在开发中

mvn quarkus:dev

提供的似乎被忽略了,我仍然收到消息。

JCo 初始化失败,出现 java.lang.ExceptionInInitializerError:非法 JCo 存档“sapjco3-3.1.jar”。不允许重命名或重新打包原始存档“sapjco3.jar”。

如果我打包并尝试将其部署到 docker-container

mvn clean package

如果我将副本更改为 pom.xml 中的另一个阶段,它基本上可以将 jar 文件复制到 lib 目录

<phase>package</phase>
<goals>
      <goal>copy-dependencies</goal>
</goals>

但我首先收到构建警告:

[警告] [io.quarkus.arc.processor.BeanArchives] 无法索引 com.sap.conn.jco.ext.DestinationDataProvider:ClassLoader 中不存在类 QuarkusClassLoader:部署类加载器

[INFO] [io.quarkus.arc.processor.IndexClassLookupUtils] 在 Jandex 索引中找不到名称的类:com.sap.conn.jco.ext.DestinationDataProvider。请确保该类是索引的一部分。

后来出现以下错误:

java.lang.NoClassDefFoundError: com/sap/conn/jco/ext/DestinationDataProvider

Quarkus 是否有解决方案来处理提供的依赖项并使用 maven 手动复制它们?

【问题讨论】:

【参考方案1】:

我在一个项目中使用了与 Quarkus 一起使用的 SAP 库。该解决方案并非特定于 Quarkus(Spring Boot 项目使用相同的解决方案)。

首先,使用系统 scome 定义库,使其名称不会被修改。

<dependency>
  <groupId>com.sap</groupId>
  <artifactId>sapjco3</artifactId>
  <version>3.1</version>
  <scope>system</scope>
  <systemPath>$project.build.directory/dependency/sapjco3.jar</systemPath>
</dependency>

然后,配置maven-dependency-plugin,在初始化阶段复制此路径下的库,并将其包含在最终包中。它还包含 sapjco3.jar 库使用的本机库的配置。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.1.1</version>
    <executions>
      <execution>
        <id>copy-jco-libs-unit-tests</id>
        <phase>initialize</phase>
        <goals>
          <goal>copy</goal>
        </goals>
        <configuration>
          <stripVersion>true</stripVersion>
          <outputDirectory>$lib.directory</outputDirectory>
          <artifactItems>
            <artifactItem>
              <groupId>com.sap.conn.jco</groupId>
              <artifactId>sapjco3</artifactId>
              <version>$sap.jco.version</version>
              <overWrite>true</overWrite>
              <destFileName>sapjco3.jar</destFileName>
            </artifactItem>
          </artifactItems>
        </configuration>
      </execution>
      <execution>
        <id>copy-native-lib-for-unit-tests</id>
        <phase>process-sources</phase>
        <goals>
          <goal>copy</goal>
        </goals>
        <configuration>
          <stripVersion>true</stripVersion>
          <outputDirectory>$native.lib.directory</outputDirectory>
          <artifactItems>
            <artifactItem>
              <groupId>com.sap.conn.jco</groupId>
              <artifactId>sapjco3</artifactId>
              <version>$sap.jco.version</version>
              <type>$envType</type>
              <classifier>$envClassifier</classifier>
              <overWrite>true</overWrite>
              <destFileName>$native.lib.filename.$envType</destFileName>
            </artifactItem>
          </artifactItems>
        </configuration>
      </execution>
    </executions>
  </plugin>

最后,通过配置文件配置应包含的本机库,需要一个按 OS/CPU 架构的配置文件。这是配置:

<profiles>
<!-- Manage JCO native deps by OS arch -->
<profile>
  <id>windows-x86_64</id>
  <activation>
    <os>
      <family>windows</family>
      <arch>x86_64</arch>
    </os>
  </activation>
  <properties>
    <envClassifier>ntamd64</envClassifier>
    <envType>dll</envType>
    <native.lib.filename>sapjco3</native.lib.filename>
  </properties>
</profile>
<profile>
  <id>windows-amd64</id>
  <activation>
    <os>
      <family>windows</family>
      <arch>amd64</arch>
    </os>
  </activation>
  <properties>
    <envClassifier>ntamd64</envClassifier>
    <envType>dll</envType>
    <native.lib.filename>sapjco3</native.lib.filename>
  </properties>
</profile>
<profile>
  <id>linux-x86_64</id>
  <activation>
    <os>
      <name>linux</name>
      <arch>x86_64</arch>
    </os>
  </activation>
  <properties>
    <envClassifier>linuxx86_64</envClassifier>
    <envType>so</envType>
    <native.lib.filename>libsapjco3</native.lib.filename>
  </properties>
</profile>
<profile>
  <id>linux-amd64</id>
  <activation>
    <os>
      <name>linux</name>
      <arch>amd64</arch>
    </os>
  </activation>
  <properties>
    <envClassifier>linuxx86_64</envClassifier>
    <envType>so</envType>
    <native.lib.filename>libsapjco3</native.lib.filename>
  </properties>
</profile>
<profile>
  <id>macosx-x86_64</id>
  <activation>
    <os>
      <name>mac os x</name>
      <arch>x86_64</arch>
    </os>
  </activation>
  <properties>
    <envClassifier>darwinintel64</envClassifier>
    <envType>dylib</envType>
    <native.lib.filename>libsapjco3</native.lib.filename>
  </properties>
</profile>
<profile>
  <id>macosx-amd64</id>
  <activation>
    <os>
      <name>mac os x</name>
      <arch>amd64</arch>
    </os>
  </activation>
  <properties>
    <envClassifier>darwinintel64</envClassifier>
    <envType>dylib</envType>
    <native.lib.filename>libsapjco3</native.lib.filename>
  </properties>
</profile>

有了这一切,测试工作,mvn quarkus:dev 工作,并且用 mvn clean package 完成的包工作。

注意 Maven 的初始化阶段默认不会启动,您需要调用一次mvn initialize 才能进行库复制。

【讨论】:

这对mvn quarkus:dev 非常有效。不幸的是mvn package 在复制到 target/lib 文件夹时仍然添加 com.sap.sapjco3.jar。我也会尝试为最后一个问题找到解决方案。 应该不是这样,你之前有没有跑过mvn clean 因为有一个 systemPath 并且 lib 范围是 system 它不会在打包时下载 lib 并使用系统路径中的那个所以它不会被重命名。 是的,我做了一个 mvn clean。尽管如此,我还是被 maven 强制进行本地安装 mvn install:install-file -DgroupId="com.sap" -DartifactId=sapjco3 -Dversion="3.1" -Dpackaging=jar -Dfile="target/dependency/sapjco3.jar",我猜即使在系统范围内,它也是从该本地存储库下载而不是? 使用建议的设置,使用mvn clean,然后使用mvn initialize,然后使用mvn quarkus:dev,最后使用mvn package。 sapjco3.jar 库在我的公司 Maven 存储库中,因此 maven 下载它,然后将其放入配置的 systemPath 中而不修改其名称。【参考方案2】:

我们一直在努力解决 sapjco3.jar 的命名问题,直到我偶然发现此链接上的脚注:https://help.mulesoft.com/s/article/It-is-not-allowed-to-rename-or-repackage-the-original-archive-sapjco3-jar

将您的工件命名为com.sap.conn.jco.sapjco3.jar,它将解决命名问题,因为即使添加了版本号,驱动程序也会接受此名称。

不过,您的下一个绊脚石将是本机库......我在 quarkus 环境中没有针对该部分的解决方案,因为我还没有尝试过。

【讨论】:

以上是关于Quarkus 和提供的依赖项 (sapjco3.jar)的主要内容,如果未能解决你的问题,请参考以下文章

DynamoDB + Quarkus - 奇数类型转换

通过JAVA连接SAP (sapjco3.jar在Windows和MacOS上的配置)

quarkus依赖注入之十:学习和改变bean懒加载规则

未找到功能性渠道服务提供者。尝试添加对 grpc-okhttp、grpc-netty 或 grpc-netty-shaded 工件的依赖项

quarkus依赖注入之六:发布和消费事件

quarkus依赖注入之六:发布和消费事件