在Maven尝试解决之前,将本地jar依赖项作为生命周期的一部分进行安装

在Maven尝试解决之前,将本地jar依赖项作为生命周期的一部分进行安装

问题描述:

由于两个依赖项之间存在一些不兼容性,我被迫制作了一个依赖项的着色版本。这意味着我的项目现在依赖于本地.jar文件。

Because of some incompatibilities between two dependencies, I was forced to make a shaded version of one of my dependencies. This means my project now depends on a local .jar file.

我之前完全没法使用 mvn install-file 将此.jar安装到我的本地存储库,然后再运行 mvn install

I was previously perfectly fine with just using mvn install-file to install this .jar to my local repository, before running mvn install:

mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile=lib/my-custom-jar-1.0.0.jar
mvn install

但是,我的项目现在将位于自动构建服务器上,该服务器只会执行 mvn clean install ,没有别的。

However, my project will now be on an automated build server, who will only do mvn clean install and nothing else.

通过寻找很长一段时间,我找到了几个解决方案,但没有一个是完美的。

By looking for a long while, I have found several solutions, but none are perfect.

我将在下面写下我找到的解决方案作为答案,但我发布了这个问题,希望有人能更好地解决这个问题。

I will be writing down the solutions I found as an answer below, but I'm posting this question hoping that somebody has a better idea to solve this problem.

以下是我尝试过的几个解决方案,但对我的用途不太好:

Here's the few solutions I tried, but weren't great for my uses:

想法是将安装文件目标作为安装生命周期的一部分添加到pom中:

The idea is to add the install-file goal as part of the install lifecycle by adding this to the pom:

<plugin>
  <artifactId>maven-install-plugin</artifactId>
  <version>2.5.2</version>
  <executions>
    <execution>
      <phase>validate</phase>
      <goals>
        <goal>install-file</goal>
      </goals>
      <configuration>
        <file>lib/my-custom-jar-1.0.0.jar</file>
      </configuration>
    </execution>
  </executions>
</plugin>

[...]

<dependency>
  <groupId>org.me</groupId>
  <artifactId>my-custom-jar</artifactId>
  <version>1.0.0</version>
</dependency>

然而,即使是第一个目标,验证,Maven将在安装文件运行之前尝试解决依赖关系。

However, even on the very first goal, validate, Maven will try to resolve dependencies before install-file is run.

我看到了使用清洁目标的想法。令人讨厌的是,当您执行单独的命令( mvn clean&& mvn install )时,这会有效,但是如果你在一个mvn命令中同时执行这两个命令( mvn clean安装),Maven将首先解决依赖关系。可以有解决方案吗?

I saw the idea of using the clean goal. Annoyingly, this works when you do separate commands (mvn clean && mvn install) but if you do both in one mvn command (mvn clean install), Maven will resolve dependencies first. Could there be a solution to this?

这个想法,在此Stack Overflow答案中看到,是您在父pom中安装文件,并在您的子pom中添加依赖项。 Maven将只分别解决依赖关系,所以这应该有效。

The idea, seen in this Stack Overflow answer, is that you install-file in your parent pom, and add the dependency in your child pom. Maven will only resolve dependencies separately so this should work.

然而我的项目是一个单独的模块,只是为了解决这个问题而做一个假的父母似乎过于复杂化和一个丑陋的黑客。

However my project is a single module, and making a fake parent just to solve this problem seems like an over-complication and an ugly hack.

<dependency>
  <groupId>org.me</groupId>
  <artifactId>my-custom-jar</artifactId>
  <version>1.0.0</version>
  <scope>system</scope>
  <systemPath>${basedir}/lib/my-custom-jar-1.0.0.jar</systemPath>
</dependency>

虽然这看起来完全是出于这种情况,系统范围实际上是期望依赖在你将运行你的项目的每个系统上,因此它不会打包在.war中,使我的项目无法正常运行。

Although this looks like this was made exactly for this kind of situation, the system scope actually expects the dependency to be on every system where you'll run your project, and so it will not be packaged in the .war, making my project non-functional.

此处的自定义插件包含.war文件中的.jar,然后在编译时将其添加到您的pom中。

This custom plugin found here includes a .jar in your .war file, then adds it to your pom during compilation.

<plugin>
  <groupId>com.googlecode.addjars-maven-plugin</groupId>
  <artifactId>addjars-maven-plugin</artifactId>
  <version>1.0.5</version>
  <executions>
    <execution>
      <goals>
        <goal>add-jars</goal>
      </goals>
      <configuration>
        <resources>
          <resource>
            <directory>${basedir}/lib</directory>
            <includes>
              <include>**/my-custom-jar-1.0.0.jar</include>
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

这适用于大多数正常情况。但是,由于您没有在实际的pom中指示对自定义.jar的任何依赖性,因此您的IDE将缺少很多类,因此您需要手动将自定义.jar添加为外部库。

This will work in most normal cases. However, since you don't indicate any dependency to your custom .jar in your actual pom, your IDE will be missing a lot of classes, so you'll need to manually add your custom .jar as an external library.

这仍然有点hacky并且不适用于某些特殊情况(hpi:运行Jenkins调试例如抛出一些错误)。另外我更喜欢我的代码不依赖第三方插件。

This still is somewhat hacky and does not work with some special cases (hpi:run for Jenkins debugging for example throws some errors). Plus I preferred that my code did not rely on third-party plugins.

我在创建这篇文章后找到了这个解决方案,我很满意。

I found this solution after creating this post, and I'm pretty happy with it.

这与在我的问题中执行 mvn install-file 命令的结果非常相似,除了您保存结果并通过安装将其保留为项目的一部分位于项目内的存储库中的自定义库。

This is pretty much the same result as doing the mvn install-file command in my question, except you save the result and keep it as part of your project by installing the custom library in a repository located inside your project.

您需要使用此命令预安装库。

You will need to pre-install the library using this command.

mvn org.apache.maven.plugins:maven-install-plugin:2.5.1:install-file \
-Dfile=lib/cloudfoundry-client-lib-shaded-1.0.3.jar \
-DlocalRepositoryPath=lib

一旦这是完成您的存储库是在lib文件夹中创建的,您不需要再次执行此命令。

Once that's done your repository is created in the lib folder and you won't need to do this command ever again.

表示你想在你的pom中使用这个存储库:

Indicate that you want to use this repository in your pom:

<repository>
  <id>Local repository</id>
  <url>file://${basedir}/lib</url>
</repository>

[...]

<dependency>
  <groupId>org.me</groupId>
  <artifactId>my-custom-jar</artifactId>
  <version>1.0.0</version>
</dependency>

此解决方案强制您向SCM提交一堆额外的文件夹,但这是一个可管理的缺点对我来说,我对此感到满意。

This solution forces you to commit a bunch of extra folders to your SCM, but that was a manageable drawback for me and I'm satisfied with this.