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

Quarkus and provided dependencies (sapjco3.jar)

我目前正在尝试将通过 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 initialization failed with java.lang.ExceptionInInitializerError: Illegal JCo archive "com.sap.sapjco3-3.1.jar". It is not allowed to rename or repackage the original archive "sapjco3.jar".

Whosebug 上已经有一些文章描述了这个问题,并且还有一个 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 initialization failed with java.lang.ExceptionInInitializerError: Illegal JCo archive "sapjco3-3.1.jar". It is not allowed to rename or repackage the original archive "sapjco3.jar".

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

mvn clean package

它基本上可以将 jar 文件复制到 lib 目录,如果我将副本更改为 pom.xml

中的另一个阶段
<phase>package</phase>
<goals>
      <goal>copy-dependencies</goal>
</goals>

但我首先收到构建警告:

[WARNING] [io.quarkus.arc.processor.BeanArchives] Failed to index com.sap.conn.jco.ext.DestinationDataProvider: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader

[INFO] [io.quarkus.arc.processor.IndexClassLookupUtils] Class for name: com.sap.conn.jco.ext.DestinationDataProvider was not found in Jandex index. Please ensure the class is part of the index.

之后出现以下错误:

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

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

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

首先,用系统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 arch 的配置文件。这是配置:

<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一次才能进行库复制。

我们一直在努力解决 sapjco3.jar 的命名问题,直到我偶然发现关于这个 link 的脚注: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 环境中没有针对该部分的解决方案,因为我还没有尝试过。