Oximeeg

年収を上げたいITエンジニア

GradleによるJavaライブラリの作成と利用

構成

以下のような sample.core に依存した sample.lib を使用した sample-gradle アプリを作成する。

─ sample-gradle
  └ sample.lib
    └ sample.core

Building Java Libraries Sample

sample-gradle-core

sample.core を作成する。

mkdir sample-gradle-core
cd sample-gradle-core
gradle init

パッケージは以下のように変更する。

> Source package (default: sample.gradle.core): com.oximeeg.sample.core

build.gradle

plugins {
    id 'java-library'
    id 'maven-publish'
}

repositories {
    mavenLocal()
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            group = 'com.oximeeg'
            artifactId = 'sample.core'
            version = '1.0.0'
            from components.java
        }
    }
}

Core.java

package com.oximeeg.sample.core;

public class Core {
    public String echo(String arg1) {
        return "CoreMethod arg1:" + arg1;
    }
}

ローカルホストに公開

  • gradle clean publishToMavenLocal

sample-gradle-lib

sample.lib を作成する。

mkdir sample-gradle-lib
cd sample-gradle-lib
gradle init

パッケージは以下のように変更する。

> Source package (default: sample.gradle.lib): com.oximeeg.sample.lib

build.gradle

plugins {
    id 'java-library'
    id 'maven-publish'
}

repositories {
    mavenLocal()
}

dependencies {
    implementation 'com.oximeeg:sample.core:1.0.0'
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            group = 'com.oximeeg'
            artifactId = 'sample.lib'
            version = '1.0.0'
            from components.java
        }
    }
}

Library.java

package com.oximeeg.sample.lib;

import com.oximeeg.sample.core.Core;

public class Library {
    public String echo() {
        return new Core().echo("Hello World");
    }
}

ローカルホストに公開

  • gradle clean publishToMavenLocal

Building Java Applications Sample

sample-gradle

アプリを作成する。

mkdir sample-gradle
cd sample-gradle
gradle init

パッケージは以下のように変更する。

> Source package (default: sample.gradle): com.oximeeg.sample.app

build.gradle

plugins {
    id 'application'
}

repositories {
    mavenLocal()
}

dependencies {
    implementation 'com.oximeeg:sample.lib:1.0.0'
}

application {
    mainClass = 'com.oximeeg.sample.app.App'
}

App.java

package com.oximeeg.sample.app;

import com.oximeeg.sample.lib.Library;

public class App {
    public String getGreeting() {
        return new Library().echo();
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}

実行

  • ビルド - gradle build
  • 実行 - gradle run

依存関係

  • 確認 - gradle app:dependencies --configuration runtimeClasspath
  runtimeClasspath - Runtime classpath of source set 'main'.
  \--- com.oximeeg:sample.lib:1.0.0
      \--- com.oximeeg:sample.core:1.0.0

推移的な依存関係

ライブラリを利用する際の注意点に 推移的な依存関係 がある。依存しているライブラリのバージョンが競合した際の解決方法も知識として知っておいた方が良い。

sample.coreを以下のように更新する。

  • build.gradle
  -   version = '1.0.0'
  +   version = '2.0.0'
  -    public String echo(String arg1) {
  -        return "CoreMethod arg1:" + arg1;
  +    public String echo(String arg1, String arg2) {
  +        return "CoreMethod arg1:" + arg1 + " arg2:" + arg2;

アプリの依存関係に core:2.0.0 を追加する。

  • build.gradle
  dependencies {
      implementation 'com.oximeeg:sample.lib:1.0.0'
      implementation 'com.oximeeg:sample.core:2.0.0'
  }

実行

  • ビルド - gradle build
  • 実行 - gradle run
Exception in thread "main" java.lang.NoSuchMethodError: 'java.lang.String com.oximeeg.sample.core.Core.echo(java.lang.String)'
        at com.oximeeg.sample.lib.Library.echo(Library.java:7)
        at com.oximeeg.sample.app.App.getGreeting(App.java:7)
        at com.oximeeg.sample.app.App.main(App.java:11)

依存関係

  • 確認 - gradle app:dependencies --configuration runtimeClasspath
  runtimeClasspath - Runtime classpath of source set 'main'.
  +--- com.oximeeg:sample.lib:1.0.0
  |    \--- com.oximeeg:sample.core:1.0.0 -> 2.0.0
  \--- com.oximeeg:sample.core:2.0.0

何が起きたのか

ビルドは成功したのに、実行時に Exception が発生した。

依存関係を見ると sample.lib の依存していた sample.core のバージョンが v2.0.0 に変更されている。

sample.libsample.corev1.0.0 を使用するつもりなのに v2.0.0 に更新されたことで echo(String arg1)echo(String arg1, String arg2) に変更されているが、echo(String arg1) を呼び出そうとした結果、NoSuchMethodError が発生した。

結局

不要な依存関係を exclude で除外したり、整合性の取れた依存関係になるようにライブラリのバージョンを調整する。