【Gradle × Java】ライブラリの作り方

独自のライブラリの作り方をご紹介します!

ビルドツールはGradleを前提にまとめます。

ひらべー
ひらべー

この記事は、こんな人にオススメ!

・Javaのライブラリを作りたい

・SpringBootのコンポーネントをライブラリで提供したい

Javaライブラリの作り方

まずはピュアなJavaライブラリの作り方です。

プロジェクト作成

gradle initコマンドでプロジェクトを作成します。

ポイント
・「type of project」は「library」を選択する
・他は現場の開発ルールや言語選定に合わせて選べばOK!
$ gradle init
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 3

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no
Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4] 4

Project name (default: java-library-sample):
Source package (default: java.library.sample):

> Task :init
Get more help with your project: https://docs.gradle.org/7.6/samples/sample_building_java_libraries.html

BUILD SUCCESSFUL in 54s
2 actionable tasks: 2 executed

これでプロジェクトの雛形ができあがり!

通常のアプリケーション用のプロジェクトとの違いだけ押さえておくと、javaプラグインの代わりにjava-libraryプラグインを使うことです。

逆にこの差分さえ押さえておけば、既存のプロジェクトをコピペしてライブラリを作ったり https://start.spring.io/ で生成したプロジェクトからライブラリを作ったりもできます!

maven repositoryへのアップロード設定

ライブラリのアップロード先がどこなのか(AWSだとCode ArtifatとかGCPだとArtifact Registryとか)で変わるので、ここではローカルのmaven repositoryへアップロードできるようにしてみます。

plugins {
	id 'java-library'
  // uploadに必要なプラグイン
	id 'maven-publish'
}

...

// アップロードに必要な設定
publishing {
	publications {
		maven(MavenPublication) {
			groupId = 'java.library.sample'
			artifactId = 'java-library-sample'
			version = '1.0.0'

			from components.java
		}
	}
}

ライブラリで提供するクラスを作成

ここでは足し算をしてくれるMathUtilsクラスを実装してみます。

※ライブラリを作る上でのポイントはないので、単純にどんなクラスをライブラリで提供したいかだけ考えて実装すればOKです!

public class MathUtils {
    public static int plus(int n1, int n2) {
        return n1 + n2;
    }
}

Maven Repositoryへアップロード

ここまでできたらmaven repositoryへアップロードをしましょう!

以下のコマンドを実行すればOKです!

$ ./gradlew publish

# ローカルへのアップロードの場合
# $ ./gradlew publishToMavenLocal

この記事ではローカルリポジトリを利用するので、publishToMavenLocalの方を実行します。

ライブラリ利用

最後にライブラリの利用側の設定です!

ポイント
・「repositories」にライブラリをアップロードしたリポジトリを追加する
・「dependencies」に利用するライブラリを追加する
repositories {
	mavenCentral()
  // この記事ではローカルリポジトリ利用なので「mavenLocal」を追加
	mavenLocal()
}

dependencies {
  ...
  // publishingで指定した「groupId」 「artifactId」「version」と対応
	implementation 'java.library.sample:java-library-sample:1.0.0'
}

apiとimplementationの違い

ここまででライブラリを作りことはできるようになったので、ライブラリを作る上で知っておくべきことを1つ紹介します。

それがapiimplementaionの違いで、どちらもライブラリの依存を定義するものなのですが、利用側に依存が伝播するかしないかの違いがあります。

ポイント
・「implementation」:依存は伝播しない
・「api」:依存が伝播する

Apacheのhttpclient5を利用するライブラリを提供する例で解説していきます。

implementation

ライブラリ側に以下のように依存を追加し、httpclientをカスタマイズする関数を実装しています。

dependencies {
	implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1'
}
public class HttpClientCustomizer {
    public static HttpClient customize(HttpClientBuilder builder) {
        // カスタマイズ実装(本題ではないので省略)
        return builder.build();
    }
}

このライブラリを使おうとするとimplementationでは以下のようなdependenciesになります。

dependencies {
	implementation 'java.library.sample:java-library-sample:1.0.0'
  // 「java-library-sample」の利用に必要なライブラリを追加
	implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1'
}

このように、独自ライブラリの利用に必要なライブラリを明示的に追加しなければならないということです。
これはちょっと不便ですよね。。。

依存を追加しないと当然クラスを読み込めません。

api

今後はapiで依存を追加してみます。(クラスは同じ)

dependencies {
	api 'org.apache.httpcomponents.client5:httpclient5:5.2.1'
}

このようにライブラリを定義すると、利用者側はhttpclient5の依存を追加することなく実装をすることができます!

dependencies {
	implementation 'java.library.sample:java-library-sample:1.0.0'
}

なんでもかんでもapiで定義するのもちょっと違うと思うので、「『引数』『戻り値』で外部ライブラリを利用する場合はapiを使う」と把握しておけば良いと思います!

SpringBootライブラリの作り方

ライブラリはライブラリでも、SpringBootのBeanの登録までしてくれるライブラリを提供したい場合の実装方法を紹介します。

以下のクラスをBean登録して提供したいとします。

public class MathUtils {
    public int plus(int n1, int n2) {
        return n1 + n2;
    }
}

通常のライブラリを提供する場合に比べ、SpringBootライブラリを提供する場合には追加でやるべきことが2つあります。

・@ConfigurationクラスでBean登録する
・@Confirutaionクラスを「org.springframework.boot.autoconfigure.AutoConfiguration.imports」に登録する

まずは@ConfirurationクラスでBean登録をします。

@Configuration
public class MathUtilsAutoConfiguration {
    @Bean
    public MathUtils mathUtils() {
        return new MathUtils();
    }
}

次にConfigurationクラス(例でいうMathUtilsAutoConfiguration)をresources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsに記載します。

hirabay.library.springboot.MathUtilsAutoConfiguration

※パッケージ部分はクラスがあるパッケージに置き換えてください。

これ以外は、通常のライブラリと同じです!

Repositoryを使えない場合

Maven RepositoryやCode Artifact、Artifact Registry等を利用できない場合、jarファイルを直接生成・配置すると言う方法もあります。

jarファイルの生成は、gradleのjarジョブで実行します。

./gradlew jar

jarファイルの配置は、任意のディレクトリでよく、例えばプロジェクトルート配下のlibsというディレクトに配置する場合、以下のようにdependenciesを定義すれば良いです。

dependencies {
  ...
	implementation files("${project.rootDir}/libs/<jarファイル名>")
}

publishでエラーになる場合

> Invalid publication 'maven':
    - Publication only contains dependencies and/or constraints without a version. You need to add minimal version information, publish resolved versions (https://docs.gradle.org/7.6/userguide/publishing_maven.html#publishing_maven:resolved_dependencies) or reference a platform (https://docs.gradle.org/7.6/userguide/platforms.html)

publishを実行すると上記のようなエラーになることがあります。

このエラーが出た場合は、publicationversionMappingの設定を追加しましょう。

publishing {
	publications {
		maven(MavenPublication) {
      ...

			// dependency-managementで依存のversion解決をさせたい場合は必須
			versionMapping {
				usage('java-api') {
					fromResolutionOf('runtimeClasspath')
				}
				usage('java-runtime') {
					fromResolutionResult()
				}
			}
		}
	}
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です