Spring Initializr不徹底解剖

# 話の経緯

2年ほど前にSpringの教材を作った（当時Spring Boot 2.2）のですが、

- 2.3出た→validationが分離されたので[^1]「テキスト通り」できなくなる→2.2系選んでプロジェクト作ってと修正[^2]
- 2.5のMが出たぐらい？→2.2系が選べなくなった→最後に表示されるURLで2.2系に書き換えてとテキスト修正
- 今年（2021年）の8月→2.2にするとプロジェクト作れなくなった→(´・ω・`)

[^1]: https://qiita.com/rhirabay/items/22b66e413b06476c0fd3#validation-starter-no-longer-included-in-web-starters
[^2]: 「最新バージョンにアップデート」すべきですがいろいろやることがあるので即「全面的な修正」ができないもので

てことでいい加減全面改訂して2.5にするかという流れになっているのですが、一方で「Spring Initializrどんどん新しくなっちゃうしバージョン固定の意味で自鯖立てるのがよくね？」という議論も（私が関わってないところで）されており、「やってみたけどエラー出るから助けて」と言われてSpring Initializrについて調べてみたのがこの記事の元ネタです。

# Spring Initializrの仕組み

## start.spring.io

みんな大好きSpring Initializr。アクセスすると「Webページ」が表示されてポチポチ操作するとプロジェクト（ディレクトリをzipで固めたもの）が作成できます。
https://start.spring.io/

上記のサイトを構成するコードはgithubに公開されており「オレオレSpring Initilizrを立てる」ことができます。
https://github.com/spring-io/start.spring.io

しかしSpring Initializrの本体はこれとは別にあります。
画面などただの飾りです。偉い人にはそれがわからんのです。ですね(笑)

## initializr

というわけで本体。こちらはWeb「ページ」はなく、コマンドラインプログラムやらSTSなどのIDEやらからのアクセスに対して応答を返す「API」です。
https://github.com/spring-io/initializr

このライブラリ（モジュールって言った方がいいのかな？）を使って独自インスタンスを作る方法は以下に説明されています。
https://github.com/spring-io/initializr/blob/v0.10.3/initializr-docs/src/main/asciidoc/configuration-guide.adoc

- webを依存に入れてSpringBootプロジェクトを作る。
- initilizr-bomをdependencyManagementに入れたうえでinitializr-webとinitializr-generator-springを依存に入れる

書かれてるのそのまんまになりますがこんな感じですね。

```xml:pom.xml抜粋
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.spring.initializr</groupId>
            <artifactId>initializr-bom</artifactId>
            <version>0.10.3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>io.spring.initializr</groupId>
        <artifactId>initializr-generator-spring</artifactId>
    </dependency>
    <dependency>
        <groupId>io.spring.initializr</groupId>
        <artifactId>initializr-web</artifactId>
    </dependency>
</dependencies>
```

なお、タイトルにある「不徹底解剖」の意味ですが、initializr-generator-spring（というかさらにコア部分であるinitializr-generator）がどう動いているのか読み解いて解説を書こうと思ったのですけど、責務分割全開の構成に途中で挫折しました(´・ω・`)

# オレオレインスタンスの立て方

## application.ymlの用意

さて、Spring Initializrの嬉しさは依存関係をポチポチ設定したらpom.xmlを作ってくれるところだと思っているのですが、残念ながらここは手動です。まあ「自動的に」やられるとバージョン固定のオレオレインスタンスが立てられませんが。

依存関係候補の記述方法はここら辺に紹介されていますが、
https://github.com/spring-io/initializr/blob/v0.10.3/initializr-docs/src/main/asciidoc/configuration-guide.adoc#configuring-dependencies

「動いているもの」を持ってくるのが早いです。
https://github.com/spring-io/start.spring.io/blob/main/start-site/src/main/resources/application.yml

本家ではspring.ioから「最新のSpringBootバージョン」を取得してメタデータが書き換えられるようにしていますがオレオレインスタンスではバージョンを固定します。

```yaml:application.yml抜粋
  bootVersions:
    - name: 2.5.4
      id: 2.5.4
      default: true
```

このようにして作成したオレオレインスタンス（SpringBootプロジェクト）を動かし、STSで新しいプロジェクトを作るときにService URLとしてhttp://localhost:8080を指定してちゃんとプロジェクトが作れることを確認します。

ちなみに冒頭の「2.2指定でプロジェクト作れなくなった(´・ω・`)」原因（？）は以下のようにapplication.ymlで最低バージョンが2.3に変更されたためです。どうしても2.2がいいのなら2.2が削除される手前のコミットを拾ってくることになりますね。

```yaml:application.yml抜粋
    platform:
      compatibility-range: "2.3.0.RELEASE"
      v1-format-compatibility-range: "[2.0.0.RELEASE,2.4.0-M1)"
      v2-format-compatibility-range: "2.4.0-M1"
```

## Herokuへデプロイ

作ったオレオレインスタンスはHerokuにpushすれば普通に動きます。データベースとかは何も要りません。
https://devcenter.heroku.com/ja/articles/deploying-spring-boot-apps-to-heroku

以上、Spring Initializrの仕組みとオレオレインスタンスの立て方でした。