java - 読み方 - mvn コマンド




Mavenを使用して依存関係を持つ実行可能なJARを作成するにはどうすればよいですか? (20)

私は配布用に単一の実行可能なJARにプロジェクトをパッケージ化したいと思っています。

どのようにMavenプロジェクトパッケージをすべての依存関係JARを出力JARに作ることができますか?


Maven-Shadeプラグインを使用して、以下のようなuber jarを構築することができます

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

dependency-pluginを使用すると、すべての依存関係をパッケージ段階の前に別のディレクトリに生成し、それをマニフェストのクラスパスに含めることができます。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>theMainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

または、OutputDirectoryとして${project.build.directory}/classes/libを使用して、すべてのjarファイルをメインjarに統合しますが、カスタムクラスローディングコードを追加してjarをロードする必要があります。


maven-assembly-pluginは素晴らしい仕事をしてくれました。 私はmaven-dependency-pluginで数時間を過ごしてしまい、動作させることができませんでした。 主な理由は、 documentation記述されているように、構成セクションに明示的に含まれるアーティファクト項目を明示的に定義しなければならないということでした。 mvn dependency:copyように、artifactItemsは含まれていませんが、動作しない場合のための例があります。


maven-dependency-pluginを使うことができますが、問題は実行可能なJARを作成する方法でした。 これを行うには、Matthew Franglenの応答に次のような変更が必要です(btw、依存プラグインを使用すると、きれいなターゲットから起動するときに時間がかかります)。

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/target/dependency</directory>
        </resource>
    </resources>
</build>

onejarプラグインを使用して、その中にすべての依存関係jarをパッケージ化する1つの実行可能なjarファイルとして構築します。 それはこれに似た私の問題を解決しました。 アセンブリプラグインを使用すると、すべての依存関係のjarファイルがソースフォルダに展開され、jarファイルとして再パッケージ化され、コード内に同じクラス名を持つ類似の実装がすべて書き込まれました。 onejarはここでは簡単な解決策です。


maven-shade-pluginmaven-jar-plugin組み合わせることができmaven-jar-plugin

  • maven-shade-plugin 、クラスとすべての依存関係を単一のjarファイルにパックします。
  • 実行可能なjarのメインクラスを指定するようにmaven-jar-pluginを設定します( クラスパスの設定 、「Jar実行可能ファイルの作成」の章を参照)。

maven-jar-plugin POM設定例:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

最後に、以下を呼び出して実行可能なjarファイルを作成します。

mvn clean package shade:shade

あなたがコマンドラインからコマンドラインを使用したい場合。 プロジェクトパスから以下のコマンドを実行するだけです

mvnアセンブリ:アセンブリ


ここでは、Credit Karmaで使用するMavenの実行可能なjarプラグインを示します。 これは、ネストされたjarからクラスをロードできるクラスローダーでjarのjarファイルを作成します。 これにより、devとprodに同じクラスパスを持ち、すべてのクラスを単一の署名付きjarファイルに保持することができます。

https://github.com/creditkarma/maven-exec-jar-plugin

プラグインとその理由についてのブログ記事があります: https://engineering.creditkarma.com/general-engineering/new-executable-jar-plugin-available-apache-maven/ : https://engineering.creditkarma.com/general-engineering/new-executable-jar-plugin-available-apache-maven/


これが私が見つけた最良の方法です:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
      <archive>
        <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.myDomain.etc.MainClassName</mainClass>
        <classpathPrefix>dependency-jars/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>
               ${project.build.directory}/dependency-jars/
            </outputDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>

この構成では、すべての依存関係は/dependency-jars配置され/dependency-jars 。 私のアプリケーションにはMainクラスがなく、コンテキストクラスだけがありますが、私の依存関係の1つにJMXサーバを起動するMainクラス( com.myDomain.etc.MainClassName )があり、 startまたはstopパラメータを受け取ります。 だから私はこのように私のアプリケーションを起動することができました:

java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start

私はそれがすべてあなたにとって有益であるのを待つ。


これはオプションでもあります。あなたはjarファイルを構築できます

<build>
    <plugins>
        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>WordListDriver</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

すべての依存関係を1つのuber-jarにパッケージ化するには、maven-shade-pluginを使用します。 また、メインクラスを指定して実行可能なjarを構築することもできます。 maven-assemblyとmaven-jarを使用しようとした後、私はこのプラグインが自分のニーズに最も適していることを発見しました。

このプラグインは、特定のファイルの内容を上書きするのではなく、その内容をマージするので、特に便利です。 これは、JAR間で同じ名前のリソースファイルがあり、プラグインがすべてのリソースファイルをパッケージ化しようとする場合に必要です

下記の例を参照してください

      <plugins>
    <!-- This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies. -->
        <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>
                        <artifactSet>
                        <!-- signed jars-->
                            <excludes>
                                <exclude>bouncycastle:bcprov-jdk15</exclude>
                            </excludes>
                        </artifactSet>

                         <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <!-- Main class -->
                                <mainClass>com.main.MyMainClass</mainClass>
                            </transformer>
                            <!-- Use resource transformers to prevent file overwrites -->
                            <transformer 
                                 implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>properties.properties</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                                <resource>applicationContext.xml</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/cxf/cxf.extension</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                                <resource>META-INF/cxf/bus-extensions.xml</resource>
                            </transformer>
                     </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

    </plugins>

それはそうでなければなりません:

    <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                        <execution>
                                <id>unpack-dependencies</id>
                                <phase>generate-resources</phase>
                                <goals>
                                        <goal>unpack-dependencies</goal>
                                </goals>
                        </execution>
                </executions>
        </plugin>

パッケージ段階ではリソースとしてインクルードされないため、アンパックはリソース生成段階になければなりません。 きれいなパッケージを試してみてください。


ケン・リュウさんは私の意見でそういうことをしています。 Maven依存関係プラグインを使用すると、すべての依存関係を展開して、リソースとして扱うことができます。 これにより、 メインアーティファクトにそれらを含めることができます。 アセンブリプラグインを使用すると、変更が困難な副作用が発生します。私のケースでは、カスタムマニフェストエントリを追加する必要がありました。 私のポンは次のように終わった。

<project>
 ...
 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
     <execution>
      <id>unpack-dependencies</id>
      <phase>package</phase>
      <goals>
       <goal>unpack-dependencies</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
  ...
  <resources>
   <resource>
    <directory>${basedir}/target/dependency</directory>
    <targetPath>/</targetPath>
   </resource>
  </resources>
 </build>
 ...
</project>

何百万もの回答がありますので、アプリケーションにentryPointを追加する必要がない場合は、 <mainClass>は必要ありません。 たとえば、APIには必ずしもmainメソッドがない場合もあります。

mavenプラグインの設定

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

ビルドする

mvn clean compile assembly:single

確認する

ll target/
total 35100
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 maven-status/

未回答の答えを取り、それを再フォーマットすると、次のようになります。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>
    </plugins>
</build>

次に、明示的に呼び出すものではなく、ビルドの自然な部分にすることをお勧めします。 これをビルドの不可欠な部分にするには、このプラグインをpom.xml追加し、それをpackageライフサイクルイベントにバインドします。 しかし、コマンドラインから手動で実行する場合、 'assembly:assembly'を呼び出すのと同じように、これをpom.xmlに入れると、 assembly:single目標であるassembly:singleを呼び出す必要があります。

<project>
  [...]
  <build>
      <plugins>
          <plugin>
              <artifactId>maven-assembly-plugin</artifactId>
              <configuration>
                  <archive>
                      <manifest>
                          <addClasspath>true</addClasspath>
                          <mainClass>fully.qualified.MainClass</mainClass>
                      </manifest>
                  </archive>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
              </configuration>
              <executions>
                  <execution>
                      <id>make-my-jar-with-dependencies</id>
                      <phase>package</phase>
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
      [...]
      </plugins>
    [...]
  </build>
</project>

特定の依存関係をuber-jarから除外するオプションを探している人にとって、これは私のために働く解決策です:

<project...>
<dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>1.6.1</version>
            <scope>provided</scope> <=============
        </dependency>
</dependencies>
<build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>...</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

つまり、mvn-assembly-pluginの設定ではなく、依存関係のプロパティです。


私はここで最も多く投票した答えを試してみたところ、瓶を動かすことができました。 しかし、プログラムは正しく動作しませんでした。 理由は分かりません。 Eclipseから実行しようとすると、別の結果が出ますが、コマンドラインからjarファイルを実行すると、別の結果になります(プログラム固有のランタイムエラーでクラッシュします)。

私は私のプロジェクトにあまりにも多くの(Maven)依存関係があっただけで、OPと同様の要件を持っていました。 幸いにも、私のために働いた唯一の解決策は、 Eclipseを使用することでした。 非常に簡単で非常に簡単です。 これはOPに対する解決策ではありませんが、同様の要件を持っていてMavenの依存性が多い人にとっての解決策です。

1)プロジェクトフォルダ(Eclipse内)を右クリックし、 Exportを選択するだけです

2)次に、 Java - > Runnable Jar選択します

3)jarファイルの場所を選択するように求められます

4)最後に、実行するMainメソッドを持つクラスを選択Package dependencies with the Jar file選択Package dependencies with the Jar file Finishをクリックします


私はこの記事で言及したツリープラグインを比較しました。 私は2つの瓶とすべての瓶を持つディレクトリを生成しました。 私は結果を比較し、間違いなくmaven-shade-pluginが最高です。 私の課題は、jax-rsとJDBCサービスだけでなく、マージする必要のある複数のスプリングリソースがあることでした。 それらはすべて、maven-assembly-pluginと比較してshadeプラグインによって適切にマージされました。 この場合、バネは自分のリソースフォルダにコピーして手動で1回マージしない限り失敗します。 どちらのプラグインも正しい依存関係ツリーを出力します。 テスト、提供、コンパイルなどの複数のスコープがあり、両方のプラグインでスキップされました。 彼らはどちらも同じマニフェストを作成しましたが、私は変圧器を使ってシェードプラグインとライセンスを統合することができました。 もちろん、Maven-dependency-pluginでは、jarファイルが抽出されないため、これらの問題はありません。 しかし、他の人のように、適切に動作するために1つの余分なファイルを持ち運ぶ必要があると指摘しています。 ここにpom.xmlの抜粋があります

            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <includeScope>compile</includeScope>
                        <excludeTransitive>true</excludeTransitive>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-my-jar-with-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <configuration>
                <shadedArtifactAttached>false</shadedArtifactAttached>
                <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.factories</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.tooling</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
                    </transformer>
                </transformers>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

私はすべての依存関係を含んでいる実行可能な実行可能なjarファイルを作成しようとしているこれらの応答のすべてを調べましたが、どれも正しく動作しませんでした。 答えは陰影のプラグインです。非常に簡単で簡単です。

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.3</version>
      <executions>
         <!-- Run shade goal on package phase -->
        <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
             <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>path.to.MainClass</mainClass>
             </transformer>
          </transformers>
        </configuration>
          </execution>
      </executions>
    </plugin>

これが正しく動作するためには、依存関係にコンパイルまたはランタイムのスコープが必要であることに注意してください。

この例はmkyong.comから来ました


長いMavenアセンブリプラグインを使用し"already added, skipping"しています"already added, skipping"という問題の解決策を見つけることができませんでした。 今、別のプラグイン - onejar-maven-plugin 。 以下の例( mvn package build jar):

<plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.company.MainClass</mainClass>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

そのプラグインのリポジトリを追加する必要があります:

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>




executable-jar