SpringBoot 2.4 to 2.5 メモ

# 概要

springboot 2.5がGAとなりました
[Release Note](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes)を参考に2.4系から2.5系への移行方法をまとめてみます
自分が移行するときに関係のあるものや興味があるものが中心となりますがご容赦ください🙇‍♂️

過去の記事はこちら

https://qiita.com/rhirabay/items/6573d69c3c7ec1dc8be5

https://qiita.com/rhirabay/items/22b66e413b06476c0fd3

# Minimum Requirements Changes

対応するGradleのバージョンが`6.8以降`となりました。
投稿時点の最新バージョン`7.0.2`へのアップデートコマンドは以下のようになります。

```bash
./gradlew wrapper --gradle-version 7.0.2
```

# Gradle Default jar and war Tasks

`jar`, `war`タスクがデフォルトで有効になります。

そして、bootJarの生成したjarファイルと衝突しないよう`jar`, `war`タスクで生成されるファイルに「-plain」が付与されます。

以下Tipsです

## `-plain`を取り除く

`archiveClassifier`で空文字を指定してあげればOK

※Release noteでは`classifier`が紹介されていますが、非推奨となっていました…

```groovy:build.gradle
archivesBaseName = 'sample'

bootJar {
    archiveClassifier = 'boot'
}

jar {
    archiveClassifier = ''
}
```

このような設定だと、以下のように２つのjarファイルが生成されます。

```
build
...
├── libs
│   ├── sample-boot.jar
│   └── sample.jar
...
```

## `enabled`で無効化する

`enabled = false`を設定するとjarの生成を無効化することができます

```groovy:build.gradle
jar {
    enabled = false
}
```

# Environment Variable Prefixes

環境変数にprefixを付与することができるようになるようです。

prefixを付与するにはmainクラスを以下のように記述します。

```java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.setEnvironmentPrefix("prefix");
        application.run(args);
    }
}
```

この状態で、以下のようにすると`server.port`を変更してアプリケーションを起動できます

```
PREFIX_SERVER_PORT=8081 ./gradlew bootRun
```

> 当然`SERVER_PORT`では変更ができなくなるので、既存システムにこの変更を入れるメリットはないかなぁ

# OpenMetrics for Prometheus

`/actuator/prometheus`を叩くときにHeaderを設定することでOpenMetrics形式のレスポンスが返るようになりました。

デフォルトはprometheus形式で、Acceptヘッダーに`application/openmetrics-text`を載せるとOpenMetrics形式になります。

```bash
curl http://localhost:8080/actuator/prometheus -H 'Accept: application/openmetrics-text'
```

# Metrics for Spring Data Repositories

Spring Data repositoriesのメトリクスがデフォルトで収集されるようになります！✨

以下のJPAだと

```java
public interface UserRepository extends CrudRepository<User, String> {
    Optional<User> findById(String id);
}
```

こんなメトリクスが取得できます。

```prometheus
# HELP spring_data_repository_invocations_seconds_max
# TYPE spring_data_repository_invocations_seconds_max gauge
spring_data_repository_invocations_seconds_max{exception="None",method="findById",repository="UserRepository",state="SUCCESS",} 0.03175074
# HELP spring_data_repository_invocations_seconds
# TYPE spring_data_repository_invocations_seconds summary
spring_data_repository_invocations_seconds_count{exception="None",method="findById",repository="UserRepository",state="SUCCESS",} 1.0
spring_data_repository_invocations_seconds_sum{exception="None",method="findById",repository="UserRepository",state="SUCCESS",} 0.03175074
```

`application.yml`で以下の設定が可能。

```yaml:application.yml
management:
  endpoints:
    web:
      exposure:
        include: "prometheus"
  metrics:
    data:
      repository:
        autotime:
          # 自動でメトリクスを収集するかどうか？
          # falseを指定すると個別に「@Timed」アノテーションの付与が必要
          enabled: true
          # パーセンタイルも取得する
          percentiles: 0.5,0.99
        # メトリクス名を指定する
        metric-name: "spring.data.repository.invocations"
```

## 補足： `@Timed`アノテーション

`@Timed`アノテーションを使用すると、任意のメソッドでメトリクス計測ができる…！

使い方は

1. spring-boot-starter-aopを依存に加えて
1. `TimedAspect`をBean登録し
1. メトリクスを取りたいメソッドに`@Timed`を付与する

だけ！便利すぎ！

```groovy:build.gradle
dependencies {
    ...
    implementation 'org.springframework.boot:spring-boot-starter-aop'
    ...
}
```

```java
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApplicationConfiguration {
    @Bean
    public TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
    }
}
```

```java:MybatisのMapperメソッド
import io.micrometer.core.annotation.Timed;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.Optional;

@Mapper
public interface UserRepository {
    @Timed(value = "sql.time")
    @Select("SELECT * FROM USER WHERE id = #{id}")
    Optional<User> findById(String id);
}
```

こんな感じでJPAを使用していなくても、例えばMybatisのMapperの実行時間をメトリクスに落とすことができます

参考：

https://micrometer.io/docs/concepts#_the_timed_annotation

# Java 16 / Gradle 7 Support

Java 16とGradle 7がそれぞれサポートされています。

# その他参考リンク

▼Spring Boot 2.5 Configuration Changelog

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Configuration-Changelog

▼非推奨なpropertyを使用していたらビルドを失敗させる

https://qiita.com/rhirabay/items/bd85b8f2582dcbdd4819