LoginSignup
3
9

More than 3 years have passed since last update.

Gradle ことはじめ (Java プロジェクトを作成して、外部ライブラリをまとめてひとつの実行可能 JAR を生成するまで)

Last updated at Posted at 2019-07-26

概要

  • 公式のチュートリアル資料等を参考に Gradle を導入する
  • Gradle で Java プロジェクトを作成する
  • 外部ライブラリを導入し、ひとつの実行可能 JAR を生成する

今回の環境

  • macOS Mojave
  • OpenJDK 11.0.2
  • Gradle 5.5.1

Gradle をインストールする

Gradle | Installation にいくつかの方法が載っている。
今回は macOS Mojave なので Homebrew でインストールした。

$ brew install gradle

Java プロジェクトを作成する

gradle init で Java プロジェクトを作成する

Building Java Applications を参考にする。

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

$ gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

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

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

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

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 1

Project name (default: gradle): my-app
Source package (default: my.app): com.example

> Task :init
Get more help with your project: https://docs.gradle.org/5.5.1/userguide/tutorial_java_projects.html

BUILD SUCCESSFUL in 42s
2 actionable tasks: 2 executed

生成されたファイル一覧

├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── App.java
    │   └── resources
    └── test
        ├── java
        │   └── com
        │       └── example
        │           └── AppTest.java
        └── resources

build.gradle

ビルドするための設定ファイルその1。


/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * User Manual available at https://docs.gradle.org/5.5.1/userguide/tutorial_java_projects.html
 */

plugins {
    // Apply the java plugin to add support for Java
    id 'java'

    // Apply the application plugin to add support for building a CLI application
    id 'application'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // This dependency is used by the application.
    implementation 'com.google.guava:guava:27.1-jre'

    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}

application {
    // Define the main class for the application
    mainClassName = 'com.example.App'
}

settings.gradle

ビルドするための設定ファイルその2。

/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/5.5.1/userguide/multi_project_builds.html
 */

rootProject.name = 'my-app'

src/main/java/com/example/App.java

生成されたサンプル用のソースコード。

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package com.example;

public class App {
    public String getGreeting() {
        return "Hello world.";
    }

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

src/test/java/com/example/AppTest.java

生成されたサンプル用のテストコード。

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package com.example;

import org.junit.Test;
import static org.junit.Assert.*;

public class AppTest {
    @Test public void testAppHasAGreeting() {
        App classUnderTest = new App();
        assertNotNull("app should have a greeting", classUnderTest.getGreeting());
    }
}

gradle tasks で実行可能なタスク一覧を確認する

gradle tasks コマンドで見ることができる。

$ gradle tasks

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Application tasks
-----------------
run - Runs this project as a JVM application

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Distribution tasks
------------------
assembleDist - Assembles the main distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'my-app'.
components - Displays the components produced by root project 'my-app'. [incubating]
dependencies - Displays all dependencies declared in root project 'my-app'.
dependencyInsight - Displays the insight into a specific dependency in root project 'my-app'.
dependentComponents - Displays the dependent components of components in root project 'my-app'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'my-app'. [incubating]
projects - Displays the sub-projects of root project 'my-app'.
properties - Displays the properties of root project 'my-app'.
tasks - Displays the tasks runnable from root project 'my-app'.

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed

gradle test でテストを実行する

gradle test コマンドでテストを実行できる。

$ gradle test

BUILD SUCCESSFUL in 4s
3 actionable tasks: 2 executed, 1 up-to-date

gradle jar で JAR ファイルを作成する

gradle jar コマンドで JAR ファイルを生成できる。

$ gradle jar

BUILD SUCCESSFUL in 872ms
2 actionable tasks: 2 executed

Java アプリケーションを実行する

クラスパスに JAR ファイルのパスを指定して java コマンドで実行する。

$ java -classpath build/libs/my-app.jar com.example.App
Hello world.

実行可能な JAR ファイルを作成する

JARマニフェスト属性を指定する

JAR マニフェスト属性を build.gradle で指定する。
今回は以下の内容を追加している。

jar {
    manifest {
        attributes 'Main-Class': 'com.example.App'
    }
}

JARファイルの仕様

スタンドアロン・アプリケーションに対して定義する属性。この属性は、Javaランタイムからjava -jar x.jarによって直接呼び出された実行可能jarファイルに含まれる、スタンドアロン・アプリケーションによって使われる。
Main-Class: この属性の値は、起動時に起動ツールによってロードされるメイン・アプリケーション・クラスのクラス名である。 この値には、クラス名に拡張子.classが付いていてはならない。

build.gradle を整理

build.gradle から不要なコメント等を削除して整理する。

plugins {
    id 'java'
    id 'application'
}

repositories {
    jcenter()
}

dependencies {
    testImplementation 'junit:junit:4.12'
}

application {
    mainClassName = 'com.example.App'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.example.App'
    }
}

実行可能な JAR ファイルを実行する

gradle jar で JAR ファイルを生成する。

$ gradle jar

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

クラス名を指定しなくても java -jar コマンドで Java アプリケーションを実行できるようになった。

$ java -jar build/libs/my-app.jar
Hello world.

外部ライブラリを導入する

ここでは JSON を操作できる外部ライブラリ Jackson Core を導入する。

build.gradle に外部ライブラリを追加する

Maven Repository: com.fasterxml.jackson.core » jackson-core » 2.9.9 には Gradle 用の設定情報が載っている。


compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.9'

ただし、 compile は現在非推奨となっている。

The Java Plugin

compile(Deprecated)
Compile time dependencies. Superseded by implementation.

そのため、依存ライブラリは implementaion で記述する。
フォーマットは group name version をコロンで区切ったものになる。


implementation 'com.fasterxml.jackson.core:jackson-core:2.9.9'

build.gradle の全体はこのようになる。


plugins {
    id 'java'
    id 'application'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.fasterxml.jackson.core:jackson-core:2.9.9'
    testImplementation 'junit:junit:4.12'
}

application {
    mainClassName = 'com.example.App'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.example.App'
    }
}

Java ソースコードを修正する

Jackson Core を使用するように src/main/java/com/example/App.java を修正する。

package com.example;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;

public class App {
    public String getGreeting() {
        try {
            Writer out = new StringWriter();
            JsonFactory factory = new JsonFactory();
            JsonGenerator generator = factory.createGenerator(out);
            generator.writeStartObject();
            generator.writeStringField("message", "Hello world.");
            generator.writeEndObject();
            generator.flush();
            generator.close();
            return out.toString();
        } catch (IOException e) {
            return e.toString();
        }
    }

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

gradle run でプログラムを実行する

gradle run コマンドで Java アプリケーションを実行することができる。

$ gradle run

> Task :run
{"message":"Hello world."}

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

外部ライブラリをまとめてひとつの JAR ファイルにするプラグインを導入する

Shadow Plugin を導入する

Shadow Plugin を導入することで、外部ライブラリとソースコードをひとつの JAR にまとめることができる。

Gradle Shadow Plugin - Introduction

Shadow is a Gradle plugin for combining dependency classes and resources with a project's into a single output Jar. The combined Jar is often referred to a fat-jar or uber-jar. Shadow utilizes JarInputStream and JarOutputStream to efficiently process dependent libraries into the output jar without incurring the I/O overhead of expanding the jars to disk.

build.gradle の plugins に以下を追加する。


id 'com.github.johnrengelman.shadow' version '5.1.0'

build.gradle の全体はこのようになる。


plugins {
    id 'java'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '5.1.0'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.fasterxml.jackson.core:jackson-core:2.9.9'
    testImplementation 'junit:junit:4.12'
}

application {
    mainClassName = 'com.example.App'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.example.App'
    }
}

Shadow Plugin のタスクを確認する

gradle tasks コマンドで Shadow Plugin のタスクが増えていることを確認できる。

$ gradle tasks | grep -i shadow
runShadow - Runs this project as a JVM application using the shadow jar
startShadowScripts - Creates OS specific scripts to run the project as a JVM application using the shadow jar
assembleShadowDist - Assembles the shadow distributions
installShadowDist - Installs the project as a distribution as-is.
shadowDistTar - Bundles the project as a distribution.
shadowDistZip - Bundles the project as a distribution.
Shadow tasks
shadowJar - Create a combined JAR of project and runtime dependencies

gradle shadowJar で JAR ファイルを作成する

gradle shadowJar コマンドで JAR ファイルを生成できる。

$ gradle shadowJar

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

Java アプリケーションを実行する

java -jar コマンドで JAR ファイルを指定して実行する。
外部ライブラリもこのひとつの JAR ファイルにまとめられている。

$ java -jar build/libs/my-app-all.jar 
{"message":"Hello world."}

参考資料

3
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
9