Spring Bootを使ったシンJAR

Spring Bootを備えたシンJAR

1. 前書き

このチュートリアルでは、how to build a Spring Boot project into a thin JAR file, using the spring-boot-thin-launcher project.を見ていきます。

Spring Bootは、その「太い」JARデプロイメントで知られています。単一の実行可能なアーティファクトには、アプリケーションコードとそのすべての依存関係の両方が含まれます。

ブートは、マイクロサービスの開発にも広く使用されています。 多くのアーティファクトに何度も同じ依存関係を含めることは、リソースの重要な浪費になる可能性があるため、これは「ファットJAR」アプローチと矛盾する場合があります。

2. 前提条件

まず、もちろん、Spring Bootプロジェクトが必要です。 この記事では、Mavenビルドと、最も一般的な構成でのGradleビルドについて説明します。

すべてのビルドシステムとビルド構成を網羅することは不可能ですが、特定のセットアップに適用できるはずの一般原則を十分に理解できることを願っています。

2.1. Mavenプロジェクト

MavenでビルドされたBootプロジェクトでは、Spring Boot Mavenプラグインをプロジェクトのpom.xmlファイル、その親、またはその祖先の1つで構成する必要があります。


    org.springframework.boot
    spring-boot-maven-plugin

ここでは、プラグインのバージョン2.0.2.RELEASEを参照しています。これは、執筆時点で最新のものです。 Spring Bootの依存関係のバージョンは、通常、参照プロジェクトのように、BOMを使用するか、親POMから継承することによって決定されます。


    org.springframework.boot
    spring-boot-starter-parent
    2.0.1.RELEASE
    

2.2. Gradleプロジェクト

GradleでビルドされたBootプロジェクトには、BootGradleプラグインがあります。

buildscript {
    ext {
        springBootPlugin = 'org.springframework.boot:spring-boot-gradle-plugin'
        springBootVersion = '2.0.1.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("${springBootPlugin}:${springBootVersion}")
    }
}

// elided

apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

springBoot {
    mainClassName = 'org.example.DemoApplication'
}

この記事では、Boot2.x以降のプロジェクトのみを検討することに注意してください。 Thin Launcherは以前のバージョンもサポートしていますが、簡単にするために省略しているわずかに異なるGradle構成が必要です。 詳細については、プロジェクトのホームページをご覧ください。

3. シンJARを作成する方法は?

Spring Boot Thin Launcherは、アーカイブ自体にバンドルされているファイルからアーティファクトの依存関係を読み取り、Mavenリポジトリからダウンロードして、最終的にアプリケーションのメインクラスを起動する小さなライブラリです。

したがって、when we build a project with the library, we get a JAR file with our code, a file enumerating its dependencies, and the main class from the library that performs the above tasks.

もちろん、物事は私たちの簡単な説明よりも少し微妙です。いくつかのトピックについては、この記事の後半で詳しく説明します。

4. 基本的な使い方

次に、通常のSpringBootアプリケーションから「薄い」JARを構築する方法を見てみましょう。

シンランチャーを制御するオプションの追加コマンドライン引数を使用して、通常のjava -jar <my-app-1.0.jar>,でアプリケーションを起動します。 次のセクションでそれらのいくつかを見ていきます。プロジェクトのホームページには完全なリストが含まれています。

4.1. Mavenプロジェクト

Mavenプロジェクトでは、カスタムシンレイアウトへの依存関係を含めるために、ブートプラグインの宣言(セクション2.1を参照)を変更する必要があります。


    org.springframework.boot
    spring-boot-maven-plugin
    
        
        
            org.springframework.boot.experimental
            spring-boot-thin-layout
            1.0.11.RELEASE
        
    

launcherは、Mavenが生成されたJARのMETA-INF/mavenディレクトリに格納するpom.xmlファイルから依存関係を読み取ります。

ビルドは通常どおりに実行します。たとえば、mvn installを使用します。

シンビルドとファットビルドの両方を作成できるようにする場合(たとえば、複数のモジュールを含むプロジェクトで)、専用のMavenプロファイルでカスタムレイアウトを宣言できます。

4.2. Mavenと依存関係:thin.properties

We can also have Maven generate a thin.properties file in addition to pom.xml.その場合、ファイルには推移的な依存関係を含む依存関係の完全なリストが含まれ、ランチャーはpom.xmlよりも依存関係を優先します。

そのためのmojo(プラグイン)はspring-boot-thin-maven-plugin:properties,であり、デフォルトではthin.propertiesファイルをsrc/main/resources/META-INFで出力しますが、その場所はthin.outputプロパティで指定できます。

$ mvn org.springframework.boot.experimental:spring-boot-thin-maven-plugin:properties -Dthin.output=.

デフォルトのディレクトリを維持している場合でも、目標を成功させるには出力ディレクトリが存在する必要があることに注意してください。

4.3. Gradleプロジェクト

代わりに、Gradleプロジェクトでは、専用のプラグインを追加します。

buildscript {
    ext {
        //...
        thinPlugin = 'org.springframework.boot.experimental:spring-boot-thin-gradle-plugin'
        thinVersion = '1.0.11.RELEASE'
    }
    //...
    dependencies {
        //...
        classpath("${thinPlugin}:${thinVersion}")
    }
}

//elided

apply plugin: 'maven'
apply plugin: 'org.springframework.boot.experimental.thin-launcher'

シンビルドを取得するために、GradleにthinJarタスクを実行するように指示します。

~/projects/example/spring-boot-gradle $ ./gradlew thinJar

4.4. Gradleと依存関係:pom.xml

前のセクションのコード例では、Thin Launcherに加えてMavenプラグイン(および前提条件のセクションですでに見たBoot and Dependency Managementプラグイン)を宣言しました。

これは、前に見たMavenの場合と同様に、アーティファクトにはアプリケーションの依存関係を列挙するpom.xmlファイルが含まれ、それを利用するためです。 pom.xmlファイルは、thinPomと呼ばれるタスクによって生成されます。これは、jarタスクの暗黙的な依存関係です。

We can customize the generated pom.xml file with a dedicated task.ここでは、シンプラグインがすでに自動的に実行していることを複製します。

task createPom {
    def basePath = 'build/resources/main/META-INF/maven'
    doLast {
        pom {
            withXml(dependencyManagement.pomConfigurer)
        }.writeTo("${basePath}/${project.group}/${project.name}/pom.xml")
    }
}

カスタムpom.xmlファイルを使用するには、上記のタスクをjarタスクの依存関係に追加します。

bootJar.dependsOn = [createPom]

4.5. Gradleと依存関係:thin.properties

以前にMavenで行ったようにWe can also have Gradle generate a thin.properties file rather than pom.xml,

thin.propertiesファイルを生成するタスクはthinProperties,と呼ばれ、デフォルトでは使用されません。 jarタスクの依存関係として追加できます。

bootJar.dependsOn = [thinProperties]

5. 依存関係の保存

シンジャーの重要なポイントは、アプリケーションに依存関係がバンドルされないようにすることです。 ただし、依存関係が魔法のように消えることはなく、単に別の場所に保存されます。

特に、Thin LauncherはMavenインフラストラクチャを使用して依存関係を解決します。

  1. ローカルのMavenリポジトリをチェックします。デフォルトでは~/.m2/repositoryにありますが、他の場所に移動できます。

  2. 次に、Maven Central(または他の設定済みリポジトリ)から不足している依存関係をダウンロードします。

  3. 最後に、ローカルリポジトリにキャッシュするため、次回アプリケーションを実行するときに再度ダウンロードする必要はありません。

もちろん、the download phase is the slow and error-prone part of the process,は、インターネットを介したMaven Centralへのアクセス、またはローカルプロキシへのアクセスが必要であり、これらが一般的に信頼できないことは誰もが知っています。

幸いなことに、アプリケーションと一緒に依存関係をデプロイするさまざまな方法があります。たとえば、クラウドデプロイメント用に事前にパッケージ化されたコンテナなどです。

5.1. ウォームアップのためのアプリケーションの実行

依存関係をキャッシュする最も簡単な方法は、ターゲット環境でアプリケーションのウォームアップを実行することです。 前に見たように、これにより依存関係がダウンロードされ、ローカルのMavenリポジトリにキャッシュされます。 複数のアプリを実行すると、リポジトリには重複することなくすべての依存関係が含まれることになります。

アプリケーションを実行すると望ましくない副作用が発生する可能性があるため、we can also perform a “dry run” that only resolves and downloads the dependencies without running any user code:

$ java -Dthin.dryrun=true -jar my-app-1.0.jar

Spring Bootの規則に従って、アプリケーションへの–thin.dryrunコマンドライン引数またはTHIN_DRYRUNシステムプロパティを使用して、-Dthin.dryrunプロパティを設定できることに注意してください。 false以外の値は、ドライランを実行するようにシンランチャーに指示します。

5.2. ビルド中の依存関係のパッケージ化

別のオプションは、ビルド時に依存関係をJARにバンドルせずに収集することです。 その後、展開手順の一部として、それらをターゲット環境にコピーできます。

ターゲット環境でアプリケーションを実行する必要がないため、これは一般的に簡単です。 ただし、複数のアプリケーションをデプロイする場合は、手動またはスクリプトを使用して、それらの依存関係をマージする必要があります。

MavenおよびGradle用のシンプラグインがビルド中に依存関係をパッケージ化する形式は、Mavenローカルリポジトリと同じです。

root/
    repository/
        com/
        net/
        org/
        ...

実際、Thin Launcherを使用するアプリケーションは、実行時にthin.rootプロパティを使用してそのようなディレクトリ(ローカルのMavenリポジトリを含む)を指すことができます。

$ java -jar my-app-1.0.jar --thin.root=my-app/deps

また、複数のディレクトリをコピーして安全にマージすることもできます。これにより、必要な依存関係をすべて備えたMavenリポジトリを取得できます。

5.3. Mavenで依存関係をパッケージ化する

Mavenに依存関係をパッケージ化させるには、spring-boot-thin-maven-plugin.resolveゴールを使用します。pom.xml:で手動または自動で呼び出すことができます。


    org.springframework.boot.experimental
    spring-boot-thin-maven-plugin
    ${thin.version}
    
        
        
        resolve
        
            resolve
        
        false
        
    

プロジェクトをビルドすると、前のセクションで説明した構造のディレクトリtarget/thin/root/が見つかります。

5.4. Gradleを使用した依存関係のパッケージ化

代わりに、thin-launcherプラグインでGradleを使用している場合は、thinResolveタスクを使用できます。 このタスクは、前のセクションのMavenプラグインと同様に、アプリケーションとその依存関係をbuild/thin/root/ディレクトリに保存します。

$ gradlew thinResolve

執筆時点で、thin-launcherプラグインには、thin.propertiesが使用されている場合に依存関係を保存できないバグがあります:https://github.com/dsyer/spring-boot-thin-launcher/issues/53

6. 結論と参考資料

この記事では、薄いjarファイルの作成方法について説明しました。 また、Mavenインフラストラクチャを使用して依存関係をダウンロードして保存する方法も確認しました。

シンランチャーのhomepageには、Herokuへのクラウド展開などのシナリオに関するHOW-TOガイドと、サポートされているコマンドライン引数の完全なリストがいくつかあります。

すべてのMavenサンプルとコードスニペットの実装は、the GitHub projectにあります– Mavenプロジェクトとして、そのままインポートして実行するのは簡単です。

同様に、すべてのGradleの例はthis GitHub projectを参照しています。