如何使用 Maven 创建 JarJar 工件,其中工件的使用不会拉动传递依赖项?

发布于 2024-11-02 18:40:58 字数 507 浏览 1 评论 0原文

我目前有一个 Java 测试库,它是用 Maven 构建的,并作为 jar 分发。我的项目依赖于一个非常常见的库(Objectweb ASM),并且我遇到过以下问题:早期且不兼容的 ASM 版本已位于类路径中。因此,我开始使用 jarjar-maven-plugin 创建 jar,重新打包ASM 内部不能与 ASM 的其他版本冲突。

这执行得很好,我的库可以作为依赖项引入,没有问题。

但是,由于我的项目对 ASM 具有编译范围依赖项,因此每当客户端项目添加我的库时,传递依赖项也会全部被拉入。因此,假设,如果他们使用特定版本的 ASM,并且他们还将我依赖的版本添加到类路径中,他们就会有未定义的行为。我想避免这种情况,并允许客户端依赖于 JarJar'd 工件,而不会让 Maven 不必要地和潜在地危险地拉下传递依赖项。

如何创建用户可以依赖的 JarJar 工件,而无需拉动传递依赖项?

I currently have a Java testing library which is built with Maven, and distributed as a jar. My project depends on a very common library (Objectweb ASM), and I've experienced problems where an earlier and incompatible version of ASM is already on the classpath. Thus, I've started usings the jarjar-maven-plugin to create jar, repackaging ASM internally where it cannot conflict with another version of ASM.

This executes fine, and my library can be pulled in as a dependency with no problem.

However, because my project has compile-scope dependencies on ASM, whenever a client project adds my library, the transitive dependencies are all pulled in as well. So, hypothetically, if they use a particular version of ASM, and they also add the version I depend on to the classpath, they have undefined behaviour. I'd like to avoid this situation, and allow clients to depend on the JarJar'd artifact without having Maven pulling down the transitive dependencies both unnecessarily and potentially dangerously.

How do I create a JarJar'd artifact which users can depend on without pulling transitive dependencies?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

少跟Wǒ拽 2024-11-09 18:40:58

我通过放弃 jarjar-maven-plugin 并恢复到 maven-shade-plugin 找到了这个问题的解决方案。这允许在您自己的命名空间中重新打包类,设置 jar 的主类,最重要的是,重写生成的 pom 以包含现在捆绑的编译时依赖项。

我的 pom.xml 实现这一点的部分是:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>

            <shadedArtifactAttached>false</shadedArtifactAttached>
            <createDependencyReducedPom>true</createDependencyReducedPom>

            <relocations>
                <relocation>
                    <pattern>org.objectweb.asm</pattern>
                    <shadedPattern>${repackage.base}.org.objectweb.asm</shadedPattern>
                </relocation>
            </relocations>
            <transformers>
                <transformer
                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>${package.base}.my.MainClass</mainClass>
                </transformer>
            </transformers>
        </configuration>
    </execution>
</executions>

此配置的重要部分是:

  • shadedArtifactAttached,当设置为 false 时,意味着着色 jar 将替换通常生成的主要工件。默认为 false,但值得指出。
  • createDependencyReducedPom 当设置为 true 时,意味着当部署或安装阴影 jar 时,部署的 pom.xml 将不包含已重新打包到 jar 中的编译范围依赖项。
  • relocation 这些元素配置如何将依赖项中的文件重新打包到阴影 jar 中。在上面的示例中,任何规范名称以 org.objectweb.asm 开头的类都将被移动到 ${package.base}.org.objectweb.asm ,因此当打包在 jar 中将在 jar 内具有等效的文件路径。

使用此配置,当部署我的项目时,当客户端声明对我的项目的编译范围依赖项时,它只会引入阴影 jar,而不会引入传递依赖项。

I found a solution to this problem by ditching the jarjar-maven-plugin, and reverting to the maven-shade-plugin. This allows repackaging classes within your own namespace, setting the main class of the jar, and crucially, rewriting the generated pom to not include the compile time dependencies which are now bundled.

The part of my pom.xml which acheived this is:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>

            <shadedArtifactAttached>false</shadedArtifactAttached>
            <createDependencyReducedPom>true</createDependencyReducedPom>

            <relocations>
                <relocation>
                    <pattern>org.objectweb.asm</pattern>
                    <shadedPattern>${repackage.base}.org.objectweb.asm</shadedPattern>
                </relocation>
            </relocations>
            <transformers>
                <transformer
                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>${package.base}.my.MainClass</mainClass>
                </transformer>
            </transformers>
        </configuration>
    </execution>
</executions>

The important parts of this configuration are:

  • shadedArtifactAttached which when set to false, means the shaded jar will replace the main artifact that would normally be produced. This defaults to false but it's worth pointing out.
  • createDependencyReducedPom which when set to true means that when the shaded jar is deployed or installed, the pom.xml which is deployed will not include the compile-scope dependencies which have been repackaged into the jar.
  • relocation these elements configure how files within the dependencies are repackaged into the shaded jar. In the above example any class whose canonical name begins with org.objectweb.asm will be moved to ${package.base}.org.objectweb.asm, and thus when packaged in the jar will have the equivalent file path within the jar.

With this configuration, when my project is deployed, when clients declare a compile-scope dependency on my project, it only pulls in the shaded jar, and no transitive dependencies.

任性一次 2024-11-09 18:40:58

考虑尝试使用 maven-shade-plugin,它允许各种精细控制。

Consider trying the maven-shade-plugin instead, which allows all sorts of fine control.

丑丑阿 2024-11-09 18:40:58

也许设置 属性适合您的情况。在您的 java 测试库 pom.xml 中指定类似以下内容:

  <dependencies>
    <dependency>
      <groupId>asm.group</groupId>
      <artifactId>asm</artifactId>
      <version>x.y</version>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>

Perhaps setting the <optional> attribute will work in your case. Specifying something like the following in your java testing library pom.

  <dependencies>
    <dependency>
      <groupId>asm.group</groupId>
      <artifactId>asm</artifactId>
      <version>x.y</version>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文