Java の開発環境と CI 環境を構築する

先日、2023 年の抱負として Rust を学習しながら Web アプリケーションを作ると宣言をした。この時はやるべきよりやりたいを優先しようと思っていた。

kazuhe.hatenablog.com

記事を書いた数日後に現職でバックエンド開発チームへ転向できる可能性があることを聞いた。マネジメント層に対して以前からバックエンド開発に関心があることは伝えており、日々の業務でもある程度評価していただいている様でチャンスがあるとのことだった。

そのため Rust 学習計画は中断し、チャンスに備えて現職で利用されている Java を用いた Web アプリケーションを作る計画に変更した。2023 年の抱負を書いて早々に興味ドリブンで学習をする方針を変更することになったが、業務で経験できるチャンスを逃さないためにできる準備をしておこうと思う。

昨年、書籍「プロになる Java」を読んで、 JVMJDK などを含む Java 自体の基礎知識と基本的な文法を学習し、手元の PC にインストールした H2 Database とやりとりをする簡単な ToDo アプリケーションを作成している。なので、次のステップとしてもう少しマシなアプリケーションを作りながら、自分が知らないことをその都度学習することをしばらくの目標にする。

Java の開発環境を作ってみる

開発環境に対する理解は必須だと思うので、まずは環境を作成して開発の準備から始めようと思う。

まず周辺ツールのトレンドが気になったので調べてみた。

www.jetbrains.com

これは JetBrains 社が Java 開発者に対して行った調査で、Java のどのバージョンを利用しているか、何のビルドシステムを利用しているか等の調査結果が記載されている。

ツールそれぞれ良し悪しがあるのだろうが、調べているとキリがなさそうだったので、とりあえず以下の構成にした。

ちなみにエディタは VSCode を利用しようと思っている。Java 開発には IntelliJ IDEA が最も多く利用されている様で、私も書籍「プロになる Java」を読むタイミングで利用を始めたが、昔から使い慣れている VS Code の方が書きやすかったのが理由だ。

以下の VS Code 拡張機能を入れたが、初学者の私にとってはインテリセンスなど IntelliJ IDEA と比較しても遜色ない様に感じている。Web で提供されている Spring Initializr を利用しなくても VS Code 上で簡単にプロジェクトを作成できて感動した。

VS Code拡張機能などについては WEB+DB PRESS Vol.124 を参考にした。

gihyo.jp

ローカルの開発環境は Ubuntu をベースに Docker イメージを作成した。ユーザ追加など諸々を行った後に SDKMAN! CLI をインストールして、SDKMAN! で Java と Gradle をインストールしている。

# docker/workspace/Dockerfile
FROM ubuntu:22.04

ARG USER_NAME=default
ARG USER_GROUP_NAME=workspace

ARG PKG="git vim curl unzip zip sudo"

SHELL ["/bin/bash", "-c"]

RUN apt update \
  && apt install -y ${PKG} \
  && groupadd ${USER_GROUP_NAME} \
  && useradd --shell /bin/bash -m ${USER_NAME} \
  && echo %${USER_GROUP_NAME} ALL=\(ALL\) NOPASSWD:ALL > /etc/sudoers.d/${USER_GROUP_NAME} \
  && chmod 0440 /etc/sudoers.d/${USER_GROUP_NAME}

ARG JAVA_VERSION=17.0.5-ms
ARG GRADLE_VERSION=7.5

RUN su ${USER_NAME} --command \
  'curl -s "https://get.sdkman.io" | bash \
  && source "${HOME}/.sdkman/bin/sdkman-init.sh" \
  && sdk install java "${JAVA_VERSION}" \
  && sdk install gradle "${GRADLE_VERSION}"'

Docker Compose はとりあえず最低限書いた。

# docker-compose.yml
version: "3.9"

services:
  workspace:
    container_name: plantree-workspace
    env_file: .env
    build:
      context: .
      dockerfile: docker/workspace/Dockerfile
      args:
        USER_NAME: ${USER_NAME}
        USER_GROUP_NAME: ${USER_GROUP_NAME}
    tty: true
    volumes:
      - type: bind
        source: .
        target: /home/${USER_NAME}/workspace
    working_dir: /home/${USER_NAME}/workspace
    ports:
      - 8080:8080

docker compose up からの docker compose execワークスペースへ接続して、ユーザーを切り替えた後 ./gradlew build でプロジェクトをビルドできる様にした。これがベストプラクティスなのかは分からないが、他の PC でも同じ環境でビルドや実行をできる様になった。

Java アプリケーションの CI 環境を作ってみる

継続的インテグレーション(以下 CI と呼ぶ)を実施するために書籍「[改訂第3版]Jenkins実践入門―ビルド・テスト・デプロイを自動化する技術」を読んだ。

gihyo.jp

冒頭は CI の概念やメリット・デメリットなどが解説されている。これはフロントエンドにもバックエンドにも共通する知識で、すでにある程度意識して業務で実践できていた部分なのでスラスラと読んだ。

Jenkins を使って Java アプリケーションの CI を実現するために、テストやインスペクションなどで広く利用されているツールも紹介されていた。

しかし、今回はもう少しお手軽に CI を実現したかったので、Jenkins は利用せず GitHub Actions を利用することにした。以下を参考にした。

zenn.dev

そもそも Java プロジェクトのビルドはどの様なタスクで構成されているのか簡潔に説明されており、Java におけるビルドの具体的な役割イメージすることができる良い書籍だった。 また、CI の旨味なども丁寧に説明されていたので、先の Jenkins 本を買わずに無料で読めるこちらだけ読んでも充分な気がする。

ほとんど書籍そのままだが、Workflow の実行タイミングや、uses: XX のバージョンなど少しだけ変えた。

# .github/workflows/build.yml
name: Build

on:
  pull_request:
    branches:
      - "**"
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - uses: gradle/wrapper-validation-action@v1
      - name: Set up Java 17
        uses: actions/setup-java@v2
        with:
          distribution: microsoft
          java-version: 17
          cache: gradle
      - run: ./gradlew build

実際に GitHub Actions の上でビルドが成功した。取り急ぎなので必要に応じてチューニングしていこうと思う。

github.com

以上でシンプルな開発環境と CI 環境を構築できたので、ついに開発を始めていこうと思う。Java 初学者が調べながら書いた文書なので不適切な説明などあるかもしれない。